@angular/core
Version:
Angular - the core framework
118 lines • 19.9 kB
JavaScript
/**
* @license
* Copyright Google LLC 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 { RuntimeError } from '../errors';
import { getComponentDef } from './definition';
import { getDeclarationComponentDef } from './instructions/element_validation';
import { TVIEW } from './interfaces/view';
import { INTERPOLATION_DELIMITER } from './util/misc_utils';
import { stringifyForError } from './util/stringify_utils';
/**
* The max length of the string representation of a value in an error message
*/
const VALUE_STRING_LENGTH_LIMIT = 200;
/** Verifies that a given type is a Standalone Component. */
export function assertStandaloneComponentType(type) {
assertComponentDef(type);
const componentDef = getComponentDef(type);
if (!componentDef.standalone) {
throw new RuntimeError(907 /* RuntimeErrorCode.TYPE_IS_NOT_STANDALONE */, `The ${stringifyForError(type)} component is not marked as standalone, ` +
`but Angular expects to have a standalone component here. ` +
`Please make sure the ${stringifyForError(type)} component has ` +
`the \`standalone: true\` flag in the decorator.`);
}
}
/** Verifies whether a given type is a component */
export function assertComponentDef(type) {
if (!getComponentDef(type)) {
throw new RuntimeError(906 /* RuntimeErrorCode.MISSING_GENERATED_DEF */, `The ${stringifyForError(type)} is not an Angular component, ` +
`make sure it has the \`@Component\` decorator.`);
}
}
/** Called when there are multiple component selectors that match a given node */
export function throwMultipleComponentError(tNode, first, second) {
throw new RuntimeError(-300 /* RuntimeErrorCode.MULTIPLE_COMPONENTS_MATCH */, `Multiple components match node with tagname ${tNode.value}: ` +
`${stringifyForError(first)} and ` +
`${stringifyForError(second)}`);
}
/** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */
export function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName, lView) {
const hostComponentDef = getDeclarationComponentDef(lView);
const componentClassName = hostComponentDef?.type?.name;
const field = propName ? ` for '${propName}'` : '';
let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${formatValue(oldValue)}'. Current value: '${formatValue(currValue)}'.${componentClassName ? ` Expression location: ${componentClassName} component` : ''}`;
if (creationMode) {
msg +=
` It seems like the view has been created after its parent and its children have been dirty checked.` +
` Has it been created in a change detection hook?`;
}
throw new RuntimeError(-100 /* RuntimeErrorCode.EXPRESSION_CHANGED_AFTER_CHECKED */, msg);
}
function formatValue(value) {
let strValue = String(value);
// JSON.stringify will throw on circular references
try {
if (Array.isArray(value) || strValue === '[object Object]') {
strValue = JSON.stringify(value);
}
}
catch (error) { }
return strValue.length > VALUE_STRING_LENGTH_LIMIT
? strValue.substring(0, VALUE_STRING_LENGTH_LIMIT) + '…'
: strValue;
}
function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER);
let oldValue = prefix, newValue = prefix;
for (let i = 0; i < chunks.length; i++) {
const slotIdx = rootIndex + i;
oldValue += `${lView[slotIdx]}${chunks[i]}`;
newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`;
}
return { propName, oldValue, newValue };
}
/**
* Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError:
* - property name (for property bindings or interpolations)
* - old and new values, enriched using information from metadata
*
* More information on the metadata storage format can be found in `storePropertyBindingMetadata`
* function description.
*/
export function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) {
const tData = lView[TVIEW].data;
const metadata = tData[bindingIndex];
if (typeof metadata === 'string') {
// metadata for property interpolation
if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) {
return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue);
}
// metadata for property binding
return { propName: metadata, oldValue, newValue };
}
// metadata is not available for this expression, check if this expression is a part of the
// property interpolation by going from the current binding index left and look for a string that
// contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
// [..., 'id�Prefix � and � suffix', null, null, null, ...]
if (metadata === null) {
let idx = bindingIndex - 1;
while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
idx--;
}
const meta = tData[idx];
if (typeof meta === 'string') {
const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g'));
// first interpolation delimiter separates property name from interpolation parts (in case of
// property interpolations), so we subtract one from total number of found delimiters
if (matches && matches.length - 1 > bindingIndex - idx) {
return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue);
}
}
}
return { propName: undefined, oldValue, newValue };
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29yZS9zcmMvcmVuZGVyMy9lcnJvcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLFlBQVksRUFBbUIsTUFBTSxXQUFXLENBQUM7QUFHekQsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUM3QyxPQUFPLEVBQUMsMEJBQTBCLEVBQUMsTUFBTSxtQ0FBbUMsQ0FBQztBQUU3RSxPQUFPLEVBQVEsS0FBSyxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDL0MsT0FBTyxFQUFDLHVCQUF1QixFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDMUQsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFFekQ7O0dBRUc7QUFDSCxNQUFNLHlCQUF5QixHQUFHLEdBQUcsQ0FBQztBQUV0Qyw0REFBNEQ7QUFDNUQsTUFBTSxVQUFVLDZCQUE2QixDQUFDLElBQW1CO0lBQy9ELGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pCLE1BQU0sWUFBWSxHQUFHLGVBQWUsQ0FBQyxJQUFJLENBQUUsQ0FBQztJQUM1QyxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQzdCLE1BQU0sSUFBSSxZQUFZLG9EQUVwQixPQUFPLGlCQUFpQixDQUFDLElBQUksQ0FBQywwQ0FBMEM7WUFDdEUsMkRBQTJEO1lBQzNELHdCQUF3QixpQkFBaUIsQ0FBQyxJQUFJLENBQUMsaUJBQWlCO1lBQ2hFLGlEQUFpRCxDQUNwRCxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUM7QUFFRCxtREFBbUQ7QUFDbkQsTUFBTSxVQUFVLGtCQUFrQixDQUFDLElBQW1CO0lBQ3BELElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUMzQixNQUFNLElBQUksWUFB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QUN4QixJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzdCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsdUJBQXVCLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUNyRSw2RkFBNkY7WUFDN0YscUZBQXFGO1lBQ3JGLElBQUksT0FBTyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxHQUFHLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQztnQkFDdkQsT0FBTyxnQ0FBZ0MsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDcEYsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxFQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBQyxDQUFDO0FBQ25ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtSdW50aW1lRXJyb3IsIFJ1bnRpbWVFcnJvckNvZGV9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQge1R5cGV9IGZyb20gJy4uL2ludGVyZmFjZS90eXBlJztcblxuaW1wb3J0IHtnZXRDb21wb25lbnREZWZ9IGZyb20gJy4vZGVmaW5pdGlvbic7XG5pbXBvcnQge2dldERlY2xhcmF0aW9uQ29tcG9uZW50RGVmfSBmcm9tICcuL2luc3RydWN0aW9ucy9lbGVtZW50X3ZhbGlkYXRpb24nO1xuaW1wb3J0IHtUTm9kZX0gZnJvbSAnLi9pbnRlcmZhY2VzL25vZGUnO1xuaW1wb3J0IHtMVmlldywgVFZJRVd9IGZyb20gJy4vaW50ZXJmYWNlcy92aWV3JztcbmltcG9ydCB7SU5URVJQT0xBVElPTl9ERUxJTUlURVJ9IGZyb20gJy4vdXRpbC9taXNjX3V0aWxzJztcbmltcG9ydCB7c3RyaW5naWZ5Rm9yRXJyb3J9IGZyb20gJy4vdXRpbC9zdHJpbmdpZnlfdXRpbHMnO1xuXG4vKipcbiAqIFRoZSBtYXggbGVuZ3RoIG9mIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSB2YWx1ZSBpbiBhbiBlcnJvciBtZXNzYWdlXG4gKi9cbmNvbnN0IFZBTFVFX1NUUklOR19MRU5HVEhfTElNSVQgPSAyMDA7XG5cbi8qKiBWZXJpZmllcyB0aGF0IGEgZ2l2ZW4gdHlwZSBpcyBhIFN0YW5kYWxvbmUgQ29tcG9uZW50LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydFN0YW5kYWxvbmVDb21wb25lbnRUeXBlKHR5cGU6IFR5cGU8dW5rbm93bj4pIHtcbiAgYXNzZXJ0Q29tcG9uZW50RGVmKHR5cGUpO1xuICBjb25zdCBjb21wb25lbnREZWYgPSBnZXRDb21wb25lbnREZWYodHlwZSkhO1xuICBpZiAoIWNvbXBvbmVudERlZi5zdGFuZGFsb25lKSB7XG4gICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcihcbiAgICAgIFJ1bnRpbWVFcnJvckNvZGUuVFlQRV9JU19OT1RfU1RBTkRBTE9ORSxcbiAgICAgIGBUaGUgJHtzdHJpbmdpZnlGb3JFcnJvcih0eXBlKX0gY29tcG9uZW50IGlzIG5vdCBtYXJrZWQgYXMgc3RhbmRhbG9uZSwgYCArXG4gICAgICAgIGBidXQgQW5ndWxhciBleHBlY3RzIHRvIGhhdmUgYSBzdGFuZGFsb25lIGNvbXBvbmVudCBoZXJlLiBgICtcbiAgICAgICAgYFBsZWFzZSBtYWtlIHN1cmUgdGhlICR7c3RyaW5naWZ5Rm9yRXJyb3IodHlwZSl9IGNvbXBvbmVudCBoYXMgYCArXG4gICAgICAgIGB0aGUgXFxgc3RhbmRhbG9uZTogdHJ1ZVxcYCBmbGFnIGluIHRoZSBkZWNvcmF0b3IuYCxcbiAgICApO1xuICB9XG59XG5cbi8qKiBWZXJpZmllcyB3aGV0aGVyIGEgZ2l2ZW4gdHlwZSBpcyBhIGNvbXBvbmVudCAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydENvbXBvbmVudERlZih0eXBlOiBUeXBlPHVua25vd24+KSB7XG4gIGlmICghZ2V0Q29tcG9uZW50RGVmKHR5cGUpKSB7XG4gICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcihcbiAgICAgIFJ1bnRpbWVFcnJvckNvZGUuTUlTU0lOR19HRU5FUkFURURfREVGLFxuICAgICAgYFRoZSAke3N0cmluZ2lmeUZvckVycm9yKHR5cGUpfSBpcyBub3QgYW4gQW5ndWxhciBjb21wb25lbnQsIGAgK1xuICAgICAgICBgbWFrZSBzdXJlIGl0IGhhcyB0aGUgXFxgQENvbXBvbmVudFxcYCBkZWNvcmF0b3IuYCxcbiAgICApO1xuICB9XG59XG5cbi8qKiBDYWxsZWQgd2hlbiB0aGVyZSBhcmUgbXVsdGlwbGUgY29tcG9uZW50IHNlbGVjdG9ycyB0aGF0IG1hdGNoIGEgZ2l2ZW4gbm9kZSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRocm93TXVsdGlwbGVDb21wb25lbnRFcnJvcihcbiAgdE5vZGU6IFROb2RlLFxuICBmaXJzdDogVHlwZTx1bmtub3duPixcbiAgc2Vjb25kOiBUeXBlPHVua25vd24+LFxuKTogbmV2ZXIge1xuICB0aHJvdyBuZXcgUnVudGltZUVycm9yKFxuICAgIFJ1bnRpbWVFcnJvckNvZGUuTVVMVElQTEVfQ09NUE9ORU5UU19NQVRDSCxcbiAgICBgTXVsdGlwbGUgY29tcG9uZW50cyBtYXRjaCBub2RlIHdpdGggdGFnbmFtZSAke3ROb2RlLnZhbHVlfTogYCArXG4gICAgICBgJHtzdHJpbmdpZnlGb3JFcnJvcihmaXJzdCl9IGFuZCBgICtcbiAgICAgIGAke3N0cmluZ2lmeUZvckVycm9yKHNlY29uZCl9YCxcbiAgKTtcbn1cblxuLyoqIFRocm93cyBhbiBFeHByZXNzaW9uQ2hhbmdlZEFmdGVyQ2hlY2tlZCBlcnJvciBpZiBjaGVja05vQ2hhbmdlcyBtb2RlIGlzIG9uLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRocm93RXJyb3JJZk5vQ2hhbmdlc01vZGUoXG4gIGNyZWF0aW9uTW9kZTogYm9vbGVhbixcbiAgb2xkVmFsdWU6IGFueSxcbiAgY3VyclZhbHVlOiBhbnksXG4gIHByb3BOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIGxWaWV3OiBMVmlldyxcbik6IG5ldmVyIHtcbiAgY29uc3QgaG9zdENvbXBvbmVudERlZiA9IGdldERlY2xhcmF0aW9uQ29tcG9uZW50RGVmKGxWaWV3KTtcbiAgY29uc3QgY29tcG9uZW50Q2xhc3NOYW1lID0gaG9zdENvbXBvbmVudERlZj8udHlwZT8ubmFtZTtcbiAgY29uc3QgZmllbGQgPSBwcm9wTmFtZSA/IGAgZm9yICcke3Byb3BOYW1lfSdgIDogJyc7XG4gIGxldCBtc2cgPSBgRXhwcmVzc2lvbkNoYW5nZWRBZnRlckl0SGFzQmVlbkNoZWNrZWRFcnJvcjogRXhwcmVzc2lvbiBoYXMgY2hhbmdlZCBhZnRlciBpdCB3YXMgY2hlY2tlZC4gUHJldmlvdXMgdmFsdWUke2ZpZWxkfTogJyR7Zm9ybWF0VmFsdWUob2xkVmFsdWUpfScuIEN1cnJlbnQgdmFsdWU6ICcke2Zvcm1hdFZhbHVlKGN1cnJWYWx1ZSl9Jy4ke1xuICAgIGNvbXBvbmVudENsYXNzTmFtZSA/IGAgRXhwcmVzc2lvbiBsb2NhdGlvbjogJHtjb21wb25lbnRDbGFzc05hbWV9IGNvbXBvbmVudGAgOiAnJ1xuICB9YDtcbiAgaWYgKGNyZWF0aW9uTW9kZSkge1xuICAgIG1zZyArPVxuICAgICAgYCBJdCBzZWVtcyBsaWtlIHRoZSB2aWV3IGhhcyBiZWVuIGNyZWF0ZWQgYWZ0ZXIgaXRzIHBhcmVudCBhbmQgaXRzIGNoaWxkcmVuIGhhdmUgYmVlbiBkaXJ0eSBjaGVja2VkLmAgK1xuICAgICAgYCBIYXMgaXQgYmVlbiBjcmVhdGVkIGluIGEgY2hhbmdlIGRldGVjdGlvbiBob29rP2A7XG4gIH1cbiAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcihSdW50aW1lRXJyb3JDb2RlLkVYUFJFU1NJT05fQ0hBTkdFRF9BRlRFUl9DSEVDS0VELCBtc2cpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRWYWx1ZSh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB7XG4gIGxldCBzdHJWYWx1ZTogc3RyaW5nID0gU3RyaW5nKHZhbHVlKTtcblxuICAvLyBKU09OLnN0cmluZ2lmeSB3aWxsIHRocm93IG9uIGNpcmN1bGFyIHJlZmVyZW5jZXNcbiAgdHJ5IHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgfHwgc3RyVmFsdWUgPT09ICdbb2JqZWN0IE9iamVjdF0nKSB7XG4gICAgICBzdHJWYWx1ZSA9IEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7fVxuICByZXR1cm4gc3RyVmFsdWUubGVuZ3RoID4gVkFMVUVfU1RSSU5HX0xFTkdUSF9MSU1JVFxuICAgID8gc3RyVmFsdWUuc3Vic3RyaW5nKDAsIFZBTFVFX1NUUklOR19MRU5HVEhfTElNSVQpICsgJ+KApidcbiAgICA6IHN0clZhbHVlO1xufVxuXG5mdW5jdGlvbiBjb25zdHJ1Y3REZXRhaWxzRm9ySW50ZXJwb2xhdGlvbihcbiAgbFZpZXc6IExWaWV3LFxuICByb290SW5kZXg6IG51bWJlcixcbiAgZXhwcmVzc2lvbkluZGV4OiBudW1iZXIsXG4gIG1ldGE6IHN0cmluZyxcbiAgY2hhbmdlZFZhbHVlOiBhbnksXG4pIHtcbiAgY29uc3QgW3Byb3BOYW1lLCBwcmVmaXgsIC4uLmNodW5rc10gPSBtZXRhLnNwbGl0KElOVEVSUE9MQVRJT05fREVMSU1JVEVSKTtcbiAgbGV0IG9sZFZhbHVlID0gcHJlZml4LFxuICAgIG5ld1ZhbHVlID0gcHJlZml4O1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGNodW5rcy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IHNsb3RJZHggPSByb290SW5kZXggKyBpO1xuICAgIG9sZFZhbHVlICs9IGAke2xWaWV3W3Nsb3RJZHhdfSR7Y2h1bmtzW2ldfWA7XG4gICAgbmV3VmFsdWUgKz0gYCR7c2xvdElkeCA9PT0gZXhwcmVzc2lvbkluZGV4ID8gY2hhbmdlZFZhbHVlIDogbFZpZXdbc2xvdElkeF19JHtjaHVua3NbaV19YDtcbiAgfVxuICByZXR1cm4ge3Byb3BOYW1lLCBvbGRWYWx1ZSwgbmV3VmFsdWV9O1xufVxuXG4vKipcbiAqIENvbnN0cnVjdHMgYW4gb2JqZWN0IHRoYXQgY29udGFpbnMgZGV0YWlscyBmb3IgdGhlIEV4cHJlc3Npb25DaGFuZ2VkQWZ0ZXJJdEhhc0JlZW5DaGVja2VkRXJyb3I6XG4gKiAtIHByb3BlcnR5IG5hbWUgKGZvciBwcm9wZXJ0eSBiaW5kaW5ncyBvciBpbnRlcnBvbGF0aW9ucylcbiAqIC0gb2xkIGFuZCBuZXcgdmFsdWVzLCBlbnJpY2hlZCB1c2luZyBpbmZvcm1hdGlvbiBmcm9tIG1ldGFkYXRhXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbiBvbiB0aGUgbWV0YWRhdGEgc3RvcmFnZSBmb3JtYXQgY2FuIGJlIGZvdW5kIGluIGBzdG9yZVByb3BlcnR5QmluZGluZ01ldGFkYXRhYFxuICogZnVuY3Rpb24gZGVzY3JpcHRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRFeHByZXNzaW9uQ2hhbmdlZEVycm9yRGV0YWlscyhcbiAgbFZpZXc6IExWaWV3LFxuICBiaW5kaW5nSW5kZXg6IG51bWJlcixcbiAgb2xkVmFsdWU6IGFueSxcbiAgbmV3VmFsdWU6IGFueSxcbik6IHtwcm9wTmFtZT86IHN0cmluZzsgb2xkVmFsdWU6IGFueTsgbmV3VmFsdWU6IGFueX0ge1xuICBjb25zdCB0RGF0YSA9IGxWaWV3W1RWSUVXXS5kYXRhO1xuICBjb25zdCBtZXRhZGF0YSA9IHREYXRhW2JpbmRpbmdJbmRleF07XG5cbiAgaWYgKHR5cGVvZiBtZXRhZGF0YSA9PT0gJ3N0cmluZycpIHtcbiAgICAvLyBtZXRhZGF0YSBmb3IgcHJvcGVydHkgaW50ZXJwb2xhdGlvblxuICAgIGlmIChtZXRhZGF0YS5pbmRleE9mKElOVEVSUE9MQVRJT05fREVMSU1JVEVSKSA+IC0xKSB7XG4gICAgICByZXR1cm4gY29uc3RydWN0RGV0YWlsc0ZvckludGVycG9sYXRpb24oXG4gICAgICAgIGxWaWV3LFxuICAgICAgICBiaW5kaW5nSW5kZXgsXG4gICAgICAgIGJpbmRpbmdJbmRleCxcbiAgICAgICAgbWV0YWRhdGEsXG4gICAgICAgIG5ld1ZhbHVlLFxuICAgICAgKTtcbiAgICB9XG4gICAgLy8gbWV0YWRhdGEgZm9yIHByb3BlcnR5IGJpbmRpbmdcbiAgICByZXR1cm4ge3Byb3BOYW1lOiBtZXRhZGF0YSwgb2xkVmFsdWUsIG5ld1ZhbHVlfTtcbiAgfVxuXG4gIC8vIG1ldGFkYXRhIGlzIG5vdCBhdmFpbGFibGUgZm9yIHRoaXMgZXhwcmVzc2lvbiwgY2hlY2sgaWYgdGhpcyBleHByZXNzaW9uIGlzIGEgcGFydCBvZiB0aGVcbiAgLy8gcHJvcGVydHkgaW50ZXJwb2xhdGlvbiBieSBnb2luZyBmcm9tIHRoZSBjdXJyZW50IGJpbmRpbmcgaW5kZXggbGVmdCBhbmQgbG9vayBmb3IgYSBzdHJpbmcgdGhhdFxuICAvLyBjb250YWlucyBJTlRFUlBPTEFUSU9OX0RFTElNSVRFUiwgdGhlIGxheW91dCBpbiB0Vmlldy5kYXRhIGZvciB0aGlzIGNhc2Ugd2lsbCBsb29rIGxpa2UgdGhpczpcbiAgLy8gWy4uLiwgJ2lk77+9UHJlZml4IO+/vSBhbmQg77+9IHN1ZmZpeCcsIG51bGwsIG51bGwsIG51bGwsIC4uLl1cbiAgaWYgKG1ldGFkYXRhID09PSBudWxsKSB7XG4gICAgbGV0IGlkeCA9IGJpbmRpbmdJbmRleCAtIDE7XG4gICAgd2hpbGUgKHR5cGVvZiB0RGF0YVtpZHhdICE9PSAnc3RyaW5nJyAmJiB0RGF0YVtpZHggKyAxXSA9PT0gbnVsbCkge1xuICAgICAgaWR4LS07XG4gICAgfVxuICAgIGNvbnN0IG1ldGEgPSB0RGF0YVtpZHhdO1xuICAgIGlmICh0eXBlb2YgbWV0YSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBtZXRhLm1hdGNoKG5ldyBSZWdFeHAoSU5URVJQT0xBVElPTl9ERUxJTUlURVIsICdnJykpO1xuICAgICAgLy8gZmlyc3QgaW50ZXJwb2xhdGlvbiBkZWxpbWl0ZXIgc2VwYXJhdGVzIHByb3BlcnR5IG5hbWUgZnJvbSBpbnRlcnBvbGF0aW9uIHBhcnRzIChpbiBjYXNlIG9mXG4gICAgICAvLyBwcm9wZXJ0eSBpbnRlcnBvbGF0aW9ucyksIHNvIHdlIHN1YnRyYWN0IG9uZSBmcm9tIHRvdGFsIG51bWJlciBvZiBmb3VuZCBkZWxpbWl0ZXJzXG4gICAgICBpZiAobWF0Y2hlcyAmJiBtYXRjaGVzLmxlbmd0aCAtIDEgPiBiaW5kaW5nSW5kZXggLSBpZHgpIHtcbiAgICAgICAgcmV0dXJuIGNvbnN0cnVjdERldGFpbHNGb3JJbnRlcnBvbGF0aW9uKGxWaWV3LCBpZHgsIGJpbmRpbmdJbmRleCwgbWV0YSwgbmV3VmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4ge3Byb3BOYW1lOiB1bmRlZmluZWQsIG9sZFZhbHVlLCBuZXdWYWx1ZX07XG59XG4iXX0=