UNPKG

@ngx-formly/core

Version:

Formly is a dynamic (JSON powered) form library for Angular that bring unmatched maintainability to your application's forms.

459 lines 59.9 kB
// CSP-compliant expression parser for Formly expressions // Supports: model.path, formState.path, field.path, comparisons, logical operators, and negation // Tokenizer var TokenType; (function (TokenType) { TokenType["IDENTIFIER"] = "IDENTIFIER"; TokenType["DOT"] = "DOT"; TokenType["BRACKET_OPEN"] = "BRACKET_OPEN"; TokenType["BRACKET_CLOSE"] = "BRACKET_CLOSE"; TokenType["STRING"] = "STRING"; TokenType["NUMBER"] = "NUMBER"; TokenType["BOOLEAN"] = "BOOLEAN"; TokenType["NULL"] = "NULL"; TokenType["UNDEFINED"] = "UNDEFINED"; TokenType["OPERATOR"] = "OPERATOR"; TokenType["LOGICAL"] = "LOGICAL"; TokenType["NOT"] = "NOT"; TokenType["ARITHMETIC"] = "ARITHMETIC"; TokenType["PAREN_OPEN"] = "PAREN_OPEN"; TokenType["PAREN_CLOSE"] = "PAREN_CLOSE"; TokenType["TERNARY_QUESTION"] = "TERNARY_QUESTION"; TokenType["TERNARY_COLON"] = "TERNARY_COLON"; TokenType["EOF"] = "EOF"; })(TokenType || (TokenType = {})); class Tokenizer { constructor(input) { this.pos = 0; this.input = input.trim(); } tokenize() { const tokens = []; while (this.pos < this.input.length) { this.skipWhitespace(); if (this.pos >= this.input.length) break; const char = this.input[this.pos]; // String literals if (char === '"' || char === "'") { tokens.push(this.readString()); } // Numbers else if (/\d/.test(char)) { tokens.push(this.readNumber()); } // Identifiers and keywords else if (/[a-zA-Z_$]/.test(char)) { tokens.push(this.readIdentifier()); } // Operators and symbols else if (char === '.') { tokens.push({ type: TokenType.DOT, value: '.' }); this.pos++; } else if (char === '[') { tokens.push({ type: TokenType.BRACKET_OPEN, value: '[' }); this.pos++; } else if (char === ']') { tokens.push({ type: TokenType.BRACKET_CLOSE, value: ']' }); this.pos++; } else if (char === '(') { tokens.push({ type: TokenType.PAREN_OPEN, value: '(' }); this.pos++; } else if (char === ')') { tokens.push({ type: TokenType.PAREN_CLOSE, value: ')' }); this.pos++; } else if (char === '?') { tokens.push({ type: TokenType.TERNARY_QUESTION, value: '?' }); this.pos++; } else if (char === ':') { tokens.push({ type: TokenType.TERNARY_COLON, value: ':' }); this.pos++; } else if (char === '!') { if (this.peek() === '=') { if (this.input[this.pos + 2] === '=') { tokens.push({ type: TokenType.OPERATOR, value: '!==' }); this.pos += 3; } else { tokens.push({ type: TokenType.OPERATOR, value: '!=' }); this.pos += 2; } } else { tokens.push({ type: TokenType.NOT, value: '!' }); this.pos++; } } else if (char === '=' || char === '<' || char === '>') { tokens.push(this.readOperator()); } else if (char === '+' || char === '*' || char === '/' || char === '%') { tokens.push({ type: TokenType.ARITHMETIC, value: char }); this.pos++; } else if (char === '-') { // Check if this is a negative number or subtraction // It's a negative number if preceded by an operator, opening paren, or at the start const lastToken = tokens[tokens.length - 1]; const isNegativeNumber = tokens.length === 0 || lastToken?.type === TokenType.OPERATOR || lastToken?.type === TokenType.LOGICAL || lastToken?.type === TokenType.ARITHMETIC || lastToken?.type === TokenType.PAREN_OPEN || lastToken?.type === TokenType.TERNARY_QUESTION || lastToken?.type === TokenType.TERNARY_COLON; if (isNegativeNumber && this.peek() && /\d/.test(this.peek())) { tokens.push(this.readNumber()); } else { tokens.push({ type: TokenType.ARITHMETIC, value: '-' }); this.pos++; } } else if (char === '&' && this.peek() === '&') { tokens.push({ type: TokenType.LOGICAL, value: '&&' }); this.pos += 2; } else if (char === '|' && this.peek() === '|') { tokens.push({ type: TokenType.LOGICAL, value: '||' }); this.pos += 2; } else { throw new Error(`Unexpected character: ${char} at position ${this.pos}`); } } tokens.push({ type: TokenType.EOF, value: null }); return tokens; } skipWhitespace() { while (this.pos < this.input.length && /\s/.test(this.input[this.pos])) { this.pos++; } } peek(offset = 1) { return this.input[this.pos + offset] || ''; } readString() { const quote = this.input[this.pos]; this.pos++; let value = ''; while (this.pos < this.input.length && this.input[this.pos] !== quote) { if (this.input[this.pos] === '\\') { this.pos++; if (this.pos < this.input.length) { const escaped = this.input[this.pos]; switch (escaped) { case 'n': value += '\n'; break; case 't': value += '\t'; break; case 'r': value += '\r'; break; default: value += escaped; } } } else { value += this.input[this.pos]; } this.pos++; } this.pos++; // skip closing quote return { type: TokenType.STRING, value }; } readNumber() { let value = ''; // Handle negatives if (this.input[this.pos] === '-') { value += '-'; this.pos++; } let hasDecimal = false; while (this.pos < this.input.length && /[\d.]/.test(this.input[this.pos])) { if (this.input[this.pos] === '.') { if (hasDecimal) { throw new Error(`Invalid number format: multiple decimal points at position ${this.pos}`); } hasDecimal = true; } value += this.input[this.pos]; this.pos++; } const parsed = parseFloat(value); if (isNaN(parsed)) { throw new Error(`Invalid number format: ${value}`); } return { type: TokenType.NUMBER, value: parsed }; } readIdentifier() { let value = ''; while (this.pos < this.input.length && /[a-zA-Z0-9_$]/.test(this.input[this.pos])) { value += this.input[this.pos]; this.pos++; } // Check for keywords if (value === 'true' || value === 'false') { return { type: TokenType.BOOLEAN, value: value === 'true' }; } if (value === 'null') { return { type: TokenType.NULL, value: null }; } if (value === 'undefined') { return { type: TokenType.UNDEFINED, value: undefined }; } return { type: TokenType.IDENTIFIER, value }; } readOperator() { let op = this.input[this.pos]; this.pos++; if (this.pos < this.input.length) { const next = this.input[this.pos]; if ((op === '=' && next === '=') || (op === '!' && next === '=') || (op === '<' && next === '=') || (op === '>' && next === '=')) { op += next; this.pos++; // Check for === or !== if (this.pos < this.input.length && this.input[this.pos] === '=') { op += '='; this.pos++; } } } return { type: TokenType.OPERATOR, value: op }; } } // Parser and Evaluator class ExpressionParser { constructor(tokens) { this.pos = 0; this.tokens = tokens; } parse() { const expr = this.parseTernary(); return (context) => expr(context); } parseTernary() { const expr = this.parseLogicalOr(); if (this.current().type === TokenType.TERNARY_QUESTION) { this.consume(TokenType.TERNARY_QUESTION); const trueExpr = this.parseLogicalOr(); this.consume(TokenType.TERNARY_COLON); const falseExpr = this.parseTernary(); return (context) => { return expr(context) ? trueExpr(context) : falseExpr(context); }; } return expr; } parseLogicalOr() { let left = this.parseLogicalAnd(); while (this.current().type === TokenType.LOGICAL && this.current().value === '||') { this.consume(TokenType.LOGICAL); const right = this.parseLogicalAnd(); const prevLeft = left; left = (context) => prevLeft(context) || right(context); } return left; } parseLogicalAnd() { let left = this.parseComparison(); while (this.current().type === TokenType.LOGICAL && this.current().value === '&&') { this.consume(TokenType.LOGICAL); const right = this.parseComparison(); const prevLeft = left; left = (context) => prevLeft(context) && right(context); } return left; } parseComparison() { const left = this.parseAdditive(); if (this.current().type === TokenType.OPERATOR) { const op = this.consume(TokenType.OPERATOR).value; const right = this.parseAdditive(); return (context) => { const leftVal = left(context); const rightVal = right(context); switch (op) { case '===': return leftVal === rightVal; case '!==': return leftVal !== rightVal; case '==': return leftVal == rightVal; case '!=': return leftVal != rightVal; case '<': return leftVal < rightVal; case '<=': return leftVal <= rightVal; case '>': return leftVal > rightVal; case '>=': return leftVal >= rightVal; default: throw new Error(`Unknown operator: ${op}`); } }; } return left; } parseAdditive() { let left = this.parseMultiplicative(); while (this.current().type === TokenType.ARITHMETIC && (this.current().value === '+' || this.current().value === '-')) { const op = this.consume(TokenType.ARITHMETIC).value; const right = this.parseMultiplicative(); const prevLeft = left; if (op === '+') { left = (context) => prevLeft(context) + right(context); } else { left = (context) => prevLeft(context) - right(context); } } return left; } parseMultiplicative() { let left = this.parseUnary(); while (this.current().type === TokenType.ARITHMETIC && (this.current().value === '*' || this.current().value === '/' || this.current().value === '%')) { const op = this.consume(TokenType.ARITHMETIC).value; const right = this.parseUnary(); const prevLeft = left; if (op === '*') { left = (context) => prevLeft(context) * right(context); } else if (op === '/') { left = (context) => prevLeft(context) / right(context); } else { left = (context) => prevLeft(context) % right(context); } } return left; } parseUnary() { if (this.current().type === TokenType.NOT) { this.consume(TokenType.NOT); const expr = this.parseUnary(); return (context) => !expr(context); } return this.parsePrimary(); } parsePrimary() { const token = this.current(); // Parentheses if (token.type === TokenType.PAREN_OPEN) { this.consume(TokenType.PAREN_OPEN); const expr = this.parseTernary(); this.consume(TokenType.PAREN_CLOSE); return expr; } // Literals if (token.type === TokenType.STRING || token.type === TokenType.NUMBER || token.type === TokenType.BOOLEAN || token.type === TokenType.NULL || token.type === TokenType.UNDEFINED) { const value = token.value; this.pos++; return () => value; } // Property access (model.field, formState.prop, etc) if (token.type === TokenType.IDENTIFIER) { return this.parsePropertyAccess(); } throw new Error(`Unexpected token: ${JSON.stringify(token)}`); } parsePropertyAccess() { const path = []; // Read first identifier path.push(this.consume(TokenType.IDENTIFIER).value); // Read rest of path (dots and brackets) while (this.current().type === TokenType.DOT || this.current().type === TokenType.BRACKET_OPEN) { if (this.current().type === TokenType.DOT) { this.consume(TokenType.DOT); path.push(this.consume(TokenType.IDENTIFIER).value); } else { this.consume(TokenType.BRACKET_OPEN); // bracket notation can contain expressions if (this.current().type === TokenType.STRING) { path.push(this.consume(TokenType.STRING).value); } else if (this.current().type === TokenType.NUMBER) { path.push(String(this.consume(TokenType.NUMBER).value)); } else { // dynamic property access const expr = this.parseTernary(); path.push(expr); } this.consume(TokenType.BRACKET_CLOSE); } } return (context) => { let value = context; for (const segment of path) { if (value === null || value === undefined) { return undefined; } if (typeof segment === 'function') { value = value[segment(context)]; } else { value = value[segment]; } } return value; }; } current() { return this.tokens[this.pos]; } consume(expectedType) { const token = this.current(); if (token.type !== expectedType) { throw new Error(`Expected ${expectedType}, got ${token.type}`); } this.pos++; return token; } } /** * Uses CSP-safe implementation */ export function parseExpression(expression, argNames) { try { const tokenizer = new Tokenizer(expression); const tokens = tokenizer.tokenize(); const parser = new ExpressionParser(tokens); const evaluator = parser.parse(); // Return a function that maps the args to the context return (...args) => { const context = {}; argNames.forEach((name, i) => { context[name] = args[i]; }); return evaluator(context); }; } catch (error) { console.error('Expression parse error:', error); return undefined; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29yZS9zcmMvbGliL2V4dGVuc2lvbnMvZmllbGQtZXhwcmVzc2lvbi91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsaUdBQWlHO0FBUWpHLFlBQVk7QUFDWixJQUFLLFNBbUJKO0FBbkJELFdBQUssU0FBUztJQUNaLHNDQUF5QixDQUFBO0lBQ3pCLHdCQUFXLENBQUE7SUFDWCwwQ0FBNkIsQ0FBQTtJQUM3Qiw0Q0FBK0IsQ0FBQTtJQUMvQiw4QkFBaUIsQ0FBQTtJQUNqQiw4QkFBaUIsQ0FBQTtJQUNqQixnQ0FBbUIsQ0FBQTtJQUNuQiwwQkFBYSxDQUFBO0lBQ2Isb0NBQXVCLENBQUE7SUFDdkIsa0NBQXFCLENBQUE7SUFDckIsZ0NBQW1CLENBQUE7SUFDbkIsd0JBQVcsQ0FBQTtJQUNYLHNDQUF5QixDQUFBO0lBQ3pCLHNDQUF5QixDQUFBO0lBQ3pCLHdDQUEyQixDQUFBO0lBQzNCLGtEQUFxQyxDQUFBO0lBQ3JDLDRDQUErQixDQUFBO0lBQy9CLHdCQUFXLENBQUE7QUFDYixDQUFDLEVBbkJJLFNBQVMsS0FBVCxTQUFTLFFBbUJiO0FBT0QsTUFBTSxTQUFTO0lBSWIsWUFBWSxLQUFhO1FBSGpCLFFBQUcsR0FBRyxDQUFDLENBQUM7UUFJZCxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRUQsUUFBUTtRQUNOLE1BQU0sTUFBTSxHQUFZLEVBQUUsQ0FBQztRQUUzQixPQUFPLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNwQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFFdEIsSUFBSSxJQUFJLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTTtnQkFBRSxNQUFN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Q3hCLE1BQU0sT0FBTyxHQUFRLEVBQUUsQ0FBQztZQUN4QixRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFO2dCQUMzQixPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFCLENBQUMsQ0FBQyxDQUFDO1lBQ0gsT0FBTyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUIsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixPQUFPLENBQUMsS0FBSyxDQUFDLHlCQUF5QixFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ2hELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ1NQLWNvbXBsaWFudCBleHByZXNzaW9uIHBhcnNlciBmb3IgRm9ybWx5IGV4cHJlc3Npb25zXG4vLyBTdXBwb3J0czogbW9kZWwucGF0aCwgZm9ybVN0YXRlLnBhdGgsIGZpZWxkLnBhdGgsIGNvbXBhcmlzb25zLCBsb2dpY2FsIG9wZXJhdG9ycywgYW5kIG5lZ2F0aW9uXG5cbnR5cGUgRXhwcmVzc2lvbkNvbnRleHQgPSB7XG4gIG1vZGVsOiBhbnk7XG4gIGZvcm1TdGF0ZTogYW55O1xuICBmaWVsZDogYW55O1xufTtcblxuLy8gVG9rZW5pemVyXG5lbnVtIFRva2VuVHlwZSB7XG4gIElERU5USUZJRVIgPSAnSURFTlRJRklFUicsXG4gIERPVCA9ICdET1QnLFxuICBCUkFDS0VUX09QRU4gPSAnQlJBQ0tFVF9PUEVOJyxcbiAgQlJBQ0tFVF9DTE9TRSA9ICdCUkFDS0VUX0NMT1NFJyxcbiAgU1RSSU5HID0gJ1NUUklORycsXG4gIE5VTUJFUiA9ICdOVU1CRVInLFxuICBCT09MRUFOID0gJ0JPT0xFQU4nLFxuICBOVUxMID0gJ05VTEwnLFxuICBVTkRFRklORUQgPSAnVU5ERUZJTkVEJyxcbiAgT1BFUkFUT1IgPSAnT1BFUkFUT1InLFxuICBMT0dJQ0FMID0gJ0xPR0lDQUwnLFxuICBOT1QgPSAnTk9UJyxcbiAgQVJJVEhNRVRJQyA9ICdBUklUSE1FVElDJyxcbiAgUEFSRU5fT1BFTiA9ICdQQVJFTl9PUEVOJyxcbiAgUEFSRU5fQ0xPU0UgPSAnUEFSRU5fQ0xPU0UnLFxuICBURVJOQVJZX1FVRVNUSU9OID0gJ1RFUk5BUllfUVVFU1RJT04nLFxuICBURVJOQVJZX0NPTE9OID0gJ1RFUk5BUllfQ09MT04nLFxuICBFT0YgPSAnRU9GJyxcbn1cblxuaW50ZXJmYWNlIFRva2VuIHtcbiAgdHlwZTogVG9rZW5UeXBlO1xuICB2YWx1ZTogYW55O1xufVxuXG5jbGFzcyBUb2tlbml6ZXIge1xuICBwcml2YXRlIHBvcyA9IDA7XG4gIHByaXZhdGUgaW5wdXQ6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihpbnB1dDogc3RyaW5nKSB7XG4gICAgdGhpcy5pbnB1dCA9IGlucHV0LnRyaW0oKTtcbiAgfVxuXG4gIHRva2VuaXplKCk6IFRva2VuW10ge1xuICAgIGNvbnN0IHRva2VuczogVG9rZW5bXSA9IFtdO1xuXG4gICAgd2hpbGUgKHRoaXMucG9zIDwgdGhpcy5pbnB1dC5sZW5ndGgpIHtcbiAgICAgIHRoaXMuc2tpcFdoaXRlc3BhY2UoKTtcblxuICAgICAgaWYgKHRoaXMucG9zID49IHRoaXMuaW5wdXQubGVuZ3RoKSBicmVhaztcblxuICAgICAgY29uc3QgY2hhciA9IHRoaXMuaW5wdXRbdGhpcy5wb3NdO1xuXG4gICAgICAvLyBTdHJpbmcgbGl0ZXJhbHNcbiAgICAgIGlmIChjaGFyID09PSAnXCInIHx8IGNoYXIgPT09IFwiJ1wiKSB7XG4gICAgICAgIHRva2Vucy5wdXNoKHRoaXMucmVhZFN0cmluZygpKTtcbiAgICAgIH1cbiAgICAgIC8vIE51bWJlcnNcbiAgICAgIGVsc2UgaWYgKC9cXGQvLnRlc3QoY2hhcikpIHtcbiAgICAgICAgdG9rZW5zLnB1c2godGhpcy5yZWFkTnVtYmVyKCkpO1xuICAgICAgfVxuICAgICAgLy8gSWRlbnRpZmllcnMgYW5kIGtleXdvcmRzXG4gICAgICBlbHNlIGlmICgvW2EtekEtWl8kXS8udGVzdChjaGFyKSkge1xuICAgICAgICB0b2tlbnMucHVzaCh0aGlzLnJlYWRJZGVudGlmaWVyKCkpO1xuICAgICAgfVxuICAgICAgLy8gT3BlcmF0b3JzIGFuZCBzeW1ib2xzXG4gICAgICBlbHNlIGlmIChjaGFyID09PSAnLicpIHtcbiAgICAgICAgdG9rZW5zLnB1c2goeyB0eXBlOiBUb2tlblR5cGUuRE9ULCB2YWx1ZTogJy4nIH0pO1xuICAgICAgICB0aGlzLnBvcysrO1xuICAgICAgfSBlbHNlIGlmIChjaGFyID09PSAnWycpIHtcbiAgICAgICAgdG9rZW5zLnB1c2goeyB0eXBlOiBUb2tlblR5cGUuQlJBQ0tFVF9PUEVOLCB2YWx1ZTogJ1snIH0pO1xuICAgICAgICB0aGlzLnBvcysrO1xuICAgICAgfSBlbHNlIGlmIChjaGFyID09PSAnXScpIHtcbiAgICAgICAgdG9rZW5zLnB1c2goeyB0eXBlOiBUb2tlblR5cGUuQlJBQ0tFVF9DTE9TRSwgdmFsdWU6ICddJyB9KTtcbiAgICAgICAgdGhpcy5wb3MrKztcbiAgICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gJygnKSB7XG4gICAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogVG9rZW5UeXBlLlBBUkVOX09QRU4sIHZhbHVlOiAnKCcgfSk7XG4gICAgICAgIHRoaXMucG9zKys7XG4gICAgICB9IGVsc2UgaWYgKGNoYXIgPT09ICcpJykge1xuICAgICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFRva2VuVHlwZS5QQVJFTl9DTE9TRSwgdmFsdWU6ICcpJyB9KTtcbiAgICAgICAgdGhpcy5wb3MrKztcbiAgICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gJz8nKSB7XG4gICAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogVG9rZW5UeXBlLlRFUk5BUllfUVVFU1RJT04sIHZhbHVlOiAnPycgfSk7XG4gICAgICAgIHRoaXMucG9zKys7XG4gICAgICB9IGVsc2UgaWYgKGNoYXIgPT09ICc6Jykge1xuICAgICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFRva2VuVHlwZS5URVJOQVJZX0NPTE9OLCB2YWx1ZTogJzonIH0pO1xuICAgICAgICB0aGlzLnBvcysrO1xuICAgICAgfSBlbHNlIGlmIChjaGFyID09PSAnIScpIHtcbiAgICAgICAgaWYgKHRoaXMucGVlaygpID09PSAnPScpIHtcbiAgICAgICAgICBpZiAodGhpcy5pbnB1dFt0aGlzLnBvcyArIDJdID09PSAnPScpIHtcbiAgICAgICAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogVG9rZW5UeXBlLk9QRVJBVE9SLCB2YWx1ZTogJyE9PScgfSk7XG4gICAgICAgICAgICB0aGlzLnBvcyArPSAzO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFRva2VuVHlwZS5PUEVSQVRPUiwgdmFsdWU6ICchPScgfSk7XG4gICAgICAgICAgICB0aGlzLnBvcyArPSAyO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFRva2VuVHlwZS5OT1QsIHZhbHVlOiAnIScgfSk7XG4gICAgICAgICAgdGhpcy5wb3MrKztcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjaGFyID09PSAnPScgfHwgY2hhciA9PT0gJzwnIHx8IGNoYXIgPT09ICc+Jykge1xuICAgICAgICB0b2tlbnMucHVzaCh0aGlzLnJlYWRPcGVyYXRvcigpKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gJysnIHx8IGNoYXIgPT09ICcqJyB8fCBjaGFyID09PSAnLycgfHwgY2hhciA9PT0gJyUnKSB7XG4gICAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogVG9rZW5UeXBlLkFSSVRITUVUSUMsIHZhbHVlOiBjaGFyIH0pO1xuICAgICAgICB0aGlzLnBvcysrO1xuICAgICAgfSBlbHNlIGlmIChjaGFyID09PSAnLScpIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBhIG5lZ2F0aXZlIG51bWJlciBvciBzdWJ0cmFjdGlvblxuICAgICAgICAvLyBJdCdzIGEgbmVnYXRpdmUgbnVtYmVyIGlmIHByZWNlZGVkIGJ5IGFuIG9wZXJhdG9yLCBvcGVuaW5nIHBhcmVuLCBvciBhdCB0aGUgc3RhcnRcbiAgICAgICAgY29uc3QgbGFzdFRva2VuID0gdG9rZW5zW3Rva2Vucy5sZW5ndGggLSAxXTtcbiAgICAgICAgY29uc3QgaXNOZWdhdGl2ZU51bWJlciA9XG4gICAgICAgICAgdG9rZW5zLmxlbmd0aCA9PT0gMCB8fFxuICAgICAgICAgIGxhc3RUb2tlbj8udHlwZSA9PT0gVG9rZW5UeXBlLk9QRVJBVE9SIHx8XG4gICAgICAgICAgbGFzdFRva2VuPy50eXBlID09PSBUb2tlblR5cGUuTE9HSUNBTCB8fFxuICAgICAgICAgIGxhc3RUb2tlbj8udHlwZSA9PT0gVG9rZW5UeXBlLkFSSVRITUVUSUMgfHxcbiAgICAgICAgICBsYXN0VG9rZW4/LnR5cGUgPT09IFRva2VuVHlwZS5QQVJFTl9PUEVOIHx8XG4gICAgICAgICAgbGFzdFRva2VuPy50eXBlID09PSBUb2tlblR5cGUuVEVSTkFSWV9RVUVTVElPTiB8fFxuICAgICAgICAgIGxhc3RUb2tlbj8udHlwZSA9PT0gVG9rZW5UeXBlLlRFUk5BUllfQ09MT047XG5cbiAgICAgICAgaWYgKGlzTmVnYXRpdmVOdW1iZXIgJiYgdGhpcy5wZWVrKCkgJiYgL1xcZC8udGVzdCh0aGlzLnBlZWsoKSkpIHtcbiAgICAgICAgICB0b2tlbnMucHVzaCh0aGlzLnJlYWROdW1iZXIoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdG9rZW5zLnB1c2goeyB0eXBlOiBUb2tlblR5cGUuQVJJVEhNRVRJQywgdmFsdWU6ICctJyB9KTtcbiAgICAgICAgICB0aGlzLnBvcysrO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGNoYXIgPT09ICcmJyAmJiB0aGlzLnBlZWsoKSA9PT0gJyYnKSB7XG4gICAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogVG9rZW5UeXBlLkxPR0lDQUwsIHZhbHVlOiAnJiYnIH0pO1xuICAgICAgICB0aGlzLnBvcyArPSAyO1xuICAgICAgfSBlbHNlIGlmIChjaGFyID09PSAnfCcgJiYgdGhpcy5wZWVrKCkgPT09ICd8Jykge1xuICAgICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFRva2VuVHlwZS5MT0dJQ0FMLCB2YWx1ZTogJ3x8JyB9KTtcbiAgICAgICAgdGhpcy5wb3MgKz0gMjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5leHBlY3RlZCBjaGFyYWN0ZXI6ICR7Y2hhcn0gYXQgcG9zaXRpb24gJHt0aGlzLnBvc31gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFRva2VuVHlwZS5FT0YsIHZhbHVlOiBudWxsIH0pO1xuICAgIHJldHVybiB0b2tlbnM7XG4gIH1cblxuICBwcml2YXRlIHNraXBXaGl0ZXNwYWNlKCk6IHZvaWQge1xuICAgIHdoaWxlICh0aGlzLnBvcyA8IHRoaXMuaW5wdXQubGVuZ3RoICYmIC9cXHMvLnRlc3QodGhpcy5pbnB1dFt0aGlzLnBvc10pKSB7XG4gICAgICB0aGlzLnBvcysrO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcGVlayhvZmZzZXQgPSAxKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5pbnB1dFt0aGlzLnBvcyArIG9mZnNldF0gfHwgJyc7XG4gIH1cblxuICBwcml2YXRlIHJlYWRTdHJpbmcoKTogVG9rZW4ge1xuICAgIGNvbnN0IHF1b3RlID0gdGhpcy5pbnB1dFt0aGlzLnBvc107XG4gICAgdGhpcy5wb3MrKztcbiAgICBsZXQgdmFsdWUgPSAnJztcblxuICAgIHdoaWxlICh0aGlzLnBvcyA8IHRoaXMuaW5wdXQubGVuZ3RoICYmIHRoaXMuaW5wdXRbdGhpcy5wb3NdICE9PSBxdW90ZSkge1xuICAgICAgaWYgKHRoaXMuaW5wdXRbdGhpcy5wb3NdID09PSAnXFxcXCcpIHtcbiAgICAgICAgdGhpcy5wb3MrKztcbiAgICAgICAgaWYgKHRoaXMucG9zIDwgdGhpcy5pbnB1dC5sZW5ndGgpIHtcbiAgICAgICAgICBjb25zdCBlc2NhcGVkID0gdGhpcy5pbnB1dFt0aGlzLnBvc107XG4gICAgICAgICAgc3dpdGNoIChlc2NhcGVkKSB7XG4gICAgICAgICAgICBjYXNlICduJzpcbiAgICAgICAgICAgICAgdmFsdWUgKz0gJ1xcbic7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAndCc6XG4gICAgICAgICAgICAgIHZhbHVlICs9ICdcXHQnO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3InOlxuICAgICAgICAgICAgICB2YWx1ZSArPSAnXFxyJztcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICB2YWx1ZSArPSBlc2NhcGVkO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWUgKz0gdGhpcy5pbnB1dFt0aGlzLnBvc107XG4gICAgICB9XG4gICAgICB0aGlzLnBvcysrO1xuICAgIH1cblxuICAgIHRoaXMucG9zKys7IC8vIHNraXAgY2xvc2luZyBxdW90ZVxuICAgIHJldHVybiB7IHR5cGU6IFRva2VuVHlwZS5TVFJJTkcsIHZhbHVlIH07XG4gIH1cblxuICBwcml2YXRlIHJlYWROdW1iZXIoKTogVG9rZW4ge1xuICAgIGxldCB2YWx1ZSA9ICcnO1xuXG4gICAgLy8gSGFuZGxlIG5lZ2F0aXZlc1xuICAgIGlmICh0aGlzLmlucHV0W3RoaXMucG9zXSA9PT0gJy0nKSB7XG4gICAgICB2YWx1ZSArPSAnLSc7XG4gICAgICB0aGlzLnBvcysrO1xuICAgIH1cblxuICAgIGxldCBoYXNEZWNpbWFsID0gZmFsc2U7XG4gICAgd2hpbGUgKHRoaXMucG9zIDwgdGhpcy5pbnB1dC5sZW5ndGggJiYgL1tcXGQuXS8udGVzdCh0aGlzLmlucHV0W3RoaXMucG9zXSkpIHtcbiAgICAgIGlmICh0aGlzLmlucHV0W3RoaXMucG9zXSA9PT0gJy4nKSB7XG4gICAgICAgIGlmIChoYXNEZWNpbWFsKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIG51bWJlciBmb3JtYXQ6IG11bHRpcGxlIGRlY2ltYWwgcG9pbnRzIGF0IHBvc2l0aW9uICR7dGhpcy5wb3N9YCk7XG4gICAgICAgIH1cbiAgICAgICAgaGFzRGVjaW1hbCA9IHRydWU7XG4gICAgICB9XG4gICAgICB2YWx1ZSArPSB0aGlzLmlucHV0W3RoaXMucG9zXTtcbiAgICAgIHRoaXMucG9zKys7XG4gICAgfVxuXG4gICAgY29uc3QgcGFyc2VkID0gcGFyc2VGbG9hdCh2YWx1ZSk7XG4gICAgaWYgKGlzTmFOKHBhcnNlZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBudW1iZXIgZm9ybWF0OiAke3ZhbHVlfWApO1xuICAgIH1cblxuICAgIHJldHVybiB7IHR5cGU6IFRva2VuVHlwZS5OVU1CRVIsIHZhbHVlOiBwYXJzZWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZElkZW50aWZpZXIoKTogVG9rZW4ge1xuICAgIGxldCB2YWx1ZSA9ICcnO1xuXG4gICAgd2hpbGUgKHRoaXMucG9zIDwgdGhpcy5pbnB1dC5sZW5ndGggJiYgL1thLXpBLVowLTlfJF0vLnRlc3QodGhpcy5pbnB1dFt0aGlzLnBvc10pKSB7XG4gICAgICB2YWx1ZSArPSB0aGlzLmlucHV0W3RoaXMucG9zXTtcbiAgICAgIHRoaXMucG9zKys7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGtleXdvcmRzXG4gICAgaWYgKHZhbHVlID09PSAndHJ1ZScgfHwgdmFsdWUgPT09ICdmYWxzZScpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IFRva2VuVHlwZS5CT09MRUFOLCB2YWx1ZTogdmFsdWUgPT09ICd0cnVlJyB9O1xuICAgIH1cbiAgICBpZiAodmFsdWUgPT09ICdudWxsJykge1xuICAgICAgcmV0dXJuIHsgdHlwZTogVG9rZW5UeXBlLk5VTEwsIHZhbHVlOiBudWxsIH07XG4gICAgfVxuICAgIGlmICh2YWx1ZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IFRva2VuVHlwZS5VTkRFRklORUQsIHZhbHVlOiB1bmRlZmluZWQgfTtcbiAgICB9XG5cbiAgICByZXR1cm4geyB0eXBlOiBUb2tlblR5cGUuSURFTlRJRklFUiwgdmFsdWUgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZE9wZXJhdG9yKCk6IFRva2VuIHtcbiAgICBsZXQgb3AgPSB0aGlzLmlucHV0W3RoaXMucG9zXTtcbiAgICB0aGlzLnBvcysrO1xuXG4gICAgaWYgKHRoaXMucG9zIDwgdGhpcy5pbnB1dC5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IG5leHQgPSB0aGlzLmlucHV0W3RoaXMucG9zXTtcbiAgICAgIGlmIChcbiAgICAgICAgKG9wID09PSAnPScgJiYgbmV4dCA9PT0gJz0nKSB8fFxuICAgICAgICAob3AgPT09ICchJyAmJiBuZXh0ID09PSAnPScpIHx8XG4gICAgICAgIChvcCA9PT0gJzwnICYmIG5leHQgPT09ICc9JykgfHxcbiAgICAgICAgKG9wID09PSAnPicgJiYgbmV4dCA9PT0gJz0nKVxuICAgICAgKSB7XG4gICAgICAgIG9wICs9IG5leHQ7XG4gICAgICAgIHRoaXMucG9zKys7XG5cbiAgICAgICAgLy8gQ2hlY2sgZm9yID09PSBvciAhPT1cbiAgICAgICAgaWYgKHRoaXMucG9zIDwgdGhpcy5pbnB1dC5sZW5ndGggJiYgdGhpcy5pbnB1dFt0aGlzLnBvc10gPT09ICc9Jykge1xuICAgICAgICAgIG9wICs9ICc9JztcbiAgICAgICAgICB0aGlzLnBvcysrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgdHlwZTogVG9rZW5UeXBlLk9QRVJBVE9SLCB2YWx1ZTogb3AgfTtcbiAgfVxufVxuXG4vLyBQYXJzZXIgYW5kIEV2YWx1YXRvclxuY2xhc3MgRXhwcmVzc2lvblBhcnNlciB7XG4gIHByaXZhdGUgdG9rZW5zOiBUb2tlbltdO1xuICBwcml2YXRlIHBvcyA9IDA7XG5cbiAgY29uc3RydWN0b3IodG9rZW5zOiBUb2tlbltdKSB7XG4gICAgdGhpcy50b2tlbnMgPSB0b2tlbnM7XG4gIH1cblxuICBwYXJzZSgpOiAoY29udGV4dDogRXhwcmVzc2lvbkNvbnRleHQpID0+IGFueSB7XG4gICAgY29uc3QgZXhwciA9IHRoaXMucGFyc2VUZXJuYXJ5KCk7XG4gICAgcmV0dXJuIChjb250ZXh0OiBFeHByZXNzaW9uQ29udGV4dCkgPT4gZXhwcihjb250ZXh0KTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VUZXJuYXJ5KCk6IChjb250ZXh0OiBFeHByZXNzaW9uQ29udGV4dCkgPT4gYW55IHtcbiAgICBjb25zdCBleHByID0gdGhpcy5wYXJzZUxvZ2ljYWxPcigpO1xuXG4gICAgaWYgKHRoaXMuY3VycmVudCgpLnR5cGUgPT09IFRva2VuVHlwZS5URVJOQVJZX1FVRVNUS