@nota/nativescript-webview-ext
Version:
Extended WebView for NativeScript which adds 'x-local' scheme for local-files. events between WebView and native-layer, javascript execution, injecting CSS and JS-files.
440 lines • 57.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("tns-core-modules/file-system");
var nativescript_webview_bridge_loader_1 = require("./nativescript-webview-bridge-loader");
var webview_ext_common_1 = require("./webview-ext-common");
var WKNavigationDelegateImpl = (function (_super) {
__extends(WKNavigationDelegateImpl, _super);
function WKNavigationDelegateImpl() {
return _super !== null && _super.apply(this, arguments) || this;
}
WKNavigationDelegateImpl.initWithOwner = function (owner) {
var handler = WKNavigationDelegateImpl.new();
handler.owner = owner;
return handler;
};
WKNavigationDelegateImpl.prototype.webViewDecidePolicyForNavigationActionDecisionHandler = function (webView, navigationAction, decisionHandler) {
var owner = this.owner.get();
if (!owner) {
decisionHandler(0);
return;
}
var request = navigationAction.request;
var httpMethod = request.HTTPMethod;
var url = request.URL && request.URL.absoluteString;
owner.writeTrace("webViewDecidePolicyForNavigationActionDecisionHandler: \"" + url + "\"");
if (!url) {
return;
}
var navType = "other";
switch (navigationAction.navigationType) {
case 0: {
navType = "linkClicked";
break;
}
case 1: {
navType = "formSubmitted";
break;
}
case 2: {
navType = "backForward";
break;
}
case 3: {
navType = "reload";
break;
}
case 4: {
navType = "formResubmitted";
break;
}
default: {
navType = "other";
break;
}
}
var shouldOverrideUrlLoading = owner._onShouldOverrideUrlLoading(url, httpMethod, navType);
if (shouldOverrideUrlLoading === true) {
owner.writeTrace("WKNavigationDelegateClass.webViewDecidePolicyForNavigationActionDecisionHandler(\"" + url + "\", \"" + navigationAction.navigationType + "\") -> method:" + httpMethod + " \"" + navType + "\" -> cancel");
decisionHandler(0);
return;
}
decisionHandler(1);
owner.writeTrace("WKNavigationDelegateClass.webViewDecidePolicyForNavigationActionDecisionHandler(\"" + url + "\", \"" + navigationAction.navigationType + "\") -> method:" + httpMethod + " \"" + navType + "\"");
owner._onLoadStarted(url, navType);
};
WKNavigationDelegateImpl.prototype.webViewDidStartProvisionalNavigation = function (webView, navigation) {
var owner = this.owner.get();
if (!owner) {
return;
}
owner.writeTrace("WKNavigationDelegateClass.webViewDidStartProvisionalNavigation(\"" + webView.URL + "\")");
};
WKNavigationDelegateImpl.prototype.webViewDidFinishNavigation = function (webView, navigation) {
var owner = this.owner.get();
if (!owner) {
return;
}
owner.writeTrace("WKNavigationDelegateClass.webViewDidFinishNavigation(\"" + webView.URL + "\")");
var src = owner.src;
if (webView.URL) {
src = webView.URL.absoluteString;
}
owner._onLoadFinished(src).catch(function () { return void 0; });
};
WKNavigationDelegateImpl.prototype.webViewDidFailNavigationWithError = function (webView, navigation, error) {
var owner = this.owner.get();
if (!owner) {
return;
}
var src = owner.src;
if (webView.URL) {
src = webView.URL.absoluteString;
}
owner.writeTrace("WKNavigationDelegateClass.webViewDidFailNavigationWithError(\"" + error.localizedDescription + "\")");
owner._onLoadFinished(src, error.localizedDescription).catch(function () { return void 0; });
};
WKNavigationDelegateImpl.ObjCProtocols = [WKNavigationDelegate];
return WKNavigationDelegateImpl;
}(NSObject));
exports.WKNavigationDelegateImpl = WKNavigationDelegateImpl;
var WKScriptMessageHandlerImpl = (function (_super) {
__extends(WKScriptMessageHandlerImpl, _super);
function WKScriptMessageHandlerImpl() {
return _super !== null && _super.apply(this, arguments) || this;
}
WKScriptMessageHandlerImpl.initWithOwner = function (owner) {
var delegate = WKScriptMessageHandlerImpl.new();
delegate.owner = owner;
return delegate;
};
WKScriptMessageHandlerImpl.prototype.userContentControllerDidReceiveScriptMessage = function (userContentController, webViewMessage) {
var owner = this.owner.get();
if (!owner) {
return;
}
try {
var message = JSON.parse(webViewMessage.body);
owner.onWebViewEvent(message.eventName, message.data);
}
catch (err) {
owner.writeTrace("userContentControllerDidReceiveScriptMessage(" + userContentController + ", " + webViewMessage + ") - bad message: " + webViewMessage.body, webview_ext_common_1.traceMessageType.error);
}
};
WKScriptMessageHandlerImpl.ObjCProtocols = [WKScriptMessageHandler];
return WKScriptMessageHandlerImpl;
}(NSObject));
exports.WKScriptMessageHandlerImpl = WKScriptMessageHandlerImpl;
var WKWebViewWrapper = (function () {
function WKWebViewWrapper(owner) {
this.wkNamedUserScripts = [];
this.shouldInjectWebViewBridge = false;
this.owner = new WeakRef(owner);
}
Object.defineProperty(WKWebViewWrapper.prototype, "ios", {
get: function () {
var owner = this.owner.get();
return owner && owner.ios;
},
enumerable: true,
configurable: true
});
Object.defineProperty(WKWebViewWrapper.prototype, "autoInjectJSBridge", {
get: function () {
var owner = this.owner.get();
return owner && owner.autoInjectJSBridge;
},
enumerable: true,
configurable: true
});
WKWebViewWrapper.prototype.createNativeView = function () {
var owner = this.owner.get();
if (!owner) {
throw new Error("No owner, this should not happen");
}
var configuration = WKWebViewConfiguration.new();
this.wkWebViewConfiguration = configuration;
var messageHandler = WKScriptMessageHandlerImpl.initWithOwner(this.owner);
var wkUController = (this.wkUserContentController = WKUserContentController.new());
wkUController.addScriptMessageHandlerName(messageHandler, "nsBridge");
configuration.userContentController = wkUController;
configuration.preferences.setValueForKey(true, "allowFileAccessFromFileURLs");
configuration.setValueForKey(true, "allowUniversalAccessFromFileURLs");
this.wkCustomUrlSchemeHandler = new CustomUrlSchemeHandler();
configuration.setURLSchemeHandlerForURLScheme(this.wkCustomUrlSchemeHandler, owner.interceptScheme);
var webview = new WKWebView({
frame: CGRectZero,
configuration: configuration,
});
return webview;
};
WKWebViewWrapper.prototype.initNativeView = function () {
this.wkNavigationDelegate = WKNavigationDelegateImpl.initWithOwner(this.owner);
this.loadWKUserScripts();
};
WKWebViewWrapper.prototype.disposeNativeView = function () {
this.wkNavigationDelegate = null;
this.wkCustomUrlSchemeHandler = null;
};
WKWebViewWrapper.prototype.onLoaded = function () {
var ios = this.ios;
if (ios) {
ios.navigationDelegate = this.wkNavigationDelegate;
}
};
WKWebViewWrapper.prototype.onUnloaded = function () {
var ios = this.ios;
if (ios) {
ios.navigationDelegate = null;
}
};
WKWebViewWrapper.prototype.loadUrl = function (src) {
var owner = this.owner.get();
var ios = this.ios;
if (!owner || !ios) {
return;
}
var nsURL = NSURL.URLWithString(src);
if (src.startsWith("file:///")) {
var nsReadAccessUrl = NSURL.URLWithString(src);
owner.writeTrace("WKWebViewWrapper.loadUrl(\"" + src + "\") -> this.ios.loadFileURLAllowingReadAccessToURL(\"" + nsURL + "\", \"" + nsReadAccessUrl + "\"");
ios.loadFileURLAllowingReadAccessToURL(nsURL, nsReadAccessUrl);
}
else {
var nsRequestWithUrl = NSURLRequest.requestWithURL(nsURL);
owner.writeTrace("WKWebViewWrapper.loadUrl(\"" + src + "\") -> this.ios.loadRequest(\"" + nsRequestWithUrl + "\"");
ios.loadRequest(nsRequestWithUrl);
}
};
WKWebViewWrapper.prototype.loadData = function (content) {
var owner = this.owner.get();
var ios = this.ios;
if (!owner || !ios) {
return;
}
var baseUrl = "file:///" + fs.knownFolders.currentApp().path + "/";
var nsBaseUrl = NSURL.URLWithString(baseUrl);
owner.writeTrace("WKWebViewWrapper.loadUrl(content) -> this.ios.loadHTMLStringBaseURL(\"" + nsBaseUrl + "\")");
ios.loadHTMLStringBaseURL(content, nsBaseUrl);
};
Object.defineProperty(WKWebViewWrapper.prototype, "canGoBack", {
get: function () {
var ios = this.ios;
return ios && !!ios.canGoBack;
},
enumerable: true,
configurable: true
});
Object.defineProperty(WKWebViewWrapper.prototype, "canGoForward", {
get: function () {
var ios = this.ios;
return ios && !!ios.canGoForward;
},
enumerable: true,
configurable: true
});
WKWebViewWrapper.prototype.goBack = function () {
var ios = this.ios;
if (!ios) {
return;
}
ios.goBack();
};
WKWebViewWrapper.prototype.goForward = function () {
var ios = this.ios;
if (!ios) {
return;
}
ios.goForward();
};
WKWebViewWrapper.prototype.reload = function () {
var ios = this.ios;
if (!ios) {
return;
}
ios.reload();
};
WKWebViewWrapper.prototype.executeJavaScript = function (scriptCode) {
var ios = this.ios;
if (!ios) {
return Promise.reject(new Error("WebView is missing"));
}
return new Promise(function (resolve, reject) {
ios.evaluateJavaScriptCompletionHandler(scriptCode, function (result, error) {
if (error) {
reject(error);
return;
}
resolve(result);
});
});
};
WKWebViewWrapper.prototype.stopLoading = function () {
var ios = this.ios;
if (!ios) {
return;
}
ios.stopLoading();
};
WKWebViewWrapper.prototype.fixLocalResourceName = function (resourceName) {
var owner = this.owner.get();
if (!owner) {
return null;
}
return owner.fixLocalResourceName(resourceName);
};
WKWebViewWrapper.prototype.registerLocalResourceForNative = function (resourceName, filepath) {
this.wkCustomUrlSchemeHandler.registerLocalResourceForKeyFilepath(resourceName, filepath);
};
WKWebViewWrapper.prototype.unregisterLocalResourceForNative = function (resourceName) {
this.wkCustomUrlSchemeHandler.unregisterLocalResourceForKey(resourceName);
};
WKWebViewWrapper.prototype.getRegisteredLocalResourceFromNative = function (resourceName) {
return this.wkCustomUrlSchemeHandler.getRegisteredLocalResourceForKey(resourceName);
};
WKWebViewWrapper.prototype.autoLoadStyleSheetFile = function (resourceName, filepath, insertBefore) {
var owner = this.owner.get();
if (!owner) {
return;
}
resourceName = this.fixLocalResourceName(resourceName);
if (filepath) {
owner.registerLocalResource(resourceName, filepath);
}
var href = owner.interceptScheme + "://" + resourceName;
var scriptCode = owner.generaateLoadCSSFileScriptCode(href, insertBefore);
this.addNamedWKUserScript("auto-load-css-" + resourceName, scriptCode);
};
WKWebViewWrapper.prototype.removeAutoLoadStyleSheetFile = function (resourceName) {
resourceName = this.fixLocalResourceName(resourceName);
this.removeNamedWKUserScript("auto-load-css-" + resourceName);
};
WKWebViewWrapper.prototype.autoLoadJavaScriptFile = function (resourceName, path) {
return __awaiter(this, void 0, void 0, function () {
var owner, filepath, scriptCode;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
owner = this.owner.get();
if (!owner) {
return [2];
}
resourceName = this.fixLocalResourceName(resourceName);
filepath = owner.resolveLocalResourceFilePath(path);
if (!filepath) {
owner.writeTrace("WKWebViewWrapper.autoLoadJavaScriptFile(\"" + resourceName + "\", \"" + path + "\") - couldn't resolve filepath");
return [2];
}
owner.registerLocalResource(resourceName, path);
return [4, fs.File.fromPath(filepath).readText()];
case 1:
scriptCode = _a.sent();
this.addNamedWKUserScript(resourceName, scriptCode);
return [2];
}
});
});
};
WKWebViewWrapper.prototype.removeAutoLoadJavaScriptFile = function (resourceName) {
var owner = this.owner.get();
if (!owner) {
return;
}
var fixedResourceName = this.fixLocalResourceName(resourceName);
var href = owner.interceptScheme + "://" + fixedResourceName;
this.removeNamedWKUserScript(href);
};
WKWebViewWrapper.prototype.loadWKUserScripts = function (autoInjectJSBridge) {
if (autoInjectJSBridge === void 0) { autoInjectJSBridge = this.autoInjectJSBridge; }
if (!this.wkUserScriptViewPortCode) {
this.wkUserScriptViewPortCode = this.makeWKUserScriptPromise(nativescript_webview_bridge_loader_1.metadataViewPort);
}
this.wkUserContentController.removeAllUserScripts();
var wkUserScriptViewPortCode = this.wkUserScriptViewPortCode;
this.addUserScriptFromPromise(wkUserScriptViewPortCode);
if (!autoInjectJSBridge) {
return;
}
if (!this.wkUserScriptInjectWebViewBrigde) {
this.wkUserScriptInjectWebViewBrigde = this.makeWKUserScriptPromise(nativescript_webview_bridge_loader_1.webViewBridge);
}
this.addUserScriptFromPromise(this.wkUserScriptInjectWebViewBrigde);
for (var _i = 0, _a = this.wkNamedUserScripts; _i < _a.length; _i++) {
var wkUserScript = _a[_i].wkUserScript;
this.addUserScript(wkUserScript);
}
};
WKWebViewWrapper.prototype.makeWKUserScriptPromise = function (scriptCodePromise) {
return __awaiter(this, void 0, void 0, function () {
var scriptCode;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, scriptCodePromise];
case 1:
scriptCode = _a.sent();
return [2, this.createWkUserScript(scriptCode)];
}
});
});
};
WKWebViewWrapper.prototype.addUserScriptFromPromise = function (userScriptPromise) {
return __awaiter(this, void 0, void 0, function () {
var userScript;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, userScriptPromise];
case 1:
userScript = _a.sent();
return [2, this.addUserScript(userScript)];
}
});
});
};
WKWebViewWrapper.prototype.addUserScript = function (userScript) {
this.wkUserContentController.addUserScript(userScript);
};
WKWebViewWrapper.prototype.addNamedWKUserScript = function (resourceName, scriptCode) {
if (!scriptCode) {
return;
}
this.removeNamedWKUserScript(resourceName);
var wkUserScript = this.createWkUserScript(scriptCode);
this.wkNamedUserScripts.push({ resourceName: resourceName, wkUserScript: wkUserScript });
this.addUserScript(wkUserScript);
};
WKWebViewWrapper.prototype.removeNamedWKUserScript = function (resourceName) {
var idx = this.wkNamedUserScripts.findIndex(function (val) { return val.resourceName === resourceName; });
if (idx === -1) {
return;
}
this.wkNamedUserScripts.splice(idx, 1);
this.loadWKUserScripts();
};
WKWebViewWrapper.prototype.createWkUserScript = function (source) {
return WKUserScript.alloc().initWithSourceInjectionTimeForMainFrameOnly(source, 1, true);
};
WKWebViewWrapper.prototype.enableAutoInject = function (enable) {
this.loadWKUserScripts(enable);
};
Object.defineProperty(WKWebViewWrapper.prototype, "scrollBounce", {
get: function () {
var ios = this.ios;
if (!ios) {
return false;
}
return ios.scrollView.bounces;
},
set: function (enable) {
var ios = this.ios;
if (!ios) {
return;
}
ios.scrollView.bounces = !!enable;
},
enumerable: true,
configurable: true
});
return WKWebViewWrapper;
}());
exports.WKWebViewWrapper = WKWebViewWrapper;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vidmlldy1leHQud2t3ZWJ2aWV3LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsid2Vidmlldy1leHQud2t3ZWJ2aWV3LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBR0EsaURBQW1EO0FBQ25ELDJGQUF1RjtBQUN2RiwyREFBMkc7QUFFM0c7SUFBOEMsNENBQVE7SUFBdEQ7O0lBK0dBLENBQUM7SUE3R2lCLHNDQUFhLEdBQTNCLFVBQTRCLEtBQThCO1FBQ3RELElBQU0sT0FBTyxHQUE2Qix3QkFBd0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUN6RSxPQUFPLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUN0QixPQUFPLE9BQU8sQ0FBQztJQUNuQixDQUFDO0lBSU0sd0ZBQXFELEdBQTVELFVBQTZELE9BQWtCLEVBQUUsZ0JBQW9DLEVBQUUsZUFBb0I7UUFDdkksSUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1IsZUFBZSxHQUFpQyxDQUFDO1lBQ2pELE9BQU87U0FDVjtRQUVELElBQU0sT0FBTyxHQUFHLGdCQUFnQixDQUFDLE9BQU8sQ0FBQztRQUN6QyxJQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDO1FBQ3RDLElBQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUM7UUFFdEQsS0FBSyxDQUFDLFVBQVUsQ0FBQyw4REFBMkQsR0FBRyxPQUFHLENBQUMsQ0FBQztRQUNwRixJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ04sT0FBTztTQUNWO1FBRUQsSUFBSSxPQUFPLEdBQW1CLE9BQU8sQ0FBQztRQUV0QyxRQUFRLGdCQUFnQixDQUFDLGNBQWMsRUFBRTtZQUNyQyxNQUFtQyxDQUFDLENBQUM7Z0JBQ2pDLE9BQU8sR0FBRyxhQUFhLENBQUM7Z0JBQ3hCLE1BQU07YUFDVDtZ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QUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO1lBQ3JCLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQ04sT0FBTzthQUNWO1lBRUQsR0FBRyxDQUFDLFVBQVUsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztRQUN0QyxDQUFDOzs7T0FBQTtJQVVMLHVCQUFDO0FBQUQsQ0FBQyxBQTVXRCxJQTRXQztBQTVXWSw0Q0FBZ0IiLCJzb3VyY2VzQ29udGVudCI6WyIvLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9ub2RlX21vZHVsZXMvdG5zLXBsYXRmb3JtLWRlY2xhcmF0aW9ucy9pb3MuZC50c1wiIC8+XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwiLi9wbGF0Zm9ybXMvaW9zL05vdGFXZWJWaWV3RXh0LmQudHNcIiAvPlxuXG5pbXBvcnQgKiBhcyBmcyBmcm9tIFwidG5zLWNvcmUtbW9kdWxlcy9maWxlLXN5c3RlbVwiO1xuaW1wb3J0IHsgbWV0YWRhdGFWaWV3UG9ydCwgd2ViVmlld0JyaWRnZSB9IGZyb20gXCIuL25hdGl2ZXNjcmlwdC13ZWJ2aWV3LWJyaWRnZS1sb2FkZXJcIjtcbmltcG9ydCB7IElPU1dlYlZpZXdXcmFwcGVyLCBOYXZpZ2F0aW9uVHlwZSwgdHJhY2VNZXNzYWdlVHlwZSwgV2ViVmlld0V4dEJhc2UgfSBmcm9tIFwiLi93ZWJ2aWV3LWV4dC1jb21tb25cIjtcblxuZXhwb3J0IGNsYXNzIFdLTmF2aWdhdGlvbkRlbGVnYXRlSW1wbCBleHRlbmRzIE5TT2JqZWN0IGltcGxlbWVudHMgV0tOYXZpZ2F0aW9uRGVsZWdhdGUge1xuICAgIHB1YmxpYyBzdGF0aWMgT2JqQ1Byb3RvY29scyA9IFtXS05hdmlnYXRpb25EZWxlZ2F0ZV07XG4gICAgcHVibGljIHN0YXRpYyBpbml0V2l0aE93bmVyKG93bmVyOiBXZWFrUmVmPFdlYlZpZXdFeHRCYXNlPik6IFdLTmF2aWdhdGlvbkRlbGVnYXRlSW1wbCB7XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSA8V0tOYXZpZ2F0aW9uRGVsZWdhdGVJbXBsPldLTmF2aWdhdGlvbkRlbGVnYXRlSW1wbC5uZXcoKTtcbiAgICAgICAgaGFuZGxlci5vd25lciA9IG93bmVyO1xuICAgICAgICByZXR1cm4gaGFuZGxlcjtcbiAgICB9XG5cbiAgICBwcml2YXRlIG93bmVyOiBXZWFrUmVmPFdlYlZpZXdFeHRCYXNlPjtcblxuICAgIHB1YmxpYyB3ZWJWaWV3RGVjaWRlUG9saWN5Rm9yTmF2aWdhdGlvbkFjdGlvbkRlY2lzaW9uSGFuZGxlcih3ZWJWaWV3OiBXS1dlYlZpZXcsIG5hdmlnYXRpb25BY3Rpb246IFdLTmF2aWdhdGlvbkFjdGlvbiwgZGVjaXNpb25IYW5kbGVyOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgb3duZXIgPSB0aGlzLm93bmVyLmdldCgpO1xuICAgICAgICBpZiAoIW93bmVyKSB7XG4gICAgICAgICAgICBkZWNpc2lvbkhhbmRsZXIoV0tOYXZpZ2F0aW9uQWN0aW9uUG9saWN5LkNhbmNlbCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXF1ZXN0ID0gbmF2aWdhdGlvbkFjdGlvbi5yZXF1ZXN0O1xuICAgICAgICBjb25zdCBodHRwTWV0aG9kID0gcmVxdWVzdC5IVFRQTWV0aG9kO1xuICAgICAgICBjb25zdCB1cmwgPSByZXF1ZXN0LlVSTCAmJiByZXF1ZXN0LlVSTC5hYnNvbHV0ZVN0cmluZztcblxuICAgICAgICBvd25lci53cml0ZVRyYWNlKGB3ZWJWaWV3RGVjaWRlUG9saWN5Rm9yTmF2aWdhdGlvbkFjdGlvbkRlY2lzaW9uSGFuZGxlcjogXCIke3VybH1cImApO1xuICAgICAgICBpZiAoIXVybCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5hdlR5cGU6IE5hdmlnYXRpb25UeXBlID0gXCJvdGhlclwiO1xuXG4gICAgICAgIHN3aXRjaCAobmF2aWdhdGlvbkFjdGlvbi5uYXZpZ2F0aW9uVHlwZSkge1xuICAgICAgICAgICAgY2FzZSBXS05hdmlnYXRpb25UeXBlLkxpbmtBY3RpdmF0ZWQ6IHtcbiAgICAgICAgICAgICAgICBuYXZUeXBlID0gXCJsaW5rQ2xpY2tlZFwiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBXS05hdmlnYXRpb25UeXBlLkZvcm1TdWJtaXR0ZWQ6IHtcbiAgICAgICAgICAgICAgICBuYXZUeXBlID0gXCJmb3JtU3VibWl0dGVkXCI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlIFdLTmF2aWdhdGlvblR5cGUuQmFja0ZvcndhcmQ6IHtcbiAgICAgICAgICAgICAgICBuYXZUeXBlID0gXCJiYWNrRm9yd2FyZFwiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBXS05hdmlnYXRpb25UeXBlLlJlbG9hZDoge1xuICAgICAgICAgICAgICAgIG5hdlR5cGUgPSBcInJlbG9hZFwiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBXS05hdmlnYXRpb25UeXBlLkZvcm1SZXN1Ym1pdHRlZDoge1xuICAgICAgICAgICAgICAgIG5hdlR5cGUgPSBcImZvcm1SZXN1Ym1pdHRlZFwiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVmYXVsdDoge1xuICAgICAgICAgICAgICAgIG5hdlR5cGUgPSBcIm90aGVyXCI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzaG91bGRPdmVycmlkZVVybExvYWRpbmcgPSBvd25lci5fb25TaG91bGRPdmVycmlkZVVybExvYWRpbmcodXJsLCBodHRwTWV0aG9kLCBuYXZUeXBlKTtcbiAgICAgICAgaWYgKHNob3VsZE92ZXJyaWRlVXJsTG9hZGluZyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgb3duZXIud3JpdGVUcmFjZShcbiAgICAgICAgICAgICAgICBgV0tOYXZpZ2F0aW9uRGVsZWdhdGVDbGFzcy53ZWJWaWV3RGVjaWRlUG9saWN5Rm9yTmF2aWdhdGlvbkFjdGlvbkRlY2lzaW9uSGFuZGxlcihcIiR7dXJsfVwiLCBcIiR7XG4gICAgICAgICAgICAgICAgICAgIG5hdmlnYXRpb25BY3Rpb24ubmF2aWdhdGlvblR5cGVcbiAgICAgICAgICAgICAgICB9XCIpIC0+IG1ldGhvZDoke2h0dHBNZXRob2R9IFwiJHtuYXZUeXBlfVwiIC0+IGNhbmNlbGAsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgZGVjaXNpb25IYW5kbGVyKFdLTmF2aWdhdGlvbkFjdGlvblBvbGljeS5DYW5jZWwpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGRlY2lzaW9uSGFuZGxlcihXS05hdmlnYXRpb25BY3Rpb25Qb2xpY3kuQWxsb3cpO1xuXG4gICAgICAgIG93bmVyLndyaXRlVHJhY2UoXG4gICAgICAgICAgICBgV0tOYXZpZ2F0aW9uRGVsZWdhdGVDbGFzcy53ZWJWaWV3RGVjaWRlUG9saWN5Rm9yTmF2aWdhdGlvbkFjdGlvbkRlY2lzaW9uSGFuZGxlcihcIiR7dXJsfVwiLCBcIiR7XG4gICAgICAgICAgICAgICAgbmF2aWdhdGlvbkFjdGlvbi5uYXZpZ2F0aW9uVHlwZVxuICAgICAgICAgICAgfVwiKSAtPiBtZXRob2Q6JHtodHRwTWV0aG9kfSBcIiR7bmF2VHlwZX1cImAsXG4gICAgICAgICk7XG4gICAgICAgIG93bmVyLl9vbkxvYWRTdGFydGVkKHVybCwgbmF2VHlwZSk7XG4gICAgfVxuXG4gICAgcHVibGljIHdlYlZpZXdEaWRTdGFydFByb3Zpc2lvbmFsTmF2aWdhdGlvbih3ZWJWaWV3OiBXS1dlYlZpZXcsIG5hdmlnYXRpb246IFdLTmF2aWdhdGlvbik6IHZvaWQge1xuICAgICAgICBjb25zdCBvd25lciA9IHRoaXMub3duZXIuZ2V0KCk7XG4gICAgICAgIGlmICghb3duZXIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIG93bmVyLndyaXRlVHJhY2UoYFdLTmF2aWdhdGlvbkRlbGVnYXRlQ2xhc3Mud2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uKFwiJHt3ZWJWaWV3LlVSTH1cIilgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgd2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb24od2ViVmlldzogV0tXZWJWaWV3LCBuYXZpZ2F0aW9uOiBXS05hdmlnYXRpb24pOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgb3duZXIgPSB0aGlzLm93bmVyLmdldCgpO1xuICAgICAgICBpZiAoIW93bmVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBvd25lci53cml0ZVRyYWNlKGBXS05hdmlnYXRpb25EZWxlZ2F0ZUNsYXNzLndlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uKFwiJHt3ZWJWaWV3LlVSTH1cIilgKTtcbiAgICAgICAgbGV0IHNyYyA9IG93bmVyLnNyYztcbiAgICAgICAgaWYgKHdlYlZpZXcuVVJMKSB7XG4gICAgICAgICAgICBzcmMgPSB3ZWJWaWV3LlVSTC5hYnNvbHV0ZVN0cmluZztcbiAgICAgICAgfVxuICAgICAgICBvd25lci5fb25Mb2FkRmluaXNoZWQoc3JjKS5jYXRjaCgoKSA9PiB2b2lkIDApO1xuICAgIH1cblxuICAgIHB1YmxpYyB3ZWJWaWV3RGlkRmFpbE5hdmlnYXRpb25XaXRoRXJyb3Iod2ViVmlldzogV0tXZWJWaWV3LCBuYXZpZ2F0aW9uOiBXS05hdmlnYXRpb24sIGVycm9yOiBOU0Vycm9yKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG93bmVyID0gdGhpcy5vd25lci5nZXQoKTtcbiAgICAgICAgaWYgKCFvd25lcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHNyYyA9IG93bmVyLnNyYztcbiAgICAgICAgaWYgKHdlYlZpZXcuVVJMKSB7XG4gICAgICAgICAgICBzcmMgPSB3ZWJWaWV3LlVSTC5hYnNvbHV0ZVN0cmluZztcbiAgICAgICAgfVxuICAgICAgICBvd25lci53cml0ZVRyYWNlKGBXS05hdmlnYXRpb25EZWxlZ2F0ZUNsYXNzLndlYlZpZXdEaWRGYWlsTmF2aWdhdGlvbldpdGhFcnJvcihcIiR7ZXJyb3IubG9jYWxpemVkRGVzY3JpcHRpb259XCIpYCk7XG4gICAgICAgIG93bmVyLl9vbkxvYWRGaW5pc2hlZChzcmMsIGVycm9yLmxvY2FsaXplZERlc2NyaXB0aW9uKS5jYXRjaCgoKSA9PiB2b2lkIDApO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdLU2NyaXB0TWVzc2FnZUhhbmRsZXJJbXBsIGV4dGVuZHMgTlNPYmplY3QgaW1wbGVtZW50cyBXS1NjcmlwdE1lc3NhZ2VIYW5kbGVyIHtcbiAgICBwdWJsaWMgc3RhdGljIE9iakNQcm90b2NvbHMgPSBbV0tTY3JpcHRNZXNzYWdlSGFuZGxlcl07XG5cbiAgICBwcml2YXRlIG93bmVyOiBXZWFrUmVmPFdlYlZpZXdFeHRCYXNlPjtcblxuICAgIHB1YmxpYyBzdGF0aWMgaW5pdFdpdGhPd25lcihvd25lcjogV2Vha1JlZjxXZWJWaWV3RXh0QmFzZT4pOiBXS1NjcmlwdE1lc3NhZ2VIYW5kbGVySW1wbCB7XG4gICAgICAgIGNvbnN0IGRlbGVnYXRlID0gPFdLU2NyaXB0TWVzc2FnZUhhbmRsZXJJbXBsPldLU2NyaXB0TWVzc2FnZUhhbmRsZXJJbXBsLm5ldygpO1xuICAgICAgICBkZWxlZ2F0ZS5vd25lciA9IG93bmVyO1xuICAgICAgICByZXR1cm4gZGVsZWdhdGU7XG4gICAgfVxuXG4gICAgcHVibGljIHVzZXJDb250ZW50Q29udHJvbGxlckRpZFJlY2VpdmVTY3JpcHRNZXNzYWdlKHVzZXJDb250ZW50Q29udHJvbGxlcjogV0tVc2VyQ29udGVudENvbnRyb2xsZXIsIHdlYlZpZXdNZXNzYWdlOiBXS1NjcmlwdE1lc3NhZ2UpIHtcbiAgICAgICAgY29uc3Qgb3duZXIgPSB0aGlzLm93bmVyLmdldCgpO1xuICAgICAgICBpZiAoIW93bmVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IEpTT04ucGFyc2Uod2ViVmlld01lc3NhZ2UuYm9keSBhcyBzdHJpbmcpO1xuICAgICAgICAgICAgb3duZXIub25XZWJWaWV3RXZlbnQobWVzc2FnZS5ldmVudE5hbWUsIG1lc3NhZ2UuZGF0YSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgb3duZXIud3JpdGVUcmFjZShcbiAgICAgICAgICAgICAgICBgdXNlckNvbnRlbnRDb250cm9sbGVyRGlkUmVjZWl2ZVNjcmlwdE1lc3NhZ2UoJHt1c2VyQ29udGVudENvbnRyb2xsZXJ9LCAke3dlYlZpZXdNZXNzYWdlfSkgLSBiYWQgbWVzc2FnZTogJHt3ZWJWaWV3TWVzc2FnZS5ib2R5fWAsXG4gICAgICAgICAgICAgICAgdHJhY2VNZXNzYWdlVHlwZS5lcnJvcixcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBXS1dlYlZpZXdXcmFwcGVyIGltcGxlbWVudHMgSU9TV2ViVmlld1dyYXBwZXIge1xuICAgIHByb3RlY3RlZCB3a1dlYlZpZXdDb25maWd1cmF0aW9uOiBXS1dlYlZpZXdDb25maWd1cmF0aW9uO1xuICAgIHByb3RlY3RlZCB3a05hdmlnYXRpb25EZWxlZ2F0ZTogV0tOYXZpZ2F0aW9uRGVsZWdhdGVJbXBsO1xuICAgIHByb3RlY3RlZCB3a0N1c3RvbVVybFNjaGVtZUhhbmRsZXI6IEN1c3RvbVVybFNjaGVtZUhhbmRsZXI7XG4gICAgcHJvdGVjdGVkIHdrVXNlckNvbnRlbnRDb250cm9sbGVyOiBXS1VzZXJDb250ZW50Q29udHJvbGxlcjtcbiAgICBwcm90ZWN0ZWQgd2tVc2VyU2NyaXB0SW5qZWN0V2ViVmlld0JyaWdkZTogUHJvbWlzZTxXS1VzZXJTY3JpcHQ+IHwgdm9pZDtcbiAgICBwcm90ZWN0ZWQgd2tVc2VyU2NyaXB0Vmlld1BvcnRDb2RlOiBQcm9taXNlPFdLVXNlclNjcmlwdD47XG4gICAgcHJvdGVjdGVkIHdrTmFtZWRVc2VyU2NyaXB0cyA9IFtdIGFzIEFycmF5PHtcbiAgICAgICAgcmVzb3VyY2VOYW1lOiBzdHJpbmc7XG4gICAgICAgIHdrVXNlclNjcmlwdDogV0tVc2VyU2NyaXB0O1xuICAgIH0+O1xuXG4gICAgcHVibGljIG93bmVyOiBXZWFrUmVmPFdlYlZpZXdFeHRCYXNlPjtcbiAgICBwdWJsaWMgZ2V0IGlvcygpOiBXS1dlYlZpZXcgfCB2b2lkIHtcbiAgICAgICAgY29uc3Qgb3duZXIgPSB0aGlzLm93bmVyLmdldCgpO1xuICAgICAgICByZXR1cm4gb3duZXIgJiYgb3duZXIuaW9zO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWFkb25seSBzaG91bGRJbmplY3RXZWJWaWV3QnJpZGdlID0gZmFsc2U7XG5cbiAgICBwdWJsaWMgZ2V0IGF1dG9JbmplY3RKU0JyaWRnZSgpIHtcbiAgICAgICAgY29uc3Qgb3duZXIgPSB0aGlzLm93bmVyLmdldCgpO1xuICAgICAgICByZXR1cm4gb3duZXIgJiYgb3duZXIuYXV0b0luamVjdEpTQnJpZGdlO1xuICAgIH1cblxuICAgIGNvbnN0cnVjdG9yKG93bmVyOiBXZWJWaWV3RXh0QmFzZSkge1xuICAgICAgICB0aGlzLm93bmVyID0gbmV3IFdlYWtSZWYob3duZXIpO1xuICAgIH1cblxuICAgIHB1YmxpYyBjcmVhdGVOYXRpdmVWaWV3KCkge1xuICAgICAgICBjb25zdCBvd25lciA9IHRoaXMub3duZXIuZ2V0KCk7XG4gICAgICAgIGlmICghb3duZXIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIG93bmVyLCB0aGlzIHNob3VsZCBub3QgaGFwcGVuXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29uZmlndXJhdGlvbiA9IFdLV2ViVmlld0NvbmZpZ3VyYXRpb24ubmV3KCk7XG4gICAgICAgIHRoaXMud2tXZWJWaWV3Q29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb247XG5cbiAgICAgICAgY29uc3QgbWVzc2FnZUhhbmRsZXIgPSBXS1NjcmlwdE1lc3NhZ2VIYW5kbGVySW1wbC5pbml0V2l0aE93bmVyKHRoaXMub3duZXIpO1xuICAgICAgICBjb25zdCB3a1VDb250cm9sbGVyID0gKHRoaXMud2tVc2VyQ29udGVudENvbnRyb2xsZXIgPSBXS1VzZXJDb250ZW50Q29udHJvbGxlci5uZXcoKSk7XG4gICAgICAgIHdrVUNvbnRyb2xsZXIuYWRkU2NyaXB0TWVzc2FnZUhhbmRsZXJOYW1lKG1lc3NhZ2VIYW5kbGVyLCBcIm5zQnJpZGdlXCIpO1xuICAgICAgICBjb25maWd1cmF0aW9uLnVzZXJDb250ZW50Q29udHJvbGxlciA9IHdrVUNvbnRyb2xsZXI7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24ucHJlZmVyZW5jZXMuc2V0VmFsdWVGb3JLZXkodHJ1ZSwgXCJhbGxvd0ZpbGVBY2Nlc3NGcm9tRmlsZVVSTHNcIik7XG4gICAgICAgIGNvbmZpZ3VyYXRpb24uc2V0VmFsdWVGb3JLZXkodHJ1ZSwgXCJhbGxvd1VuaXZlcnNhbEFjY2Vzc0Zyb21GaWxlVVJMc1wiKTtcblxuICAgICAgICB0aGlzLndrQ3VzdG9tVXJsU2NoZW1lSGFuZGxlciA9IG5ldyBDdXN0b21VcmxTY2hlbWVIYW5kbGVyKCk7XG5cbiAgICAgICAgY29uZmlndXJhdGlvbi5zZXRVUkxTY2hlbWVIYW5kbGVyRm9yVVJMU2NoZW1lKHRoaXMud2tDdXN0b21VcmxTY2hlbWVIYW5kbGVyLCBvd25lci5pbnRlcmNlcHRTY2hlbWUpO1xuXG4gICAgICAgIGNvbnN0IHdlYnZpZXcgPSBuZXcgV0tXZWJWaWV3KHtcbiAgICAgICAgICAgIGZyYW1lOiBDR1JlY3RaZXJvLFxuICAgICAgICAgICAgY29uZmlndXJhdGlvbixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHdlYnZpZXc7XG4gICAgfVxuXG4gICAgcHVibGljIGluaXROYXRpdmVWaWV3KCkge1xuICAgICAgICB0aGlzLndrTmF2aWdhdGlvbkRlbGVnYXRlID0gV0tOYXZpZ2F0aW9uRGVsZWdhdGVJbXBsLmluaXRXaXRoT3duZXIodGhpcy5vd25lcik7XG5cbiAgICAgICAgdGhpcy5sb2FkV0tVc2VyU2NyaXB0cygpO1xuICAgIH1cblxuICAgIHB1YmxpYyBkaXNwb3NlTmF0aXZlVmlldygpIHtcbiAgICAgICAgdGhpcy53a05hdmlnYXRpb25EZWxlZ2F0ZSA9IG51bGw7XG4gICAgICAgIHRoaXMud2tDdXN0b21VcmxTY2hlbWVIYW5kbGVyID0gbnVsbDtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25Mb2FkZWQoKSB7XG4gICAgICAgIGNvbnN0IGlvcyA9IHRoaXMuaW9zO1xuICAgICAgICBpZiAoaW9zKSB7XG4gICAgICAgICAgICBpb3MubmF2aWdhdGlvbkRlbGVnYXRlID0gdGhpcy53a05hdmlnYXRpb25EZWxlZ2F0ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBvblVubG9hZGVkKCkge1xuICAgICAgICBjb25zdCBpb3MgPSB0aGlzLmlvcztcbiAgICAgICAgaWYgKGlvcykge1xuICAgICAgICAgICAgaW9zLm5hdmlnYXRpb25EZWxlZ2F0ZSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgbG9hZFVybChzcmM6IHN0cmluZykge1xuICAgICAgICBjb25zdCBvd25lciA9IHRoaXMub3duZXIuZ2V0KCk7XG4gICAgICAgIGNvbnN0IGlvcyA9IHRoaXMuaW9zO1xuICAgICAgICBpZiAoIW93bmVyIHx8ICFpb3MpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5zVVJMID0gTlNVUkwuVVJMV2l0aFN0cmluZyhzcmMpO1xuICAgICAgICBpZiAoc3JjLnN0YXJ0c1dpdGgoXCJmaWxlOi8vL1wiKSkge1xuICAgICAgICAgICAgY29uc3QgbnNSZWFkQWNjZXNzVXJsID0gTlNVUkwuVVJMV2l0aFN0cmluZyhzcmMpO1xuICAgICAgICAgICAgb3duZXIud3JpdGVUcmFjZShgV0tXZWJWaWV3V3JhcHBlci5sb2FkVXJsKFwiJHtzcmN9XCIpIC0+IHRoaXMuaW9zLmxvYWRGaWxlVVJMQWxsb3dpbmdSZWFkQWNjZXNzVG9VUkwoXCIke25zVVJMfVwiLCBcIiR7bnNSZWFkQWNjZXNzVXJsfVwiYCk7XG4gICAgICAgICAgICBpb3MubG9hZEZpbGVVUkxBbGxvd2luZ1JlYWRBY2Nlc3NUb1VSTChuc1VSTCwgbnNSZWFkQWNjZXNzVXJsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG5zUmVxdWVzdFdpdGhVcmwgPSBOU1VSTFJlcXVlc3QucmVxdWVzdFdpdGhVUkwobnNVUkwpO1xuICAgICAgICAgICAgb3duZXIud3JpdGVUcmFjZShgV0tXZWJWaWV3V3JhcHBlci5sb2FkVXJsKFwiJHtzcmN9XCIpIC0+IHRoaXMuaW9zLmxvYWRSZXF1ZXN0KFwiJHtuc1JlcXVlc3RXaXRoVXJsfVwiYCk7XG4gICAgICAgICAgICBpb3MubG9hZFJlcXVlc3QobnNSZXF1ZXN0V2l0aFVybCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgbG9hZERhdGEoY29udGVudDogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IG93bmVyID0gdGhpcy5vd25lci5nZXQoKTtcbiAgICAgICAgY29uc3QgaW9zID0gdGhpcy5pb3M7XG4gICAgICAgIGlmICghb3duZXIgfHwgIWlvcykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYmFzZVVybCA9IGBmaWxlOi8vLyR7ZnMua25vd25Gb2xkZXJzLmN1cnJlbnRBcHAoKS5wYXRofS9gO1xuICAgICAgICBjb25zdCBuc0Jhc2VVcmwgPSBOU1VSTC5VUkxXaXRoU3RyaW5nKGJhc2VVcmwpO1xuXG4gICAgICAgIG93bmVyLndyaXRlVHJhY2UoYFdLV2ViVmlld1dyYXBwZXIubG9hZFVybChjb250ZW50KSAtPiB0aGlzLmlvcy5sb2FkSFRNTFN0cmluZ0Jhc2VVUkwoXCIke25zQmFzZVVybH1cIilgKTtcbiAgICAgICAgaW9zLmxvYWRIVE1MU3RyaW5nQmFzZVVSTChjb250ZW50LCBuc0Jhc2VVcmwpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgY2FuR29CYWNrKCk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBpb3MgPSB0aGlzLmlvcztcbiAgICAgICAgcmV0dXJuIGlvcyAmJiAhIWlvcy5jYW5Hb0JhY2s7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBjYW5Hb0ZvcndhcmQoKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGlvcyA9IHRoaXMuaW9zO1xuICAgICAgICByZXR1cm4gaW9zICYmICEhaW9zLmNhbkdvRm9yd2FyZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ29CYWNrKCkge1xuICAgICAgICBjb25zdCBpb3MgPSB0aGlzLmlvcztcbiAgICAgICAgaWYgKCFpb3MpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlvcy5nb0JhY2soKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ29Gb3J3YXJkKCkge1xuICAgICAgICBjb25zdCBpb3MgPSB0aGlzLmlvcztcbiAgICAgICAgaWYgKCFpb3MpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlvcy5nb0ZvcndhcmQoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVsb2FkKCkge1xuICAgICAgICBjb25zdCBpb3MgPSB0aGlzLmlvcztcbiAgICAgICAgaWYgKCFpb3MpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlvcy5yZWxvYWQoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZXhlY3V0ZUphdmFTY3JpcHQoc2NyaXB0Q29kZTogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IGlvcyA9IHRoaXMuaW9zO1xuICAgICAgICBpZiAoIWlvcykge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcihcIldlYlZpZXcgaXMgbWlzc2luZ1wiKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8YW55PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpb3MuZXZhbHVhdGVKYXZhU2NyaXB0Q29tcGxldGlvbkhhbmRsZXIoc2NyaXB0Q29kZSwgKHJlc3VsdCwgZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJlc29sdmUocmVzdWx0KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RvcExvYWRpbmcoKSB7XG4gICAgICAgIGNvbnN0IGlvcyA9IHRoaXMuaW9zO1xuICAgICAgICBpZiAoIWlvcykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaW9zLnN0b3BMb2FkaW5nKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGZpeExvY2FsUmVzb3VyY2VOYW1lKHJlc291cmNlTmFtZTogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IG93bmVyID0gdGhpcy5vd25lci5nZXQoKTtcbiAgICAgICAgaWYgKCFvd25lcikge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb3duZXIuZml4TG9jYWxSZXNvdXJjZU5hbWUocmVzb3VyY2VOYW1lKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVnaXN0ZXJMb2NhbFJlc291cmNlRm9yTmF0aXZlKHJlc291cmNlTmFtZTogc3RyaW5nLCBmaWxlcGF0aDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMud2tDdXN0b21VcmxTY2hlbWVIYW5kbGVyLnJlZ2lzdGVyTG9jYWxSZXNvdXJjZUZvcktleUZpbGVwYXRoKHJlc291cmNlTmFtZSwgZmlsZXBhdGgpO1xuICAgIH1cblxuICAgIHB1YmxpYyB1bnJlZ2lzdGVyTG9jYWxSZXNvdXJjZUZvck5hdGl2ZShyZXNvdXJjZU5hbWU6IHN0cmluZykge1xuICAgICAgICB0aGlzLndrQ3VzdG9tVXJsU2NoZW1lSGFuZGxlci51bnJlZ2lzdGVyTG9jYWxSZXNvdXJjZUZvcktleShyZXNvdXJjZU5hbWUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRSZWdpc3RlcmVkTG9jYWxSZXNvdXJjZUZyb21OY