@angular/compiler
Version:
Angular - the compiler library
215 lines • 40.5 kB
JavaScript
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { CompileStylesheetMetadata, CompileTemplateMetadata, templateSourceUrl } from './compile_metadata';
import { preserveWhitespacesDefault } from './config';
import { ViewEncapsulation } from './core';
import * as html from './ml_parser/ast';
import { InterpolationConfig } from './ml_parser/interpolation_config';
import { extractStyleUrls, isStyleUrlResolvable } from './style_url_resolver';
import { PreparsedElementType, preparseElement } from './template_parser/template_preparser';
import { SyncAsync, isDefined, stringify, syntaxError } from './util';
export class DirectiveNormalizer {
constructor(_resourceLoader, _urlResolver, _htmlParser, _config) {
this._resourceLoader = _resourceLoader;
this._urlResolver = _urlResolver;
this._htmlParser = _htmlParser;
this._config = _config;
this._resourceLoaderCache = new Map();
}
clearCache() { this._resourceLoaderCache.clear(); }
clearCacheFor(normalizedDirective) {
if (!normalizedDirective.isComponent) {
return;
}
const template = normalizedDirective.template;
this._resourceLoaderCache.delete(template.templateUrl);
template.externalStylesheets.forEach((stylesheet) => { this._resourceLoaderCache.delete(stylesheet.moduleUrl); });
}
_fetch(url) {
let result = this._resourceLoaderCache.get(url);
if (!result) {
result = this._resourceLoader.get(url);
this._resourceLoaderCache.set(url, result);
}
return result;
}
normalizeTemplate(prenormData) {
if (isDefined(prenormData.template)) {
if (isDefined(prenormData.templateUrl)) {
throw syntaxError(`'${stringify(prenormData.componentType)}' component cannot define both template and templateUrl`);
}
if (typeof prenormData.template !== 'string') {
throw syntaxError(`The template specified for component ${stringify(prenormData.componentType)} is not a string`);
}
}
else if (isDefined(prenormData.templateUrl)) {
if (typeof prenormData.templateUrl !== 'string') {
throw syntaxError(`The templateUrl specified for component ${stringify(prenormData.componentType)} is not a string`);
}
}
else {
throw syntaxError(`No template specified for component ${stringify(prenormData.componentType)}`);
}
if (isDefined(prenormData.preserveWhitespaces) &&
typeof prenormData.preserveWhitespaces !== 'boolean') {
throw syntaxError(`The preserveWhitespaces option for component ${stringify(prenormData.componentType)} must be a boolean`);
}
return SyncAsync.then(this._preParseTemplate(prenormData), (preparsedTemplate) => this._normalizeTemplateMetadata(prenormData, preparsedTemplate));
}
_preParseTemplate(prenomData) {
let template;
let templateUrl;
if (prenomData.template != null) {
template = prenomData.template;
templateUrl = prenomData.moduleUrl;
}
else {
templateUrl = this._urlResolver.resolve(prenomData.moduleUrl, prenomData.templateUrl);
template = this._fetch(templateUrl);
}
return SyncAsync.then(template, (template) => this._preparseLoadedTemplate(prenomData, template, templateUrl));
}
_preparseLoadedTemplate(prenormData, template, templateAbsUrl) {
const isInline = !!prenormData.template;
const interpolationConfig = InterpolationConfig.fromArray(prenormData.interpolation);
const rootNodesAndErrors = this._htmlParser.parse(template, templateSourceUrl({ reference: prenormData.ngModuleType }, { type: { reference: prenormData.componentType } }, { isInline, templateUrl: templateAbsUrl }), true, interpolationConfig);
if (rootNodesAndErrors.errors.length > 0) {
const errorString = rootNodesAndErrors.errors.join('\n');
throw syntaxError(`Template parse errors:\n${errorString}`);
}
const templateMetadataStyles = this._normalizeStylesheet(new CompileStylesheetMetadata({ styles: prenormData.styles, moduleUrl: prenormData.moduleUrl }));
const visitor = new TemplatePreparseVisitor();
html.visitAll(visitor, rootNodesAndErrors.rootNodes);
const templateStyles = this._normalizeStylesheet(new CompileStylesheetMetadata({ styles: visitor.styles, styleUrls: visitor.styleUrls, moduleUrl: templateAbsUrl }));
const styles = templateMetadataStyles.styles.concat(templateStyles.styles);
const inlineStyleUrls = templateMetadataStyles.styleUrls.concat(templateStyles.styleUrls);
const styleUrls = this
._normalizeStylesheet(new CompileStylesheetMetadata({ styleUrls: prenormData.styleUrls, moduleUrl: prenormData.moduleUrl }))
.styleUrls;
return {
template,
templateUrl: templateAbsUrl, isInline,
htmlAst: rootNodesAndErrors, styles, inlineStyleUrls, styleUrls,
ngContentSelectors: visitor.ngContentSelectors,
};
}
_normalizeTemplateMetadata(prenormData, preparsedTemplate) {
return SyncAsync.then(this._loadMissingExternalStylesheets(preparsedTemplate.styleUrls.concat(preparsedTemplate.inlineStyleUrls)), (externalStylesheets) => this._normalizeLoadedTemplateMetadata(prenormData, preparsedTemplate, externalStylesheets));
}
_normalizeLoadedTemplateMetadata(prenormData, preparsedTemplate, stylesheets) {
// Algorithm:
// - produce exactly 1 entry per original styleUrl in
// CompileTemplateMetadata.externalStylesheets with all styles inlined
// - inline all styles that are referenced by the template into CompileTemplateMetadata.styles.
// Reason: be able to determine how many stylesheets there are even without loading
// the template nor the stylesheets, so we can create a stub for TypeScript always synchronously
// (as resource loading may be async)
const styles = [...preparsedTemplate.styles];
this._inlineStyles(preparsedTemplate.inlineStyleUrls, stylesheets, styles);
const styleUrls = preparsedTemplate.styleUrls;
const externalStylesheets = styleUrls.map(styleUrl => {
const stylesheet = stylesheets.get(styleUrl);
const styles = [...stylesheet.styles];
this._inlineStyles(stylesheet.styleUrls, stylesheets, styles);
return new CompileStylesheetMetadata({ moduleUrl: styleUrl, styles: styles });
});
let encapsulation = prenormData.encapsulation;
if (encapsulation == null) {
encapsulation = this._config.defaultEncapsulation;
}
if (encapsulation === ViewEncapsulation.Emulated && styles.length === 0 &&
styleUrls.length === 0) {
encapsulation = ViewEncapsulation.None;
}
return new CompileTemplateMetadata({
encapsulation,
template: preparsedTemplate.template,
templateUrl: preparsedTemplate.templateUrl,
htmlAst: preparsedTemplate.htmlAst, styles, styleUrls,
ngContentSelectors: preparsedTemplate.ngContentSelectors,
animations: prenormData.animations,
interpolation: prenormData.interpolation,
isInline: preparsedTemplate.isInline, externalStylesheets,
preserveWhitespaces: preserveWhitespacesDefault(prenormData.preserveWhitespaces, this._config.preserveWhitespaces),
});
}
_inlineStyles(styleUrls, stylesheets, targetStyles) {
styleUrls.forEach(styleUrl => {
const stylesheet = stylesheets.get(styleUrl);
stylesheet.styles.forEach(style => targetStyles.push(style));
this._inlineStyles(stylesheet.styleUrls, stylesheets, targetStyles);
});
}
_loadMissingExternalStylesheets(styleUrls, loadedStylesheets = new Map()) {
return SyncAsync.then(SyncAsync.all(styleUrls.filter((styleUrl) => !loadedStylesheets.has(styleUrl))
.map(styleUrl => SyncAsync.then(this._fetch(styleUrl), (loadedStyle) => {
const stylesheet = this._normalizeStylesheet(new CompileStylesheetMetadata({ styles: [loadedStyle], moduleUrl: styleUrl }));
loadedStylesheets.set(styleUrl, stylesheet);
return this._loadMissingExternalStylesheets(stylesheet.styleUrls, loadedStylesheets);
}))), (_) => loadedStylesheets);
}
_normalizeStylesheet(stylesheet) {
const moduleUrl = stylesheet.moduleUrl;
const allStyleUrls = stylesheet.styleUrls.filter(isStyleUrlResolvable)
.map(url => this._urlResolver.resolve(moduleUrl, url));
const allStyles = stylesheet.styles.map(style => {
const styleWithImports = extractStyleUrls(this._urlResolver, moduleUrl, style);
allStyleUrls.push(...styleWithImports.styleUrls);
return styleWithImports.style;
});
return new CompileStylesheetMetadata({ styles: allStyles, styleUrls: allStyleUrls, moduleUrl: moduleUrl });
}
}
class TemplatePreparseVisitor {
constructor() {
this.ngContentSelectors = [];
this.styles = [];
this.styleUrls = [];
this.ngNonBindableStackCount = 0;
}
visitElement(ast, context) {
const preparsedElement = preparseElement(ast);
switch (preparsedElement.type) {
case PreparsedElementType.NG_CONTENT:
if (this.ngNonBindableStackCount === 0) {
this.ngContentSelectors.push(preparsedElement.selectAttr);
}
break;
case PreparsedElementType.STYLE:
let textContent = '';
ast.children.forEach(child => {
if (child instanceof html.Text) {
textContent += child.value;
}
});
this.styles.push(textContent);
break;
case PreparsedElementType.STYLESHEET:
this.styleUrls.push(preparsedElement.hrefAttr);
break;
default:
break;
}
if (preparsedElement.nonBindable) {
this.ngNonBindableStackCount++;
}
html.visitAll(this, ast.children);
if (preparsedElement.nonBindable) {
this.ngNonBindableStackCount--;
}
return null;
}
visitExpansion(ast, context) { html.visitAll(this, ast.cases); }
visitExpansionCase(ast, context) {
html.visitAll(this, ast.expression);
}
visitComment(ast, context) { return null; }
visitAttribute(ast, context) { return null; }
visitText(ast, context) { return null; }
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlyZWN0aXZlX25vcm1hbGl6ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvZGlyZWN0aXZlX25vcm1hbGl6ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUEyQix5QkFBeUIsRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBQ25JLE9BQU8sRUFBaUIsMEJBQTBCLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDcEUsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sUUFBUSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxJQUFJLE1BQU0saUJBQWlCLENBQUM7QUFFeEMsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0sa0NBQWtDLENBQUM7QUFHckUsT0FBTyxFQUFDLGdCQUFnQixFQUFFLG9CQUFvQixFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDNUUsT0FBTyxFQUFDLG9CQUFvQixFQUFFLGVBQWUsRUFBQyxNQUFNLHNDQUFzQyxDQUFDO0FBRTNGLE9BQU8sRUFBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFnQnBFLE1BQU07SUFHSixZQUNZLGVBQStCLEVBQVUsWUFBeUIsRUFDbEUsV0FBdUIsRUFBVSxPQUF1QjtRQUR4RCxvQkFBZSxHQUFmLGVBQWUsQ0FBZ0I7UUFBVSxpQkFBWSxHQUFaLFlBQVksQ0FBYTtRQUNsRSxnQkFBVyxHQUFYLFdBQVcsQ0FBWTtRQUFVLFlBQU8sR0FBUCxPQUFPLENBQWdCO1FBSjVELHlCQUFvQixHQUFHLElBQUksR0FBRyxFQUE2QixDQUFDO0lBSUcsQ0FBQztJQUV4RSxVQUFVLEtBQVcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUV6RCxhQUFhLENBQUMsbUJB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ZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge0NvbXBpbGVEaXJlY3RpdmVNZXRhZGF0YSwgQ29tcGlsZVN0eWxlc2hlZXRNZXRhZGF0YSwgQ29tcGlsZVRlbXBsYXRlTWV0YWRhdGEsIHRlbXBsYXRlU291cmNlVXJsfSBmcm9tICcuL2NvbXBpbGVfbWV0YWRhdGEnO1xuaW1wb3J0IHtDb21waWxlckNvbmZpZywgcHJlc2VydmVXaGl0ZXNwYWNlc0RlZmF1bHR9IGZyb20gJy4vY29uZmlnJztcbmltcG9ydCB7Vmlld0VuY2Fwc3VsYXRpb259IGZyb20gJy4vY29yZSc7XG5pbXBvcnQgKiBhcyBodG1sIGZyb20gJy4vbWxfcGFyc2VyL2FzdCc7XG5pbXBvcnQge0h0bWxQYXJzZXJ9IGZyb20gJy4vbWxfcGFyc2VyL2h0bWxfcGFyc2VyJztcbmltcG9ydCB7SW50ZXJwb2xhdGlvbkNvbmZpZ30gZnJvbSAnLi9tbF9wYXJzZXIvaW50ZXJwb2xhdGlvbl9jb25maWcnO1xuaW1wb3J0IHtQYXJzZVRyZWVSZXN1bHQgYXMgSHRtbFBhcnNlVHJlZVJlc3VsdH0gZnJvbSAnLi9tbF9wYXJzZXIvcGFyc2VyJztcbmltcG9ydCB7UmVzb3VyY2VMb2FkZXJ9IGZyb20gJy4vcmVzb3VyY2VfbG9hZGVyJztcbmltcG9ydCB7ZXh0cmFjdFN0eWxlVXJscywgaXNTdHlsZVVybFJlc29sdmFibGV9IGZyb20gJy4vc3R5bGVfdXJsX3Jlc29sdmVyJztcbmltcG9ydCB7UHJlcGFyc2VkRWxlbWVudFR5cGUsIHByZXBhcnNlRWxlbWVudH0gZnJvbSAnLi90ZW1wbGF0ZV9wYXJzZXIvdGVtcGxhdGVfcHJlcGFyc2VyJztcbmltcG9ydCB7VXJsUmVzb2x2ZXJ9IGZyb20gJy4vdXJsX3Jlc29sdmVyJztcbmltcG9ydCB7U3luY0FzeW5jLCBpc0RlZmluZWQsIHN0cmluZ2lmeSwgc3ludGF4RXJyb3J9IGZyb20gJy4vdXRpbCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJlbm9ybWFsaXplZFRlbXBsYXRlTWV0YWRhdGEge1xuICBuZ01vZHVsZVR5cGU6IGFueTtcbiAgY29tcG9uZW50VHlwZTogYW55O1xuICBtb2R1bGVVcmw6IHN0cmluZztcbiAgdGVtcGxhdGU6IHN0cmluZ3xudWxsO1xuICB0ZW1wbGF0ZVVybDogc3RyaW5nfG51bGw7XG4gIHN0eWxlczogc3RyaW5nW107XG4gIHN0eWxlVXJsczogc3RyaW5nW107XG4gIGludGVycG9sYXRpb246IFtzdHJpbmcsIHN0cmluZ118bnVsbDtcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb258bnVsbDtcbiAgYW5pbWF0aW9uczogYW55W107XG4gIHByZXNlcnZlV2hpdGVzcGFjZXM6IGJvb2xlYW58bnVsbDtcbn1cblxuZXhwb3J0IGNsYXNzIERpcmVjdGl2ZU5vcm1hbGl6ZXIge1xuICBwcml2YXRlIF9yZXNvdXJjZUxvYWRlckNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIFN5bmNBc3luYzxzdHJpbmc+PigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHJpdmF0ZSBfcmVzb3VyY2VMb2FkZXI6IFJlc291cmNlTG9hZGVyLCBwcml2YXRlIF91cmxSZXNvbHZlcjogVXJsUmVzb2x2ZXIsXG4gICAgICBwcml2YXRlIF9odG1sUGFyc2VyOiBIdG1sUGFyc2VyLCBwcml2YXRlIF9jb25maWc6IENvbXBpbGVyQ29uZmlnKSB7fVxuXG4gIGNsZWFyQ2FjaGUoKTogdm9pZCB7IHRoaXMuX3Jlc291cmNlTG9hZGVyQ2FjaGUuY2xlYXIoKTsgfVxuXG4gIGNsZWFyQ2FjaGVGb3Iobm9ybWFsaXplZERpcmVjdGl2ZTogQ29tcGlsZURpcmVjdGl2ZU1ldGFkYXRhKTogdm9pZCB7XG4gICAgaWYgKCFub3JtYWxpemVkRGlyZWN0aXZlLmlzQ29tcG9uZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHRlbXBsYXRlID0gbm9ybWFsaXplZERpcmVjdGl2ZS50ZW1wbGF0ZSAhO1xuICAgIHRoaXMuX3Jlc291cmNlTG9hZGVyQ2FjaGUuZGVsZXRlKHRlbXBsYXRlLnRlbXBsYXRlVXJsICEpO1xuICAgIHRlbXBsYXRlLmV4dGVybmFsU3R5bGVzaGVldHMuZm9yRWFjaChcbiAgICAgICAgKHN0eWxlc2hlZXQpID0+IHsgdGhpcy5fcmVzb3VyY2VMb2FkZXJDYWNoZS5kZWxldGUoc3R5bGVzaGVldC5tb2R1bGVVcmwgISk7IH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfZmV0Y2godXJsOiBzdHJpbmcpOiBTeW5jQXN5bmM8c3RyaW5nPiB7XG4gICAgbGV0IHJlc3VsdCA9IHRoaXMuX3Jlc291cmNlTG9hZGVyQ2FjaGUuZ2V0KHVybCk7XG4gICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgIHJlc3VsdCA9IHRoaXMuX3Jlc291cmNlTG9hZGVyLmdldCh1cmwpO1xuICAgICAgdGhpcy5fcmVzb3VyY2VMb2FkZXJDYWNoZS5zZXQodXJsLCByZXN1bHQpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgbm9ybWFsaXplVGVtcGxhdGUocHJlbm9ybURhdGE6IFByZW5vcm1hbGl6ZWRUZW1wbGF0ZU1ldGFkYXRhKTpcbiAgICAgIFN5bmNBc3luYzxDb21waWxlVGVtcGxhdGVNZXRhZGF0YT4ge1xuICAgIGlmIChpc0RlZmluZWQocHJlbm9ybURhdGEudGVtcGxhdGUpKSB7XG4gICAgICBpZiAoaXNEZWZpbmVkKHByZW5vcm1EYXRhLnRlbXBsYXRlVXJsKSkge1xuICAgICAgICB0aHJvdyBzeW50YXhFcnJvcihcbiAgICAgICAgICAgIGAnJHtzdHJpbmdpZnkocHJlbm9ybURhdGEuY29tcG9uZW50VHlwZSl9JyBjb21wb25lbnQgY2Fubm90IGRlZmluZSBib3RoIHRlbXBsYXRlIGFuZCB0ZW1wbGF0ZVVybGApO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBwcmVub3JtRGF0YS50ZW1wbGF0ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgc3ludGF4RXJyb3IoXG4gICAgICAgICAgICBgVGhlIHRlbXBsYXRlIHNwZWNpZmllZCBmb3IgY29tcG9uZW50ICR7c3RyaW5naWZ5KHByZW5vcm1EYXRhLmNvbXBvbmVudFR5cGUpfSBpcyBub3QgYSBzdHJpbmdgKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzRGVmaW5lZChwcmVub3JtRGF0YS50ZW1wbGF0ZVVybCkpIHtcbiAgICAgIGlmICh0eXBlb2YgcHJlbm9ybURhdGEudGVtcGxhdGVVcmwgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IHN5bnRheEVycm9yKFxuICAgICAgICAgICAgYFRoZSB0ZW1wbGF0ZVVybCBzcGVjaWZpZWQgZm9yIGNvbXBvbmVudCAke3N0cmluZ2lmeShwcmVub3JtRGF0YS5jb21wb25lbnRUeXBlKX0gaXMgbm90IGEgc3RyaW5nYCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IHN5bnRheEVycm9yKFxuICAgICAgICAgIGBObyB0ZW1wbGF0ZSBzcGVjaWZpZWQgZm9yIGNvbXBvbmVudCAke3N0cmluZ2lmeShwcmVub3JtRGF0YS5jb21wb25lbnRUeXBlKX1gKTtcbiAgICB9XG5cbiAgICBpZiAoaXNEZWZpbmVkKHByZW5vcm1EYXRhLnByZXNlcnZlV2hpdGVzcGFjZXMpICYmXG4gICAgICAgIHR5cGVvZiBwcmVub3JtRGF0YS5wcmVzZXJ2ZVdoaXRlc3BhY2VzICE9PSAnYm9vbGVhbicpIHtcbiAgICAgIHRocm93IHN5bnRheEVycm9yKFxuICAgICAgICAgIGBUaGUgcHJlc2VydmVXaGl0ZXNwYWNlcyBvcHRpb24gZm9yIGNvbXBvbmVudCAke3N0cmluZ2lmeShwcmVub3JtRGF0YS5jb21wb25lbnRUeXBlKX0gbXVzdCBiZSBhIGJvb2xlYW5gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gU3luY0FzeW5jLnRoZW4oXG4gICAgICAgIHRoaXMuX3ByZVBhcnNlVGVtcGxhdGUocHJlbm9ybURhdGEpLFxuICAgICAgICAocHJlcGFyc2VkVGVtcGxhdGUpID0+IHRoaXMuX25vcm1hbGl6ZVRlbXBsYXRlTWV0YWRhdGEocHJlbm9ybURhdGEsIHByZXBhcnNlZFRlbXBsYXRlKSk7XG4gIH1cblxuICBwcml2YXRlIF9wcmVQYXJzZVRlbXBsYXRlKHByZW5vbURhdGE6IFByZW5vcm1hbGl6ZWRUZW1wbGF0ZU1ldGFkYXRhKTpcbiAgICAgIFN5bmNBc3luYzxQcmVwYXJzZWRUZW1wbGF0ZT4ge1xuICAgIGxldCB0ZW1wbGF0ZTogU3luY0FzeW5jPHN0cmluZz47XG4gICAgbGV0IHRlbXBsYXRlVXJsOiBzdHJpbmc7XG4gICAgaWYgKHByZW5vbURhdGEudGVtcGxhdGUgIT0gbnVsbCkge1xuICAgICAgdGVtcGxhdGUgPSBwcmVub21EYXRhLnRlbXBsYXRlO1xuICAgICAgdGVtcGxhdGVVcmwgPSBwcmVub21EYXRhLm1vZHVsZVVybDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGVtcGxhdGVVcmwgPSB0aGlzLl91cmxSZXNvbHZlci5yZXNvbHZlKHByZW5vbURhdGEubW9kdWxlVXJsLCBwcmVub21EYXRhLnRlbXBsYXRlVXJsICEpO1xuICAgICAgdGVtcGxhdGUgPSB0aGlzLl9mZXRjaCh0ZW1wbGF0ZVVybCk7XG4gICAgfVxuICAgIHJldHVybiBTeW5jQXN5bmMudGhlbihcbiAgICAgICAgdGVtcGxhdGUsICh0ZW1wbGF0ZSkgPT4gdGhpcy5fcHJlcGFyc2VMb2FkZWRUZW1wbGF0ZShwcmVub21EYXRhLCB0ZW1wbGF0ZSwgdGVtcGxhdGVVcmwpKTtcbiAgfVxuXG4gIHByaXZhdGUgX3ByZXBhcnNlTG9hZGVkVGVtcGxhdGUoXG4gICAgICBwcmVub3JtRGF0YTogUHJlbm9ybWFsaXplZFRlbXBsYXRlTWV0YWRhdGEsIHRlbXBsYXRlOiBzdHJpbmcsXG4gICAgICB0ZW1wbGF0ZUFic1VybDogc3RyaW5nKTogUHJlcGFyc2VkVGVtcGxhdGUge1xuICAgIGNvbnN0IGlzSW5saW5lID0gISFwcmVub3JtRGF0YS50ZW1wbGF0ZTtcbiAgICBjb25zdCBpbnRlcnBvbGF0aW9uQ29uZmlnID0gSW50ZXJwb2xhdGlvbkNvbmZpZy5mcm9tQXJyYXkocHJlbm9ybURhdGEuaW50ZXJwb2xhdGlvbiAhKTtcbiAgICBjb25zdCByb290Tm9kZXNBbmRFcnJvcnMgPSB0aGlzLl9odG1sUGFyc2VyLnBhcnNlKFxuICAgICAgICB0ZW1wbGF0ZSxcbiAgICAgICAgdGVtcGxhdGVTb3VyY2VVcmwoXG4gICAgICAgICAgICB7cmVmZXJlbmNlOiBwcmVub3JtRGF0YS5uZ01vZHVsZVR5cGV9LCB7dHlwZToge3JlZmVyZW5jZTogcHJlbm9ybURhdGEuY29tcG9uZW50VHlwZX19LFxuICAgICAgICAgICAge2lzSW5saW5lLCB0ZW1wbGF0ZVVybDogdGVtcGxhdGVBYnNVcmx9KSxcbiAgICAgICAgdHJ1ZSwgaW50ZXJwb2xhdGlvbkNvbmZpZyk7XG4gICAgaWYgKHJvb3ROb2Rlc0FuZEVycm9ycy5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgZXJyb3JTdHJpbmcgPSByb290Tm9kZXNBbmRFcnJvcnMuZXJyb3JzLmpvaW4oJ1xcbicpO1xuICAgICAgdGhyb3cgc3ludGF4RXJyb3IoYFRlbXBsYXRlIHBhcnNlIGVycm9yczpcXG4ke2Vycm9yU3RyaW5nfWApO1xuICAgIH1cblxuICAgIGNvbnN0IHRlbXBsYXRlTWV0YWRhdGFTdHlsZXMgPSB0aGlzLl9ub3JtYWxpemVTdHlsZXNoZWV0KG5ldyBDb21waWxlU3R5bGVzaGVldE1ldGFkYXRhKFxuICAgICAgICB7c3R5bGVzOiBwcmVub3JtRGF0YS5zdHlsZXMsIG1vZHVsZVVybDogcHJlbm9ybURhdGEubW9kdWxlVXJsfSkpO1xuXG4gICAgY29uc3QgdmlzaXRvciA9IG5ldyBUZW1wbGF0ZVByZXBhcnNlVmlzaXRvcigpO1xuICAgIGh0bWwudmlzaXRBbGwodmlzaXRvciwgcm9vdE5vZGVzQW5kRXJyb3JzLnJvb3ROb2Rlcyk7XG4gICAgY29uc3QgdGVtcGxhdGVTdHlsZXMgPSB0aGlzLl9ub3JtYWxpemVTdHlsZXNoZWV0KG5ldyBDb21waWxlU3R5bGVzaGVldE1ldGFkYXRhKFxuICAgICAgICB7c3R5bGVzOiB2aXNpdG9yLnN0eWxlcywgc3R5bGVVcmxzOiB2aXNpdG9yLnN0eWxlVXJscywgbW9kdWxlVXJsOiB0ZW1wbGF0ZUFic1VybH0pKTtcblxuICAgIGNvbnN0IHN0eWxlcyA9IHRlbXBsYXRlTWV0YWRhdGFTdHlsZXMuc3R5bGVzLmNvbmNhdCh0ZW1wbGF0ZVN0eWxlcy5zdHlsZXMpO1xuXG4gICAgY29uc3QgaW5saW5lU3R5bGVVcmxzID0gdGVtcGxhdGVNZXRhZGF0YVN0eWxlcy5zdHlsZVVybHMuY29uY2F0KHRlbXBsYXRlU3R5bGVzLnN0eWxlVXJscyk7XG4gICAgY29uc3Qgc3R5bGVVcmxzID0gdGhpc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAuX25vcm1hbGl6ZVN0eWxlc2hlZXQobmV3IENvbXBpbGVTdHlsZXNoZWV0TWV0YWRhdGEoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3R5bGVVcmxzOiBwcmVub3JtRGF0YS5zdHlsZVVybHMsIG1vZHVsZVVybDogcHJlbm9ybURhdGEubW9kdWxlVXJsfSkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5zdHlsZVVybHM7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRlbXBsYXRlLFxuICAgICAgdGVtcGxhdGVVcmw6IHRlbXBsYXRlQWJzVXJsLCBpc0lubGluZSxcbiAgICAgIGh0bWxBc3Q6IHJvb3ROb2Rlc0FuZEVycm9ycywgc3R5bGVzLCBpbmxpbmVTdHlsZVVybHMsIHN0eWxlVXJscyxcbiAgICAgIG5nQ29udGVudFNlbGVjdG9yczogdmlzaXRvci5uZ0NvbnRlbnRTZWxlY3RvcnMsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgX25vcm1hbGl6ZVRlbXBsYXRlTWV0YWRhdGEoXG4gICAgICBwcmVub3JtRGF0YTogUHJlbm9ybWFsaXplZFRlbXBsYXRlTWV0YWRhdGEsXG4gICAgICBwcmVwYXJzZWRUZW1wbGF0ZTogUHJlcGFyc2VkVGVtcGxhdGUpOiBTeW5jQXN5bmM8Q29tcGlsZVRlbXBsYXRlTWV0YWRhdGE+IHtcbiAgICByZXR1cm4gU3luY0FzeW5jLnRoZW4oXG4gICAgICAgIHRoaXMuX2xvYWRNaXNzaW5nRXh0ZXJuYWxTdHlsZXNoZWV0cyhcbiAgICAgICAgICAgIHByZXBhcnNlZFRlbXBsYXRlLnN0eWxlVXJscy5jb25jYXQocHJlcGFyc2VkVGVtcGxhdGUuaW5saW5lU3R5bGVVcmxzKSksXG4gICAgICAgIChleHRlcm5hbFN0eWxlc2hlZXRzKSA9PiB0aGlzLl9ub3JtYWxpemVMb2FkZWRUZW1wbGF0ZU1ldGFkYXRhKFxuICAgICAgICAgICAgcHJlbm9ybURhdGEsIHByZXBhcnNlZFRlbXBsYXRlLCBleHRlcm5hbFN0eWxlc2hlZXRzKSk7XG4gIH1cblxuICBwcml2YXRlIF9ub3JtYWxpemVMb2FkZWRUZW1wbGF0ZU1ldGFkYXRhKFxuICAgICAgcHJlbm9ybURhdGE6IFByZW5vcm1hbGl6ZWRUZW1wbGF0ZU1ldGFkYXRhLCBwcmVwYXJzZWRUZW1wbGF0ZTogUHJlcGFyc2VkVGVtcGxhdGUsXG4gICAgICBzdHlsZXNoZWV0czogTWFwPHN0cmluZywgQ29tcGlsZVN0eWxlc2hlZXRNZXRhZGF0YT4pOiBDb21waWxlVGVtcGxhdGVNZXRhZGF0YSB7XG4gICAgLy8gQWxnb3JpdGhtOlxuICAgIC8vIC0gcHJvZHVjZSBleGFjdGx5IDEgZW50cnkgcGVyIG9yaWdpbmFsIHN0eWxlVXJsIGluXG4gICAgLy8gQ29tcGlsZVRlbXBsYXRlTWV0YWRhdGEuZXh0ZXJuYWxTdHlsZXNoZWV0cyB3aXRoIGFsbCBzdHlsZXMgaW5saW5lZFxuICAgIC8vIC0gaW5saW5lIGFsbCBzdHlsZXMgdGhhdCBhcmUgcmVmZXJlbmNlZCBieSB0aGUgdGVtcGxhdGUgaW50byBDb21waWxlVGVtcGxhdGVNZXRhZGF0YS5zdHlsZXMuXG4gICAgLy8gUmVhc29uOiBiZSBhYmxlIHRvIGRldGVybWluZSBob3cgbWFueSBzdHlsZXNoZWV0cyB0aGVyZSBhcmUgZXZlbiB3aXRob3V0IGxvYWRpbmdcbiAgICAvLyB0aGUgdGVtcGxhdGUgbm9yIHRoZSBzdHlsZXNoZWV0cywgc28gd2UgY2FuIGNyZWF0ZSBhIHN0dWIgZm9yIFR5cGVTY3JpcHQgYWx3YXlzIHN5bmNocm9ub3VzbHlcbiAgICAvLyAoYXMgcmVzb3VyY2UgbG9hZGluZyBtYXkgYmUgYXN5bmMpXG5cbiAgICBjb25zdCBzdHlsZXMgPSBbLi4ucHJlcGFyc2VkVGVtcGxhdGUuc3R5bGVzXTtcbiAgICB0aGlzLl9pbmxpbmVTdHlsZXMocHJlcGFyc2VkVGVtcGxhdGUuaW5saW5lU3R5bGVVcmxzLCBzdHlsZXNoZWV0cywgc3R5bGVzKTtcbiAgICBjb25zdCBzdHlsZVVybHMgPSBwcmVwYXJzZWRUZW1wbGF0ZS5zdHlsZVVybHM7XG5cbiAgICBjb25zdCBleHRlcm5hbFN0eWxlc2hlZXRzID0gc3R5bGVVcmxzLm1hcChzdHlsZVVybCA9PiB7XG4gICAgICBjb25zdCBzdHlsZXNoZWV0ID0gc3R5bGVzaGVldHMuZ2V0KHN0eWxlVXJsKSAhO1xuICAgICAgY29uc3Qgc3R5bGVzID0gWy4uLnN0eWxlc2hlZXQuc3R5bGVzXTtcbiAgICAgIHRoaXMuX2lubGluZVN0eWxlcyhzdHlsZXNoZWV0LnN0eWxlVXJscywgc3R5bGVzaGVldHMsIHN0eWxlcyk7XG4gICAgICByZXR1cm4gbmV3IENvbXBpbGVTdHlsZXNoZWV0TWV0YWRhdGEoe21vZHVsZVVybDogc3R5bGVVcmwsIHN0eWxlczogc3R5bGVzfSk7XG4gICAgfSk7XG5cbiAgICBsZXQgZW5jYXBzdWxhdGlvbiA9IHByZW5vcm1EYXRhLmVuY2Fwc3VsYXRpb247XG4gICAgaWYgKGVuY2Fwc3VsYXRpb24gPT0gbnVsbCkge1xuICAgICAgZW5jYXBzdWxhdGlvbiA9IHRoaXMuX2NvbmZpZy5kZWZhdWx0RW5jYXBzdWxhdGlvbjtcbiAgICB9XG4gICAgaWYgKGVuY2Fwc3VsYXRpb24gPT09IFZpZXdFbmNhcHN1bGF0aW9uLkVtdWxhdGVkICYmIHN0eWxlcy5sZW5ndGggPT09IDAgJiZcbiAgICAgICAgc3R5bGVVcmxzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgZW5jYXBzdWxhdGlvbiA9IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmU7XG4gICAgfVxuICAgIHJldHVybiBuZXcgQ29tcGlsZVRlbXBsYXRlTWV0YWRhdGEoe1xuICAgICAgZW5jYXBzdWxhdGlvbixcbiAgICAgIHRlbXBsYXRlOiBwcmVwYXJzZWRUZW1wbGF0ZS50ZW1wbGF0ZSxcbiAgICAgIHRlbXBsYXRlVXJsOiBwcmVwYXJzZWRUZW1wbGF0ZS50ZW1wbGF0ZVVybCxcbiAgICAgIGh0bWxBc3Q6IHByZXBhcnNlZFRlbXBsYXRlLmh0bWxBc3QsIHN0eWxlcywgc3R5bGVVcmxzLFxuICAgICAgbmdDb250ZW50U2VsZWN0b3JzOiBwcmVwYXJzZWRUZW1wbGF0ZS5uZ0NvbnRlbnRTZWxlY3RvcnMsXG4gICAgICBhbmltYXRpb25zOiBwcmVub3JtRGF0YS5hbmltYXRpb25zLFxuICAgICAgaW50ZXJwb2xhdGlvbjogcHJlbm9ybURhdGEuaW50ZXJwb2xhdGlvbixcbiAgICAgIGlzSW5saW5lOiBwcmVwYXJzZWRUZW1wbGF0ZS5pc0lubGluZSwgZXh0ZXJuYWxTdHlsZXNoZWV0cyxcbiAgICAgIHByZXNlcnZlV2hpdGVzcGFjZXM6IHByZXNlcnZlV2hpdGVzcGFjZXNEZWZhdWx0KFxuICAgICAgICAgIHByZW5vcm1EYXRhLnByZXNlcnZlV2hpdGVzcGFjZXMsIHRoaXMuX2NvbmZpZy5wcmVzZXJ2ZVdoaXRlc3BhY2VzKSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2lubGluZVN0eWxlcyhcbiAgICAgIHN0eWxlVXJsczogc3RyaW5nW10sIHN0eWxlc2hlZXRzOiBNYXA8c3RyaW5nLCBDb21waWxlU3R5bGVzaGVldE1ldGFkYXRhPixcbiAgICAgIHRhcmdldFN0eWxlczogc3RyaW5nW10pIHtcbiAgICBzdHlsZVVybHMuZm9yRWFjaChzdHlsZVVybCA9PiB7XG4gICAgICBjb25zdCBzdHlsZXNoZWV0ID0gc3R5bGVzaGVldHMuZ2V0KHN0eWxlVXJsKSAhO1xuICAgICAgc3R5bGVzaGVldC5zdHlsZXMuZm9yRWFjaChzdHlsZSA9PiB0YXJnZXRTdHlsZXMucHVzaChzdHlsZSkpO1xuICAgICAgdGhpcy5faW5saW5lU3R5bGVzKHN0eWxlc2hlZXQuc3R5bGVVcmxzLCBzdHlsZXNoZWV0cywgdGFyZ2V0U3R5bGVzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2xvYWRNaXNzaW5nRXh0ZXJuYWxTdHlsZXNoZWV0cyhcbiAgICAgIHN0eWxlVXJsczogc3RyaW5nW10sXG4gICAgICBsb2FkZWRTdHlsZXNoZWV0czpcbiAgICAgICAgICBNYXA8c3RyaW5nLCBDb21waWxlU3R5bGVzaGVldE1ldGFkYXRhPiA9IG5ldyBNYXA8c3RyaW5nLCBDb21waWxlU3R5bGVzaGVldE1ldGFkYXRhPigpKTpcbiAgICAgIFN5bmNBc3luYzxNYXA8c3RyaW5nLCBDb21waWxlU3R5bGVzaGVldE1ldGFkYXRhPj4ge1xuICAgIHJldHVybiBTeW5jQXN5bmMudGhlbihcbiAgICAgICAgU3luY0FzeW5jLmFsbChzdHlsZVVybHMuZmlsdGVyKChzdHlsZVVybCkgPT4gIWxvYWRlZFN0eWxlc2hlZXRzLmhhcyhzdHlsZVVybCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZVVybCA9PiBTeW5jQXN5bmMudGhlbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9mZXRjaChzdHlsZVVybCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGxvYWRlZFN0eWxlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHlsZXNoZWV0ID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9ub3JtYWxpemVTdHlsZXNoZWV0KG5ldyBDb21waWxlU3R5bGVzaGVldE1ldGFkYXRhKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3R5bGVzOiBbbG9hZGVkU3R5bGVdLCBtb2R1bGVVcmw6IHN0eWxlVXJsfSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkU3R5bGVzaGVldHMuc2V0KHN0eWxlVXJsLCBzdHlsZXNoZWV0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkTWlzc2luZ0V4dGVybmFsU3R5bGVzaGVldHMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGVzaGVldC5zdHlsZVVybHMsIGxvYWRlZFN0eWxlc2hlZXRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSkpLFxuICAgICAgICAoXykgPT4gbG9hZGVkU3R5bGVzaGVldHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBfbm9ybWFsaXplU3R5bGVzaGVldChzdHlsZXNoZWV0OiBDb21waWxlU3R5bGVzaGVldE1ldGFkYXRhKTogQ29tcGlsZVN0eWxlc2hlZXRNZXRhZGF0YSB7XG4gICAgY29uc3QgbW9kdWxlVXJsID0gc3R5bGVzaGVldC5tb2R1bGVVcmwgITtcbiAgICBjb25zdCBhbGxTdHlsZVVybHMgPSBzdHlsZXNoZWV0LnN0eWxlVXJscy5maWx0ZXIoaXNTdHlsZVVybFJlc29sdmFibGUpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAodXJsID0+IHRoaXMuX3VybFJlc29sdmVyLnJlc29sdmUobW9kdWxlVXJsLCB1cmwpKTtcblxuICAgIGNvbnN0IGFsbFN0eWxlcyA9IHN0eWxlc2hlZXQuc3R5bGVzLm1hcChzdHlsZSA9PiB7XG4gICAgICBjb25zdCBzdHlsZVdpdGhJbXBvcnRzID0gZXh0cmFjdFN0eWxlVXJscyh0aGlzLl91cmxSZXNvbHZlciwgbW9kdWxlVXJsLCBzdHlsZSk7XG4gICAgICBhbGxTdHlsZVVybHMucHVzaCguLi5zdHlsZVdpdGhJbXBvcnRzLnN0eWxlVXJscyk7XG4gICAgICByZXR1cm4gc3R5bGVXaXRoSW1wb3J0cy5zdHlsZTtcbiAgICB9KTtcblxuICAgIHJldHVybiBuZXcgQ29tcGlsZVN0eWxlc2hlZXRNZXRhZGF0YShcbiAgICAgICAge3N0eWxlczogYWxsU3R5bGVzLCBzdHlsZVVybHM6IGFsbFN0eWxlVXJscywgbW9kdWxlVXJsOiBtb2R1bGVVcmx9KTtcbiAgfVxufVxuXG5pbnRlcmZhY2UgUHJlcGFyc2VkVGVtcGxhdGUge1xuICB0ZW1wbGF0ZTogc3RyaW5nO1xuICB0ZW1wbGF0ZVVybDogc3RyaW5nO1xuICBpc0lubGluZTogYm9vbGVhbjtcbiAgaHRtbEFzdDogSHRtbFBhcnNlVHJlZVJlc3VsdDtcbiAgc3R5bGVzOiBzdHJpbmdbXTtcbiAgaW5saW5lU3R5bGVVcmxzOiBzdHJpbmdbXTtcbiAgc3R5bGVVcmxzOiBzdHJpbmdbXTtcbiAgbmdDb250ZW50U2VsZWN0b3JzOiBzdHJpbmdbXTtcbn1cblxuY2xhc3MgVGVtcGxhdGVQcmVwYXJzZVZpc2l0b3IgaW1wbGVtZW50cyBodG1sLlZpc2l0b3Ige1xuICBuZ0NvbnRlbnRTZWxlY3RvcnM6IHN0cmluZ1tdID0gW107XG4gIHN0eWxlczogc3RyaW5nW10gPSBbXTtcbiAgc3R5bGVVcmxzOiBzdHJpbmdbXSA9IFtdO1xuICBuZ05vbkJpbmRhYmxlU3RhY2tDb3VudDogbnVtYmVyID0gMDtcblxuICB2aXNpdEVsZW1lbnQoYXN0OiBodG1sLkVsZW1lbnQsIGNvbnRleHQ6IGFueSk6IGFueSB7XG4gICAgY29uc3QgcHJlcGFyc2VkRWxlbWVudCA9IHByZXBhcnNlRWxlbWVudChhc3QpO1xuICAgIHN3aXRjaCAocHJlcGFyc2VkRWxlbWVudC50eXBlKSB7XG4gICAgICBjYXNlIFByZXBhcnNlZEVsZW1lbnRUeXBlLk5HX0NPTlRFTlQ6XG4gICAgICAgIGlmICh0aGlzLm5nTm9uQmluZGFibGVTdGFja0NvdW50ID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5uZ0NvbnRlbnRTZWxlY3RvcnMucHVzaChwcmVwYXJzZWRFbGVtZW50LnNlbGVjdEF0dHIpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQcmVwYXJzZWRFbGVtZW50VHlwZS5TVFlMRTpcbiAgICAgICAgbGV0IHRleHRDb250ZW50ID0gJyc7XG4gICAgICAgIGFzdC5jaGlsZHJlbi5mb3JFYWNoKGNoaWxkID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBodG1sLlRleHQpIHtcbiAgICAgICAgICAgIHRleHRDb250ZW50ICs9IGNoaWxkLnZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3R5bGVzLnB1c2godGV4dENvbnRlbnQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUHJlcGFyc2VkRWxlbWVudFR5cGUuU1RZTEVTSEVFVDpcbiAgICAgICAgdGhpcy5zdHlsZVVybHMucHVzaChwcmVwYXJzZWRFbGVtZW50LmhyZWZBdHRyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgaWYgKHByZXBhcnNlZEVsZW1lbnQubm9uQmluZGFibGUpIHtcbiAgICAgIHRoaXMubmdOb25CaW5kYWJsZVN0YWNrQ291bnQrKztcbiAgICB9XG4gICAgaHRtbC52aXNpdEFsbCh0aGlzLCBhc3QuY2hpbGRyZW4pO1xuICAgIGlmIChwcmVwYXJzZWRFbGVtZW50Lm5vbkJpbmRhYmxlKSB7XG4gICAgICB0aGlzLm5nTm9uQmluZGFibGVTdGFja0NvdW50LS07XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdmlzaXRFeHBhbnNpb24oYXN0OiBodG1sLkV4cGFuc2lvbiwgY29udGV4dDogYW55KTogYW55IHsgaHRtbC52aXNpdEFsbCh0aGlzLCBhc3QuY2FzZXMpOyB9XG5cbiAgdmlzaXRFeHBhbnNpb25DYXNlKGFzdDogaHRtbC5FeHBhbnNpb25DYXNlLCBjb250ZXh0OiBhbnkpOiBhbnkge1xuICAgIGh0bWwudmlzaXRBbGwodGhpcywgYXN0LmV4cHJlc3Npb24pO1xuICB9XG5cbiAgdmlzaXRDb21tZW50KGFzdDogaHRtbC5Db21tZW50LCBjb250ZXh0OiBhbnkpOiBhbnkgeyByZXR1cm4gbnVsbDsgfVxuICB2aXNpdEF0dHJpYnV0ZShhc3Q6IGh0bWwuQXR0cmlidXRlLCBjb250ZXh0OiBhbnkpOiBhbnkgeyByZXR1cm4gbnVsbDsgfVxuICB2aXNpdFRleHQoYXN0OiBodG1sLlRleHQsIGNvbnRleHQ6IGFueSk6IGFueSB7IHJldHVybiBudWxsOyB9XG59XG4iXX0=