@neo-one/smart-contract-compiler
Version:
NEO•ONE TypeScript smart contract compiler.
374 lines (373 loc) • 63.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const ts_utils_1 = require("@neo-one/ts-utils");
const utils_1 = require("@neo-one/utils");
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const typescript_1 = tslib_1.__importDefault(require("typescript"));
const utils_2 = require("../../utils");
const types_1 = require("./types");
const getMember = (sym, name) => ts_utils_1.tsUtils.symbol.getMemberOrThrow(sym, name);
const getExportOrMember = (sym, name) => {
const member = ts_utils_1.tsUtils.symbol.getMember(sym, name);
return member === undefined ? ts_utils_1.tsUtils.symbol.getExportOrThrow(sym, name) : member;
};
const findNonNull = (value) => value.find((val) => val !== undefined);
const throwIfNull = (value) => {
if (value == undefined) {
throw new Error('Something went wrong.');
}
return value;
};
class Builtins {
constructor(context) {
this.context = context;
this.builtinMembers = new Map();
this.allBuiltinMembers = new Map();
this.builtinInterfaces = new Map();
this.builtinValues = new Map();
this.builtinOverrides = new Map();
this.memoized = utils_2.createMemoized();
}
isBuiltinSymbol(symbol) {
return symbol !== undefined && (this.builtinValues.has(symbol) || this.builtinInterfaces.has(symbol));
}
isBuiltinIdentifier(value) {
return (this.getAnyInterfaceSymbolMaybe(value) !== undefined ||
this.getAnyTypeSymbolMaybe(value) !== undefined ||
this.getAnyValueSymbolMaybe(value) !== undefined);
}
isBuiltinFile(file) {
return this.getContract() === file;
}
getMember(value, prop) {
return this.memoized('get-member', `${utils_2.nodeKey(value)}:${utils_2.nodeKey(prop)}`, () => {
const propSymbol = this.context.analysis.getSymbol(prop);
if (propSymbol === undefined) {
return undefined;
}
const valueSymbol = this.context.analysis.getTypeSymbol(value);
if (valueSymbol === undefined) {
return this.allBuiltinMembers.get(propSymbol);
}
if (!ts_utils_1.tsUtils.guards.isSuperExpression(value)) {
const overridenMember = this.walkOverridesForMember(valueSymbol, propSymbol);
if (overridenMember !== undefined) {
return overridenMember;
}
}
const members = this.getAllMembers(valueSymbol);
return members.get(propSymbol);
});
}
getOnlyMember(value, name) {
return this.getOnlyMemberBase(value, name, (result) => result[1]);
}
getOnlyMemberSymbol(value, name) {
return throwIfNull(this.getOnlyMemberBase(value, name, (result) => result[0]));
}
getMembers(name, isMember, isEligible, symbolMembers = false) {
const filterPseudoSymbol = (symbol, key) => {
const symbolSymbol = this.getInterfaceSymbolBase('SymbolConstructor', this.getGlobals());
return ts_utils_1.tsUtils.symbol.getMember(symbolSymbol, key) !== symbol;
};
const isSymbolKey = (key) => key.startsWith('__@');
let testKey = (key) => !isSymbolKey(key);
let modifyKey = (key) => key;
if (symbolMembers) {
testKey = isSymbolKey;
modifyKey = (key) => key.slice(3);
}
const members = this.getAllMembers(this.getAnyInterfaceSymbol(name));
const mutableMembers = [];
members.forEach((builtin, memberSymbol) => {
const memberName = ts_utils_1.tsUtils.symbol.getName(memberSymbol);
if (isMember(builtin) &&
filterPseudoSymbol(memberSymbol, memberName) &&
testKey(memberName) &&
isEligible(builtin)) {
mutableMembers.push([modifyKey(memberName), builtin]);
}
});
return mutableMembers;
}
getInterface(value) {
const valueSymbol = this.context.analysis.getSymbol(value);
if (valueSymbol === undefined) {
return undefined;
}
return this.builtinInterfaces.get(valueSymbol);
}
getInterfaceSymbol(value) {
return this.getAnyInterfaceSymbol(value);
}
getValue(value) {
const valueSymbol = this.context.analysis.getSymbol(value);
if (valueSymbol === undefined) {
return undefined;
}
return this.builtinValues.get(valueSymbol);
}
getValueInterface(value) {
const builtinValue = this.getValue(value);
return builtinValue === undefined || !types_1.isBuiltinValueObject(builtinValue) ? undefined : builtinValue.type;
}
getValueSymbol(value) {
return this.getAnyValueSymbol(value);
}
getTypeSymbol(name) {
return this.getAnyTypeSymbol(name);
}
isInterface(node, testType, name) {
return this.memoized('is-interface', `${utils_2.typeKey(testType)}:${name}`, () => {
const symbol = this.context.analysis.getSymbolForType(node, testType);
if (symbol === undefined) {
return false;
}
const interfaceSymbol = this.getAnyInterfaceSymbol(name);
return symbol === interfaceSymbol;
});
}
isType(node, testType, name) {
return this.memoized('is-type', `${utils_2.typeKey(testType)}:${name}`, () => {
const symbol = this.context.analysis.getSymbolForType(node, testType);
if (symbol === undefined) {
return false;
}
if (name === 'Fixed') {
const fixedTagSymbol = this.getAnyInterfaceSymbol('FixedTag');
if (symbol === fixedTagSymbol) {
return true;
}
}
if (name === 'ForwardedValue') {
const forwardedValueTagSymbol = this.getAnyInterfaceSymbol('ForwardedValueTag');
if (symbol === forwardedValueTagSymbol) {
return true;
}
}
const typeSymbol = this.getAnyTypeSymbol(name);
return symbol === typeSymbol;
});
}
isValue(node, name) {
return this.memoized('is-value', `${utils_2.nodeKey(node)}:${name}`, () => {
const symbol = this.context.analysis.getSymbol(node);
if (symbol === undefined) {
return false;
}
const valueSymbol = this.getAnyValueSymbol(name);
return symbol === valueSymbol;
});
}
addMember(valueSymbol, memberSymbol, builtin) {
let members = this.builtinMembers.get(valueSymbol);
if (members === undefined) {
members = new Map();
this.builtinMembers.set(valueSymbol, members);
}
members.set(memberSymbol, builtin);
this.allBuiltinMembers.set(memberSymbol, builtin);
const memberSymbolName = ts_utils_1.tsUtils.symbol.getName(memberSymbol);
if (memberSymbolName.startsWith('__@')) {
const symbolSymbol = this.getInterfaceSymbolBase('SymbolConstructor', this.getGlobals());
const memberSymbolSymbol = getMember(symbolSymbol, memberSymbolName.slice(3));
members.set(memberSymbolSymbol, builtin);
this.allBuiltinMembers.set(memberSymbolSymbol, builtin);
}
}
addOverride(superSymbol, overrideSymbol) {
this.builtinOverrides.set(superSymbol, overrideSymbol);
}
addGlobalMember(value, member, builtin) {
this.addMemberBase(value, member, builtin, this.getGlobals());
}
addContractMember(value, member, builtin) {
this.addMemberBase(value, member, builtin, this.getContract());
}
addInterface(value, builtin) {
this.addInterfaceBase(value, builtin, this.getGlobals());
}
addContractInterface(value, builtin) {
this.addInterfaceBase(value, builtin, this.getContract());
}
addValue(value, builtin) {
this.addValueBase(value, builtin, this.getGlobals());
}
addTestValue(value, builtin) {
const file = this.getTestGlobals();
if (file === undefined) {
return;
}
this.addValueBase(value, builtin, file);
}
addContractValue(value, builtin) {
this.addValueBase(value, builtin, this.getContract());
}
walkOverridesForMember(valueSymbol, propSymbol) {
const overrideValueSymbol = this.builtinOverrides.get(valueSymbol);
if (overrideValueSymbol === undefined) {
return undefined;
}
let overridePropSymbol = this.builtinOverrides.get(propSymbol);
if (overridePropSymbol === undefined) {
overridePropSymbol = propSymbol;
}
const member = this.walkOverridesForMember(overrideValueSymbol, overridePropSymbol);
if (member !== undefined) {
return member;
}
const overridenMembers = this.getAllMembers(overrideValueSymbol);
return overridenMembers.get(overridePropSymbol);
}
getOnlyMemberBase(value, name, getValue) {
return this.memoized('only-member-base', `${value}$${name}`, () => {
const symbol = this.getAnyInterfaceOrValueSymbol(value);
const members = this.getAllMembers(symbol);
const result = [...members.entries()].find(([memberSymbol]) => ts_utils_1.tsUtils.symbol.getName(memberSymbol) === name);
return result === undefined ? undefined : getValue(result);
});
}
getAllMembers(symbol) {
return this.memoized('get-all-members', ts_utils_1.symbolKey(symbol), () => {
const interfaceMembers = this.builtinMembers.get(symbol);
const memberEntries = [...this.getInheritedSymbols(symbol)].reduce((acc, parentInterfaceSymbol) => {
const parentInterfaceMembers = this.builtinMembers.get(parentInterfaceSymbol);
if (parentInterfaceMembers === undefined) {
return acc;
}
return [...parentInterfaceMembers.entries()].concat(acc);
}, interfaceMembers === undefined ? [] : [...interfaceMembers.entries()]);
return new Map(memberEntries);
});
}
addMemberBase(value, member, builtin, file) {
let valueSymbol = this.getInterfaceSymbolMaybe(value, file);
let memberSymbol;
if (valueSymbol === undefined) {
valueSymbol = this.getValueSymbolBase(value, file);
memberSymbol = getExportOrMember(valueSymbol, member);
}
else {
memberSymbol = getMember(valueSymbol, member);
}
this.addMember(valueSymbol, memberSymbol, builtin);
}
getAnyInterfaceOrValueSymbol(value) {
const valueSymbol = this.getAnyInterfaceSymbolMaybe(value);
return valueSymbol === undefined ? this.getAnyValueSymbol(value) : valueSymbol;
}
addInterfaceBase(value, builtin, file) {
this.builtinInterfaces.set(this.getInterfaceSymbolBase(value, file), builtin);
}
addValueBase(value, builtin, file) {
this.builtinValues.set(this.getValueSymbolBase(value, file), builtin);
}
getAnyValueSymbol(name) {
return this.memoized('any-value-symbol', name, () => throwIfNull(this.getAnyValueSymbolMaybe(name)));
}
getAnyValueSymbolMaybe(name) {
return this.memoized('get-any-value-symbol-maybe', name, () => findNonNull(this.getFiles().map((file) => this.getValueSymbolMaybe(name, file))));
}
getValueSymbolBase(name, file) {
return throwIfNull(this.getValueSymbolMaybe(name, file));
}
getValueSymbolMaybe(name, file) {
let decl = ts_utils_1.tsUtils.statement.getVariableDeclaration(file, name);
if (decl === undefined) {
decl = ts_utils_1.tsUtils.statement.getFunction(file, name);
}
if (decl === undefined) {
decl = ts_utils_1.tsUtils.statement.getEnum(file, name);
}
if (decl === undefined) {
decl = ts_utils_1.tsUtils.statement.getClass(file, name);
}
if (decl === undefined) {
return undefined;
}
return ts_utils_1.tsUtils.node.getSymbol(this.context.typeChecker, decl);
}
getAnyInterfaceSymbol(name) {
return this.memoized('any-interface-symbol', name, () => throwIfNull(this.getAnyInterfaceSymbolMaybe(name)));
}
getAnyInterfaceSymbolMaybe(name) {
return this.memoized('get-any-interface-symbol-maybe', name, () => findNonNull(this.getFiles().map((file) => this.getInterfaceSymbolMaybe(name, file))));
}
getInterfaceSymbolBase(name, file) {
return throwIfNull(this.getInterfaceSymbolMaybe(name, file));
}
getInterfaceSymbolMaybe(name, file) {
return this.getInterfaceSymbols(file)[name];
}
getInterfaceSymbols(file) {
return this.memoized('interface-symbols', ts_utils_1.tsUtils.file.getFilePath(file), () => {
const interfaceDecls = ts_utils_1.tsUtils.statement.getInterfaces(file);
const decls = interfaceDecls.concat(ts_utils_1.tsUtils.statement.getEnums(file));
return lodash_1.default.fromPairs(decls.map((decl) => {
const type = ts_utils_1.tsUtils.type_.getType(this.context.typeChecker, decl);
const symbol = ts_utils_1.tsUtils.type_.getSymbol(type);
return [ts_utils_1.tsUtils.node.getName(decl), symbol];
}));
});
}
getInheritedSymbols(symbol, baseTypes = []) {
return this.memoized('get-inherited-symbols', ts_utils_1.symbolKey(symbol), () => {
const symbols = new Set();
for (const decl of ts_utils_1.tsUtils.symbol.getDeclarations(symbol)) {
if (typescript_1.default.isInterfaceDeclaration(decl) || typescript_1.default.isClassDeclaration(decl) || typescript_1.default.isClassExpression(decl)) {
let baseType = baseTypes[0];
let nextBaseTypes = baseTypes.slice(1);
if (baseTypes.length === 0) {
const currentBaseTypes = ts_utils_1.tsUtils.class_.getBaseTypesFlattened(this.context.typeChecker, decl);
baseType = currentBaseTypes[0];
nextBaseTypes = currentBaseTypes.slice(1);
}
if (baseType !== undefined) {
const baseSymbol = this.context.analysis.getSymbolForType(decl, baseType);
if (baseSymbol !== undefined) {
symbols.add(baseSymbol);
this.getInheritedSymbols(baseSymbol, nextBaseTypes).forEach((inheritedSymbol) => {
symbols.add(inheritedSymbol);
});
}
}
}
}
return symbols;
});
}
getAnyTypeSymbol(name) {
return this.memoized('get-any-type-symbol', name, () => throwIfNull(this.getAnyTypeSymbolMaybe(name)));
}
getAnyTypeSymbolMaybe(name) {
return this.memoized('get-any-type-symbol-maybe', name, () => findNonNull(this.getFiles().map((file) => this.getTypeSymbolMaybe(name, file))));
}
getTypeSymbolMaybe(name, file) {
return this.getTypeSymbols(file)[name];
}
getTypeSymbols(file) {
return this.memoized('type-symbols', ts_utils_1.tsUtils.file.getFilePath(file), () => {
const decls = ts_utils_1.tsUtils.statement.getTypeAliases(file);
return lodash_1.default.fromPairs(decls.map((decl) => {
const type = ts_utils_1.tsUtils.type_.getType(this.context.typeChecker, decl);
const symbol = ts_utils_1.tsUtils.type_.getAliasSymbol(type);
return [ts_utils_1.tsUtils.node.getName(decl), symbol];
}));
});
}
getFiles() {
return this.memoized('file-cache', 'files', () => [this.getGlobals(), this.getContract(), this.getTestGlobals()].filter(utils_1.utils.notNull));
}
getGlobals() {
return this.memoized('file-cache', 'globals', () => ts_utils_1.tsUtils.file.getSourceFileOrThrow(this.context.program, this.context.host.getSmartContractPath('global.d.ts')));
}
getContract() {
return this.memoized('file-cache', 'contract', () => ts_utils_1.tsUtils.file.getSourceFileOrThrow(this.context.program, this.context.host.getSmartContractPath('index.d.ts')));
}
getTestGlobals() {
return this.memoized('file-cache', 'test', () => ts_utils_1.tsUtils.file.getSourceFile(this.context.program, this.context.host.getSmartContractPath('harness.d.ts')));
}
}
exports.Builtins = Builtins;
//# sourceMappingURL=data:application/json;charset=utf8;base64,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LFVBQVUsRUFBRSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsYUFBSyxDQUFDLE9BQU8sQ0FBQyxDQUNyRixDQUFDO0lBQ0osQ0FBQztJQUVPLFVBQVU7UUFDaEIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLENBQ2pELGtCQUFPLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQy9HLENBQUM7SUFDSixDQUFDO0lBRU8sV0FBVztRQUNqQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsQ0FDbEQsa0JBQU8sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FDOUcsQ0FBQztJQUNKLENBQUM7SUFFTyxjQUFjO1FBQ3BCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUM5QyxrQkFBTyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FDekcsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQWhlRCw0QkFnZUMiLCJmaWxlIjoibmVvLW9uZS1zbWFydC1jb250cmFjdC1jb21waWxlci9zcmMvY29tcGlsZS9idWlsdGlucy9CdWlsdGlucy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHN5bWJvbEtleSwgdHNVdGlscyB9IGZyb20gJ0BuZW8tb25lL3RzLXV0aWxzJztcbmltcG9ydCB7IHV0aWxzIH0gZnJvbSAnQG5lby1vbmUvdXRpbHMnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB0cyBmcm9tICd0eXBlc2NyaXB0JztcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tICcuLi8uLi9Db250ZXh0JztcbmltcG9ydCB7IGNyZWF0ZU1lbW9pemVkLCBub2RlS2V5LCB0eXBlS2V5IH0gZnJvbSAnLi4vLi4vdXRpbHMnO1xuaW1wb3J0IHsgQnVpbHRpbiwgaXNCdWlsdGluVmFsdWVPYmplY3QgfSBmcm9tICcuL3R5cGVzJztcblxuY29uc3QgZ2V0TWVtYmVyID0gKHN5bTogdHMuU3ltYm9sLCBuYW1lOiBzdHJpbmcpID0+IHRzVXRpbHMuc3ltYm9sLmdldE1lbWJlck9yVGhyb3coc3ltLCBuYW1lKTtcbmNvbnN0IGdldEV4cG9ydE9yTWVtYmVyID0gKHN5bTogdHMuU3ltYm9sLCBuYW1lOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgbWVtYmVyID0gdHNVdGlscy5zeW1ib2wuZ2V0TWVtYmVyKHN5bSwgbmFtZSk7XG5cbiAgcmV0dXJuIG1lbWJlciA9PT0gdW5kZWZpbmVkID8gdHNVdGlscy5zeW1ib2wuZ2V0RXhwb3J0T3JUaHJvdyhzeW0sIG5hbWUpIDogbWVtYmVyO1xufTtcblxuY29uc3QgZmluZE5vbk51bGwgPSA8VD4odmFsdWU6IFJlYWRvbmx5QXJyYXk8VCB8IHVuZGVmaW5lZD4pOiBUIHwgdW5kZWZpbmVkID0+IHZhbHVlLmZpbmQoKHZhbCkgPT4gdmFsICE9PSB1bmRlZmluZWQpO1xuXG5jb25zdCB0aHJvd0lmTnVsbCA9IDxUPih2YWx1ZTogVCB8IHVuZGVmaW5lZCB8IG51bGwpOiBUID0+IHtcbiAgaWYgKHZhbHVlID09IHVuZGVmaW5lZCkge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdGhyb3cgbmV3IEVycm9yKCdTb21ldGhpbmcgd2VudCB3cm9uZy4nKTtcbiAgfVxuXG4gIHJldHVybiB2YWx1ZTtcbn07XG5cbmV4cG9ydCBjbGFzcyBCdWlsdGlucyB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYnVpbHRpbk1lbWJlcnM6IE1hcDx0cy5TeW1ib2wsIE1hcDx0cy5TeW1ib2wsIEJ1aWx0aW4+PiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSByZWFkb25seSBhbGxCdWlsdGluTWVtYmVyczogTWFwPHRzLlN5bWJvbCwgQnVpbHRpbj4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgYnVpbHRpbkludGVyZmFjZXM6IE1hcDx0cy5TeW1ib2wsIEJ1aWx0aW4+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IGJ1aWx0aW5WYWx1ZXM6IE1hcDx0cy5TeW1ib2wsIEJ1aWx0aW4+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IGJ1aWx0aW5PdmVycmlkZXM6IE1hcDx0cy5TeW1ib2wsIHRzLlN5bWJvbD4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWVtb2l6ZWQgPSBjcmVhdGVNZW1vaXplZCgpO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGNvbnRleHQ6IENvbnRleHQpIHt9XG5cbiAgcHVibGljIGlzQnVpbHRpblN5bWJvbChzeW1ib2w6IHRzLlN5bWJvbCB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBzeW1ib2wgIT09IHVuZGVmaW5lZCAmJiAodGhpcy5idWlsdGluVmFsdWVzLmhhcyhzeW1ib2wpIHx8IHRoaXMuYnVpbHRpbkludGVyZmFjZXMuaGFzKHN5bWJvbCkpO1xuICB9XG5cbiAgcHVibGljIGlzQnVpbHRpbklkZW50aWZpZXIodmFsdWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmdldEFueUludGVyZmFjZVN5bWJvbE1heWJlKHZhbHVlKSAhPT0gdW5kZWZpbmVkIHx8XG4gICAgICB0aGlzLmdldEFueVR5cGVTeW1ib2xNYXliZSh2YWx1ZSkgIT09IHVuZGVmaW5lZCB8fFxuICAgICAgdGhpcy5nZXRBbnlWYWx1ZVN5bWJvbE1heWJlKHZhbHVlKSAhPT0gdW5kZWZpbmVkXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBpc0J1aWx0aW5GaWxlKGZpbGU6IHRzLlNvdXJjZUZpbGUpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5nZXRDb250cmFjdCgpID09PSBmaWxlO1xuICB9XG5cbiAgcHVibGljIGdldE1lbWJlcih2YWx1ZTogdHMuTm9kZSwgcHJvcDogdHMuTm9kZSk6IEJ1aWx0aW4gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLm1lbW9pemVkKCdnZXQtbWVtYmVyJywgYCR7bm9kZUtleSh2YWx1ZSl9OiR7bm9kZUtleShwcm9wKX1gLCAoKSA9PiB7XG4gICAgICBjb25zdCBwcm9wU3ltYm9sID0gdGhpcy5jb250ZXh0LmFuYWx5c2lzLmdldFN5bWJvbChwcm9wKTtcbiAgICAgIGlmIChwcm9wU3ltYm9sID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdmFsdWVTeW1ib2wgPSB0aGlzLmNvbnRleHQuYW5hbHlzaXMuZ2V0VHlwZVN5bWJvbCh2YWx1ZSk7XG4gICAgICBpZiAodmFsdWVTeW1ib2wgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hbGxCdWlsdGluTWVtYmVycy5nZXQocHJvcFN5bWJvbCk7XG4gICAgICB9XG5cbiAgICAgIC8vIFN1cGVyIGhhY2t5IC0gb25seSB3b3JrcyBmb3IgdGhlIHNwZWNpYWwgd2F5IHNtYXJ0IGNvbnRyYWN0cyBhcmUgY29tcGlsZWQuXG4gICAgICBpZiAoIXRzVXRpbHMuZ3VhcmRzLmlzU3VwZXJFeHByZXNzaW9uKHZhbHVlKSkge1xuICAgICAgICBjb25zdCBvdmVycmlkZW5NZW1iZXIgPSB0aGlzLndhbGtPdmVycmlkZXNGb3JNZW1iZXIodmFsdWVTeW1ib2wsIHByb3BTeW1ib2wpO1xuICAgICAgICBpZiAob3ZlcnJpZGVuTWVtYmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gb3ZlcnJpZGVuTWVtYmVyO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1lbWJlcnMgPSB0aGlzLmdldEFsbE1lbWJlcnModmFsdWVTeW1ib2wpO1xuXG4gICAgICByZXR1cm4gbWVtYmVycy5nZXQocHJvcFN5bWJvbCk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0T25seU1lbWJlcih2YWx1ZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcpOiBCdWlsdGluIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5nZXRPbmx5TWVtYmVyQmFzZSh2YWx1ZSwgbmFtZSwgKHJlc3VsdCkgPT4gcmVzdWx0WzFdKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRPbmx5TWVtYmVyU3ltYm9sKHZhbHVlOiBzdHJpbmcsIG5hbWU6IHN0cmluZyk6IHRzLlN5bWJvbCB7XG4gICAgcmV0dXJuIHRocm93SWZOdWxsKHRoaXMuZ2V0T25seU1lbWJlckJhc2UodmFsdWUsIG5hbWUsIChyZXN1bHQpID0+IHJlc3VsdFswXSkpO1xuICB9XG5cbiAgcHVibGljIGdldE1lbWJlcnM8VCBleHRlbmRzIEJ1aWx0aW4+KFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBpc01lbWJlcjogKGJ1aWx0aW46IEJ1aWx0aW4pID0+IGJ1aWx0aW4gaXMgVCxcbiAgICBpc0VsaWdpYmxlOiAoYnVpbHRpbjogVCkgPT4gYm9vbGVhbixcbiAgICBzeW1ib2xNZW1iZXJzID0gZmFsc2UsXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiByZWFkb25seS1hcnJheVxuICApOiBSZWFkb25seUFycmF5PFtzdHJpbmcsIFRdPiB7XG4gICAgY29uc3QgZmlsdGVyUHNldWRvU3ltYm9sID0gKHN5bWJvbDogdHMuU3ltYm9sLCBrZXk6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3Qgc3ltYm9sU3ltYm9sID0gdGhpcy5nZXRJbnRlcmZhY2VTeW1ib2xCYXNlKCdTeW1ib2xDb25zdHJ1Y3RvcicsIHRoaXMuZ2V0R2xvYmFscygpKTtcblxuICAgICAgcmV0dXJuIHRzVXRpbHMuc3ltYm9sLmdldE1lbWJlcihzeW1ib2xTeW1ib2wsIGtleSkgIT09IHN5bWJvbDtcbiAgICB9O1xuICAgIGNvbnN0IGlzU3ltYm9sS2V5ID0gKGtleTogc3RyaW5nKSA9PiBrZXkuc3RhcnRzV2l0aCgnX19AJyk7XG5cbiAgICBsZXQgdGVzdEtleSA9IChrZXk6IHN0cmluZykgPT4gIWlzU3ltYm9sS2V5KGtleSk7XG4gICAgbGV0IG1vZGlmeUtleSA9IChrZXk6IHN0cmluZykgPT4ga2V5O1xuICAgIGlmIChzeW1ib2xNZW1iZXJzKSB7XG4gICAgICB0ZXN0S2V5ID0gaXNTeW1ib2xLZXk7XG4gICAgICBtb2RpZnlLZXkgPSAoa2V5KSA9PiBrZXkuc2xpY2UoMyk7XG4gICAgfVxuXG4gICAgY29uc3QgbWVtYmVycyA9IHRoaXMuZ2V0QWxsTWVtYmVycyh0aGlzLmdldEFueUludGVyZmFjZVN5bWJvbChuYW1lKSk7XG5cbiAgICBjb25zdCBtdXRhYmxlTWVtYmVyczogQXJyYXk8W3N0cmluZywgVF0+ID0gW107XG4gICAgbWVtYmVycy5mb3JFYWNoKChidWlsdGluLCBtZW1iZXJTeW1ib2wpID0+IHtcbiAgICAgIGNvbnN0IG1lbWJlck5hbWUgPSB0c1V0aWxzLnN5bWJvbC5nZXROYW1lKG1lbWJlclN5bWJvbCk7XG4gICAgICBpZiAoXG4gICAgICAgIGlzTWVtYmVyKGJ1aWx0aW4pICYmXG4gICAgICAgIGZpbHRlclBzZXVkb1N5bWJvbChtZW1iZXJTeW1ib2wsIG1lbWJlck5hbWUpICYmXG4gICAgICAgIHRlc3RLZXkobWVtYmVyTmFtZSkgJiZcbiAgICAgICAgaXNFbGlnaWJsZShidWlsdGluKVxuICAgICAgKSB7XG4gICAgICAgIG11dGFibGVNZW1iZXJzLnB1c2goW21vZGlmeUtleShtZW1iZXJOYW1lKSwgYnVpbHRpbl0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIG11dGFibGVNZW1iZXJzO1xuICB9XG5cbiAgcHVibGljIGdldEludGVyZmFjZSh2YWx1ZTogdHMuTm9kZSk6IEJ1aWx0aW4gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHZhbHVlU3ltYm9sID0gdGhpcy5jb250ZXh0LmFuYWx5c2lzLmdldFN5bWJvbCh2YWx1ZSk7XG4gICAgaWYgKHZhbHVlU3ltYm9sID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuYnVpbHRpbkludGVyZmFjZXMuZ2V0KHZhbHVlU3ltYm9sKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRJbnRlcmZhY2VTeW1ib2wodmFsdWU6IHN0cmluZyk6IHRzLlN5bWJvbCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QW55SW50ZXJmYWNlU3ltYm9sKHZhbHVlKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRWYWx1ZSh2YWx1ZTogdHMuTm9kZSk6IEJ1aWx0aW4gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHZhbHVlU3ltYm9sID0gdGhpcy5jb250ZXh0LmFuYWx5c2lzLmdldFN5bWJvbCh2YWx1ZSk7XG4gICAgaWYgKHZhbHVlU3ltYm9sID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuYnVpbHRpblZhbHVlcy5nZXQodmFsdWVTeW1ib2wpO1xuICB9XG5cbiAgcHVibGljIGdldFZhbHVlSW50ZXJmYWNlKHZhbHVlOiB0cy5Ob2RlKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBidWlsdGluVmFsdWUgPSB0aGlzLmdldFZhbHVlKHZhbHVlKTtcblxuICAgIHJldHVybiBidWlsdGluVmFsdWUgPT09IHVuZGVmaW5lZCB8fCAhaXNCdWlsdGluVmFsdWVPYmplY3QoYnVpbHRpblZhbHVlKSA/IHVuZGVmaW5lZCA6IGJ1aWx0aW5WYWx1ZS50eXBlO1xuICB9XG5cbiAgcHVibGljIGdldFZhbHVlU3ltYm9sKHZhbHVlOiBzdHJpbmcpOiB0cy5TeW1ib2wge1xuICAgIHJldHVybiB0aGlzLmdldEFueVZhbHVlU3ltYm9sKHZhbHVlKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRUeXBlU3ltYm9sKG5hbWU6IHN0cmluZyk6IHRzLlN5bWJvbCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QW55VHlwZVN5bWJvbChuYW1lKTtcbiAgfVxuXG4gIHB1YmxpYyBpc0ludGVyZmFjZShub2RlOiB0cy5Ob2RlLCB0ZXN0VHlwZTogdHMuVHlwZSwgbmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWVtb2l6ZWQoJ2lzLWludGVyZmFjZScsIGAke3R5cGVLZXkodGVzdFR5cGUpfToke25hbWV9YCwgKCkgPT4ge1xuICAgICAgY29uc3Qgc3ltYm9sID0gdGhpcy5jb250ZXh0LmFuYWx5c2lzLmdldFN5bWJvbEZvclR5cGUobm9kZSwgdGVzdFR5cGUpO1xuICAgICAgaWYgKHN5bWJvbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaW50ZXJmYWNlU3ltYm9sID0gdGhpcy5nZXRBbnlJbnRlcmZhY2VTeW1ib2wobmFtZSk7XG5cbiAgICAgIHJldHVybiBzeW1ib2wgPT09IGludGVyZmFjZVN5bWJvbDtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBpc1R5cGUobm9kZTogdHMuTm9kZSwgdGVzdFR5cGU6IHRzLlR5cGUsIG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1lbW9pemVkKCdpcy10eXBlJywgYCR7dHlwZUtleSh0ZXN0VHlwZSl9OiR7bmFtZX1gLCAoKSA9PiB7XG4gICAgICBjb25zdCBzeW1ib2wgPSB0aGlzLmNvbnRleHQuYW5hbHlzaXMuZ2V0U3ltYm9sRm9yVHlwZShub2RlLCB0ZXN0VHlwZSk7XG4gICAgICBpZiAoc3ltYm9sID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpZiAobmFtZSA9PT0gJ0ZpeGVkJykge1xuICAgICAgICBjb25zdCBmaXhlZFRhZ1N5bWJvbCA9IHRoaXMuZ2V0QW55SW50ZXJmYWNlU3ltYm9sKCdGaXhlZFRhZycpO1xuICAgICAgICBpZiAoc3ltYm9sID09PSBmaXhlZFRhZ1N5bWJvbCkge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChuYW1lID09PSAnRm9yd2FyZGVkVmFsdWUnKSB7XG4gICAgICAgIGNvbnN0IGZvcndhcmRlZFZhbHVlVGFnU3ltYm9sID0gdGhpcy5nZXRBbnlJbnRlcmZhY2VTeW1ib2woJ0ZvcndhcmRlZFZhbHVlVGFnJyk7XG4gICAgICAgIGlmIChzeW1ib2wgPT09IGZvcndhcmRlZFZhbHVlVGFnU3ltYm9sKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgdHlwZVN5bWJvbCA9IHRoaXMuZ2V0QW55VHlwZVN5bWJvbChuYW1lKTtcblxuICAgICAgcmV0dXJuIHN5bWJvbCA9PT0gdHlwZVN5bWJvbDtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBpc1ZhbHVlKG5vZGU6IHRzLk5vZGUsIG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1lbW9pemVkKCdpcy12YWx1ZScsIGAke25vZGVLZXkobm9kZSl9OiR7bmFtZX1gLCAoKSA9PiB7XG4gICAgICBjb25zdCBzeW1ib2wgPSB0aGlzLmNvbnRleHQuYW5hbHlzaXMuZ2V0U3ltYm9sKG5vZGUpO1xuICAgICAgaWYgKHN5bWJvbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdmFsdWVTeW1ib2wgPSB0aGlzLmdldEFueVZhbHVlU3ltYm9sKG5hbWUpO1xuXG4gICAgICByZXR1cm4gc3ltYm9sID09PSB2YWx1ZVN5bWJvbDtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRNZW1iZXIodmFsdWVTeW1ib2w6IHRzLlN5bWJvbCwgbWVtYmVyU3ltYm9sOiB0cy5TeW1ib2wsIGJ1aWx0aW46IEJ1aWx0aW4pOiB2b2lkIHtcbiAgICBsZXQgbWVtYmVycyA9IHRoaXMuYnVpbHRpbk1lbWJlcnMuZ2V0KHZhbHVlU3ltYm9sKTtcbiAgICBpZiAobWVtYmVycyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBtZW1iZXJzID0gbmV3IE1hcCgpO1xuICAgICAgdGhpcy5idWlsdGluTWVtYmVycy5zZXQodmFsdWVTeW1ib2wsIG1lbWJlcnMpO1xuICAgIH1cblxuICAgIG1lbWJlcnMuc2V0KG1lbWJlclN5bWJvbCwgYnVpbHRpbik7XG4gICAgdGhpcy5hbGxCdWlsdGluTWVtYmVycy5zZXQobWVtYmVyU3ltYm9sLCBidWlsdGluKTtcbiAgICBjb25zdCBtZW1iZXJTeW1ib2xOYW1lID0gdHNVdGlscy5zeW1ib2wuZ2V0TmFtZShtZW1iZXJTeW1ib2wpO1xuICAgIGlmIChtZW1iZXJTeW1ib2xOYW1lLnN0YXJ0c1dpdGgoJ19fQCcpKSB7XG4gICAgICBjb25zdCBzeW1ib2xTeW1ib2wgPSB0aGlzLmdldEludGVyZmFjZVN5bWJvbEJhc2UoJ1N5bWJvbENvbnN0cnVjdG9yJywgdGhpcy5nZXRHbG9iYWxzKCkpO1xuICAgICAgY29uc3QgbWVtYmVyU3ltYm9sU3ltYm9sID0gZ2V0TWVtYmVyKHN5bWJvbFN5bWJvbCwgbWVtYmVyU3ltYm9sTmFtZS5zbGljZSgzKSk7XG4gICAgICBtZW1iZXJzLnNldChtZW1iZXJTeW1ib2xTeW1ib2wsIGJ1aWx0aW4pO1xuICAgICAgdGhpcy5hbGxCdWlsdGluTWVtYmVycy5zZXQobWVtYmVyU3ltYm9sU3ltYm9sLCBidWlsdGluKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYWRkT3ZlcnJpZGUoc3VwZXJTeW1ib2w6IHRzLlN5bWJvbCwgb3ZlcnJpZGVTeW1ib2w6IHRzLlN5bWJvbCk6IHZvaWQge1xuICAgIHRoaXMuYnVpbHRpbk92ZXJyaWRlcy5zZXQoc3VwZXJTeW1ib2wsIG92ZXJyaWRlU3ltYm9sKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRHbG9iYWxNZW1iZXIodmFsdWU6IHN0cmluZywgbWVtYmVyOiBzdHJpbmcsIGJ1aWx0aW46IEJ1aWx0aW4pOiB2b2lkIHtcbiAgICB0aGlzLmFkZE1lbWJlckJhc2UodmFsdWUsIG1lbWJlciwgYnVpbHRpbiwgdGhpcy5nZXRHbG9iYWxzKCkpO1xuICB9XG5cbiAgcHVibGljIGFkZENvbnRyYWN0TWVtYmVyKHZhbHVlOiBzdHJpbmcsIG1lbWJlcjogc3RyaW5nLCBidWlsdGluOiBCdWlsdGluKTogdm9pZCB7XG4gICAgdGhpcy5hZGRNZW1iZXJCYXNlKHZhbHVlLCBtZW1iZXIsIGJ1aWx0aW4sIHRoaXMuZ2V0Q29udHJhY3QoKSk7XG4gIH1cblxuICBwdWJsaWMgYWRkSW50ZXJmYWNlKHZhbHVlOiBzdHJpbmcsIG