UNPKG

@glimmer/syntax

Version:
587 lines (491 loc) 49.8 kB
// eslint-disable-next-line import/no-extraneous-dependencies import { DEBUG } from '@glimmer/env'; import { assertNever } from '@glimmer/util'; import { BROKEN_LOCATION, NON_EXISTENT_LOCATION } from '../location'; import { SourceSlice } from '../slice'; import { IsInvisible, match, MatchAny } from './match'; import { BROKEN, CharPosition, HbsPosition, InvisiblePosition } from './offset'; /** * A `SourceSpan` object represents a span of characters inside of a template source. * * There are three kinds of `SourceSpan` objects: * * - `ConcreteSourceSpan`, which contains byte offsets * - `LazySourceSpan`, which contains `SourceLocation`s from the Handlebars AST, which can be * converted to byte offsets on demand. * - `InvisibleSourceSpan`, which represent source strings that aren't present in the source, * because: * - they were created synthetically * - their location is nonsensical (the span is broken) * - they represent nothing in the source (this currently happens only when a bug in the * upstream Handlebars parser fails to assign a location to empty blocks) * * At a high level, all `SourceSpan` objects provide: * * - byte offsets * - source in column and line format * * And you can do these operations on `SourceSpan`s: * * - collapse it to a `SourceSpan` representing its starting or ending position * - slice out some characters, optionally skipping some characters at the beginning or end * - create a new `SourceSpan` with a different starting or ending offset * * All SourceSpan objects implement `SourceLocation`, for compatibility. All SourceSpan * objects have a `toJSON` that emits `SourceLocation`, also for compatibility. * * For compatibility, subclasses of `AbstractSourceSpan` must implement `locDidUpdate`, which * happens when an AST plugin attempts to modify the `start` or `end` of a span directly. * * The goal is to avoid creating any problems for use-cases like AST Explorer. */ export class SourceSpan { constructor(data) { this.data = data; this.isInvisible = data.kind !== "CharPosition" /* CharPosition */ && data.kind !== "HbsPosition" /* HbsPosition */ ; } static get NON_EXISTENT() { return new InvisibleSpan("NonExistent" /* NonExistent */ , NON_EXISTENT_LOCATION).wrap(); } static load(source, serialized) { if (typeof serialized === 'number') { return SourceSpan.forCharPositions(source, serialized, serialized); } else if (typeof serialized === 'string') { return SourceSpan.synthetic(serialized); } else if (Array.isArray(serialized)) { return SourceSpan.forCharPositions(source, serialized[0], serialized[1]); } else if (serialized === "NonExistent" /* NonExistent */ ) { return SourceSpan.NON_EXISTENT; } else if (serialized === "Broken" /* Broken */ ) { return SourceSpan.broken(BROKEN_LOCATION); } assertNever(serialized); } static forHbsLoc(source, loc) { let start = new HbsPosition(source, loc.start); let end = new HbsPosition(source, loc.end); return new HbsSpan(source, { start, end }, loc).wrap(); } static forCharPositions(source, startPos, endPos) { let start = new CharPosition(source, startPos); let end = new CharPosition(source, endPos); return new CharPositionSpan(source, { start, end }).wrap(); } static synthetic(chars) { return new InvisibleSpan("InternalsSynthetic" /* InternalsSynthetic */ , NON_EXISTENT_LOCATION, chars).wrap(); } static broken(pos = BROKEN_LOCATION) { return new InvisibleSpan("Broken" /* Broken */ , pos).wrap(); } getStart() { return this.data.getStart().wrap(); } getEnd() { return this.data.getEnd().wrap(); } get loc() { let span = this.data.toHbsSpan(); return span === null ? BROKEN_LOCATION : span.toHbsLoc(); } get module() { return this.data.getModule(); } /** * Get the starting `SourcePosition` for this `SourceSpan`, lazily computing it if needed. */ get startPosition() { return this.loc.start; } /** * Get the ending `SourcePosition` for this `SourceSpan`, lazily computing it if needed. */ get endPosition() { return this.loc.end; } /** * Support converting ASTv1 nodes into a serialized format using JSON.stringify. */ toJSON() { return this.loc; } /** * Create a new span with the current span's end and a new beginning. */ withStart(other) { return span(other.data, this.data.getEnd()); } /** * Create a new span with the current span's beginning and a new ending. */ withEnd(other) { return span(this.data.getStart(), other.data); } asString() { return this.data.asString(); } /** * Convert this `SourceSpan` into a `SourceSlice`. In debug mode, this method optionally checks * that the byte offsets represented by this `SourceSpan` actually correspond to the expected * string. */ toSlice(expected) { let chars = this.data.asString(); if (DEBUG) { if (expected !== undefined && chars !== expected) { // eslint-disable-next-line no-console console.warn(`unexpectedly found ${JSON.stringify(chars)} when slicing source, but expected ${JSON.stringify(expected)}`); } } return new SourceSlice({ loc: this, chars: expected || chars }); } /** * For compatibility with SourceLocation in AST plugins * * @deprecated use startPosition instead */ get start() { return this.loc.start; } /** * For compatibility with SourceLocation in AST plugins * * @deprecated use withStart instead */ set start(position) { this.data.locDidUpdate({ start: position }); } /** * For compatibility with SourceLocation in AST plugins * * @deprecated use endPosition instead */ get end() { return this.loc.end; } /** * For compatibility with SourceLocation in AST plugins * * @deprecated use withEnd instead */ set end(position) { this.data.locDidUpdate({ end: position }); } /** * For compatibility with SourceLocation in AST plugins * * @deprecated use module instead */ get source() { return this.module; } collapse(where) { switch (where) { case 'start': return this.getStart().collapsed(); case 'end': return this.getEnd().collapsed(); } } extend(other) { return span(this.data.getStart(), other.data.getEnd()); } serialize() { return this.data.serialize(); } slice({ skipStart = 0, skipEnd = 0 }) { return span(this.getStart().move(skipStart).data, this.getEnd().move(-skipEnd).data); } sliceStartChars({ skipStart = 0, chars }) { return span(this.getStart().move(skipStart).data, this.getStart().move(skipStart + chars).data); } sliceEndChars({ skipEnd = 0, chars }) { return span(this.getEnd().move(skipEnd - chars).data, this.getStart().move(-skipEnd).data); } } class CharPositionSpan { constructor(source, charPositions) { this.source = source; this.charPositions = charPositions; this.kind = "CharPosition" /* CharPosition */ ; this._locPosSpan = null; } wrap() { return new SourceSpan(this); } asString() { return this.source.slice(this.charPositions.start.charPos, this.charPositions.end.charPos); } getModule() { return this.source.module; } getStart() { return this.charPositions.start; } getEnd() { return this.charPositions.end; } locDidUpdate() { if (false /* LOCAL_DEBUG */ ) { // eslint-disable-next-line no-console console.warn(`updating a location that came from a CharPosition span doesn't work reliably. Don't try to update locations after the plugin phase`); } } toHbsSpan() { let locPosSpan = this._locPosSpan; if (locPosSpan === null) { let start = this.charPositions.start.toHbsPos(); let end = this.charPositions.end.toHbsPos(); if (start === null || end === null) { locPosSpan = this._locPosSpan = BROKEN; } else { locPosSpan = this._locPosSpan = new HbsSpan(this.source, { start, end }); } } return locPosSpan === BROKEN ? null : locPosSpan; } serialize() { let { start: { charPos: start }, end: { charPos: end } } = this.charPositions; if (start === end) { return start; } else { return [start, end]; } } toCharPosSpan() { return this; } } export class HbsSpan { constructor(source, hbsPositions, providedHbsLoc = null) { this.source = source; this.hbsPositions = hbsPositions; this.kind = "HbsPosition" /* HbsPosition */ ; this._charPosSpan = null; this._providedHbsLoc = providedHbsLoc; } serialize() { let charPos = this.toCharPosSpan(); return charPos === null ? "Broken" /* Broken */ : charPos.wrap().serialize(); } wrap() { return new SourceSpan(this); } updateProvided(pos, edge) { if (this._providedHbsLoc) { this._providedHbsLoc[edge] = pos; } // invalidate computed character offsets this._charPosSpan = null; this._providedHbsLoc = { start: pos, end: pos }; } locDidUpdate({ start, end }) { if (start !== undefined) { this.updateProvided(start, 'start'); this.hbsPositions.start = new HbsPosition(this.source, start, null); } if (end !== undefined) { this.updateProvided(end, 'end'); this.hbsPositions.end = new HbsPosition(this.source, end, null); } } asString() { let span = this.toCharPosSpan(); return span === null ? '' : span.asString(); } getModule() { return this.source.module; } getStart() { return this.hbsPositions.start; } getEnd() { return this.hbsPositions.end; } toHbsLoc() { return { start: this.hbsPositions.start.hbsPos, end: this.hbsPositions.end.hbsPos }; } toHbsSpan() { return this; } toCharPosSpan() { let charPosSpan = this._charPosSpan; if (charPosSpan === null) { let start = this.hbsPositions.start.toCharPos(); let end = this.hbsPositions.end.toCharPos(); if (start && end) { charPosSpan = this._charPosSpan = new CharPositionSpan(this.source, { start, end }); } else { charPosSpan = this._charPosSpan = BROKEN; return null; } } return charPosSpan === BROKEN ? null : charPosSpan; } } class InvisibleSpan { constructor(kind, // whatever was provided, possibly broken loc, // if the span represents a synthetic string string = null) { this.kind = kind; this.loc = loc; this.string = string; } serialize() { switch (this.kind) { case "Broken" /* Broken */ : case "NonExistent" /* NonExistent */ : return this.kind; case "InternalsSynthetic" /* InternalsSynthetic */ : return this.string || ''; } } wrap() { return new SourceSpan(this); } asString() { return this.string || ''; } locDidUpdate({ start, end }) { if (start !== undefined) { this.loc.start = start; } if (end !== undefined) { this.loc.end = end; } } getModule() { // TODO: Make this reflect the actual module this span originated from return 'an unknown module'; } getStart() { return new InvisiblePosition(this.kind, this.loc.start); } getEnd() { return new InvisiblePosition(this.kind, this.loc.end); } toCharPosSpan() { return this; } toHbsSpan() { return null; } toHbsLoc() { return BROKEN_LOCATION; } } export const span = match(m => m.when("HbsPosition" /* HbsPosition */ , "HbsPosition" /* HbsPosition */ , (left, right) => new HbsSpan(left.source, { start: left, end: right }).wrap()).when("CharPosition" /* CharPosition */ , "CharPosition" /* CharPosition */ , (left, right) => new CharPositionSpan(left.source, { start: left, end: right }).wrap()).when("CharPosition" /* CharPosition */ , "HbsPosition" /* HbsPosition */ , (left, right) => { let rightCharPos = right.toCharPos(); if (rightCharPos === null) { return new InvisibleSpan("Broken" /* Broken */ , BROKEN_LOCATION).wrap(); } else { return span(left, rightCharPos); } }).when("HbsPosition" /* HbsPosition */ , "CharPosition" /* CharPosition */ , (left, right) => { let leftCharPos = left.toCharPos(); if (leftCharPos === null) { return new InvisibleSpan("Broken" /* Broken */ , BROKEN_LOCATION).wrap(); } else { return span(leftCharPos, right); } }).when(IsInvisible, MatchAny, left => new InvisibleSpan(left.kind, BROKEN_LOCATION).wrap()).when(MatchAny, IsInvisible, (_, right) => new InvisibleSpan(right.kind, BROKEN_LOCATION).wrap())); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3N5bnRheC9saWIvc291cmNlL2xvYy9zcGFuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0EsU0FBUyxLQUFULFFBQXNCLGNBQXRCO0FBRUEsU0FBUyxXQUFULFFBQTRCLGVBQTVCO0FBRUEsU0FDRSxlQURGLEVBRUUscUJBRkYsUUFLTyxhQUxQO0FBTUEsU0FBUyxXQUFULFFBQTRCLFVBQTVCO0FBRUEsU0FBUyxXQUFULEVBQXNCLEtBQXRCLEVBQTZCLFFBQTdCLFFBQXNELFNBQXREO0FBQ0EsU0FFRSxNQUZGLEVBR0UsWUFIRixFQUlFLFdBSkYsRUFLRSxpQkFMRixRQVFPLFVBUlA7QUF5REE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBa0NBLE9BQU0sTUFBTyxVQUFQLENBQWlCO0FBNENyQixFQUFBLFdBQUEsQ0FBb0IsSUFBcEIsRUFBNEM7QUFBeEIsU0FBQSxJQUFBLEdBQUEsSUFBQTtBQUNsQixTQUFLLFdBQUwsR0FDRSxJQUFJLENBQUMsSUFBTCxLQUFTO0FBQUE7QUFBVCxPQUF5QyxJQUFJLENBQUMsSUFBTCxLQUFTO0FBQUE7QUFEcEQ7QUFFRDs7QUE5Q0QsYUFBVyxZQUFYLEdBQXVCO0FBQ3JCLFdBQU8sSUFBSSxhQUFKLENBQWlCO0FBQUE7QUFBakIsTUFBMEMscUJBQTFDLEVBQWlFLElBQWpFLEVBQVA7QUFDRDs7QUFFRCxTQUFPLElBQVAsQ0FBWSxNQUFaLEVBQTRCLFVBQTVCLEVBQTREO0FBQzFELFFBQUksT0FBTyxVQUFQLEtBQXNCLFFBQTFCLEVBQW9DO0FBQ2xDLGFBQU8sVUFBVSxDQUFDLGdCQUFYLENBQTRCLE1BQTVCLEVBQW9DLFVBQXBDLEVBQWdELFVBQWhELENBQVA7QUFDRCxLQUZELE1BRU8sSUFBSSxPQUFPLFVBQVAsS0FBc0IsUUFBMUIsRUFBb0M7QUFDekMsYUFBTyxVQUFVLENBQUMsU0FBWCxDQUFxQixVQUFyQixD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R0FGRCxNQUVPO0FBQ0wsV0FBTyxJQUFJLENBQUMsSUFBRCxFQUFPLFlBQVAsQ0FBWDtBQUNEO0FBQ0YsQ0FyQkgsRUFzQkcsSUF0QkgsQ0FzQk87QUFBQTtBQXRCUCxFQXNCTztBQUFBO0FBdEJQLEVBc0J5RCxDQUFDLElBQUQsRUFBTyxLQUFQLEtBQWdCO0FBQ3JFLE1BQUksV0FBVyxHQUFHLElBQUksQ0FBQyxTQUFMLEVBQWxCOztBQUVBLE1BQUksV0FBVyxLQUFLLElBQXBCLEVBQTBCO0FBQ3hCLFdBQU8sSUFBSSxhQUFKLENBQWlCO0FBQUE7QUFBakIsTUFBcUMsZUFBckMsRUFBc0QsSUFBdEQsRUFBUDtBQUNELEdBRkQsTUFFTztBQUNMLFdBQU8sSUFBSSxDQUFDLFdBQUQsRUFBYyxLQUFkLENBQVg7QUFDRDtBQUNGLENBOUJILEVBK0JHLElBL0JILENBK0JRLFdBL0JSLEVBK0JxQixRQS9CckIsRUErQmdDLElBQUQsSUFBVSxJQUFJLGFBQUosQ0FBa0IsSUFBSSxDQUFDLElBQXZCLEVBQTZCLGVBQTdCLEVBQThDLElBQTlDLEVBL0J6QyxFQWdDRyxJQWhDSCxDQWdDUSxRQWhDUixFQWdDa0IsV0FoQ2xCLEVBZ0MrQixDQUFDLENBQUQsRUFBSSxLQUFKLEtBQzNCLElBQUksYUFBSixDQUFrQixLQUFLLENBQUMsSUFBeEIsRUFBOEIsZUFBOUIsRUFBK0MsSUFBL0MsRUFqQ0osQ0FENEMsQ0FBdkMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBERUJVRyB9IGZyb20gJ0BnbGltbWVyL2Vudic7XG5pbXBvcnQgeyBMT0NBTF9ERUJVRyB9IGZyb20gJ0BnbGltbWVyL2xvY2FsLWRlYnVnLWZsYWdzJztcbmltcG9ydCB7IGFzc2VydE5ldmVyIH0gZnJvbSAnQGdsaW1tZXIvdXRpbCc7XG5cbmltcG9ydCB7XG4gIEJST0tFTl9MT0NBVElPTixcbiAgTk9OX0VYSVNURU5UX0xPQ0FUSU9OLFxuICBTb3VyY2VMb2NhdGlvbixcbiAgU291cmNlUG9zaXRpb24sXG59IGZyb20gJy4uL2xvY2F0aW9uJztcbmltcG9ydCB7IFNvdXJjZVNsaWNlIH0gZnJvbSAnLi4vc2xpY2UnO1xuaW1wb3J0IHsgU291cmNlIH0gZnJvbSAnLi4vc291cmNlJztcbmltcG9ydCB7IElzSW52aXNpYmxlLCBtYXRjaCwgTWF0Y2hBbnksIE1hdGNoRm4gfSBmcm9tICcuL21hdGNoJztcbmltcG9ydCB7XG4gIEFueVBvc2l0aW9uLFxuICBCUk9LRU4sXG4gIENoYXJQb3NpdGlvbixcbiAgSGJzUG9zaXRpb24sXG4gIEludmlzaWJsZVBvc2l0aW9uLFxuICBPZmZzZXRLaW5kLFxuICBTb3VyY2VPZmZzZXQsXG59IGZyb20gJy4vb2Zmc2V0JztcblxuLyoqXG4gKiBBbGwgc3BhbnMgaGF2ZSB0aGVzZSBkZXRhaWxzIGluIGNvbW1vbi5cbiAqL1xuaW50ZXJmYWNlIFNwYW5EYXRhIHtcbiAgcmVhZG9ubHkga2luZDogT2Zmc2V0S2luZDtcblxuICAvKipcbiAgICogQ29udmVydCB0aGlzIHNwYW4gaW50byBhIHN0cmluZy4gSWYgdGhlIHNwYW4gaXMgYnJva2VuLCByZXR1cm4gYCcnYC5cbiAgICovXG4gIGFzU3RyaW5nKCk6IHN0cmluZztcblxuICAvKipcbiAgICogR2V0cyB0aGUgbW9kdWxlIHRoZSBzcGFuIHdhcyBsb2NhdGVkIGluLlxuICAgKi9cbiAgZ2V0TW9kdWxlKCk6IHN0cmluZztcblxuICAvKipcbiAgICogR2V0IHRoZSBzdGFydGluZyBwb3NpdGlvbiBmb3IgdGhpcyBzcGFuLiBUcnkgdG8gYXZvaWQgY3JlYXRpbmcgbmV3IHBvc2l0aW9uIG9iamVjdHMsIGFzIHRoZXlcbiAgICogY2FjaGUgY29tcHV0YXRpb25zLlxuICAgKi9cbiAgZ2V0U3RhcnQoKTogQW55UG9zaXRpb247XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZW5kaW5nIHBvc2l0aW9uIGZvciB0aGlzIHNwYW4uIFRyeSB0byBhdm9pZCBjcmVhdGluZyBuZXcgcG9zaXRpb24gb2JqZWN0cywgYXMgdGhleVxuICAgKiBjYWNoZSBjb21wdXRhdGlvbnMuXG4gICAqL1xuICBnZXRFbmQoKTogQW55UG9zaXRpb247XG5cbiAgLyoqXG4gICAqIENvbXB1dGUgdGhlIGBTb3VyY2VMb2NhdGlvbmAgZm9yIHRoaXMgc3BhbiwgcmV0dXJuZWQgYXMgYW4gaW5zdGFuY2Ugb2YgYEhic1NwYW5gLlxuICAgKi9cbiAgdG9IYnNTcGFuKCk6IEhic1NwYW4gfCBudWxsO1xuXG4gIC8qKlxuICAgKiBGb3IgY29tcGF0aWJpbGl0eSwgd2hlbmV2ZXIgdGhlIGBzdGFydGAgb3IgYGVuZGAgb2YgYSB7QHNlZSBTb3VyY2VPZmZzZXR9IGNoYW5nZXMsIHNwYW5zIGFyZVxuICAgKiBub3RpZmllZCBvZiB0aGUgY2hhbmdlIHNvIHRoZXkgY2FuIHVwZGF0ZSB0aGVtc2VsdmVzLiBUaGlzIHNob3VsZG4ndCBoYXBwZW4gb3V0c2lkZSBvZiBBU1RcbiAgICogcGx1Z2lucy5cbiAgICovXG4gIGxvY0RpZFVwZGF0ZShjaGFuZ2VzOiB7IHN0YXJ0PzogU291cmNlUG9zaXRpb247IGVuZD86IFNvdXJjZVBvc2l0aW9uIH0pOiB2b2lkO1xuXG4gIC8qKlxuICAgKiBTZXJpYWxpemUgaW50byBhIHtAc2VlIFNlcmlhbGl6ZWRTb3VyY2VTcGFufSwgd2hpY2ggaXMgY29tcGFjdCBhbmQgZGVzaWduZWQgZm9yIHJlYWRhYmlsaXR5IGluXG4gICAqIGNvbnRleHQgbGlrZSBBU1QgRXhwbG9yZXIuIElmIHlvdSBuZWVkIGEge0BzZWUgU291cmNlTG9jYXRpb259LCB1c2Uge0BzZWUgdG9KU09OfS5cbiAgICovXG4gIHNlcmlhbGl6ZSgpOiBTZXJpYWxpemVkU291cmNlU3Bhbjtcbn1cblxuLyoqXG4gKiBBIGBTb3VyY2VTcGFuYCBvYmplY3QgcmVwcmVzZW50cyBhIHNwYW4gb2YgY2hhcmFjdGVycyBpbnNpZGUgb2YgYSB0ZW1wbGF0ZSBzb3VyY2UuXG4gKlxuICogVGhlcmUgYXJlIHRocmVlIGtpbmRzIG9mIGBTb3VyY2VTcGFuYCBvYmplY3RzOlxuICpcbiAqIC0gYENvbmNyZXRlU291cmNlU3BhbmAsIHdoaWNoIGNvbnRhaW5zIGJ5dGUgb2Zmc2V0c1xuICogLSBgTGF6eVNvdXJjZVNwYW5gLCB3aGljaCBjb250YWlucyBgU291cmNlTG9jYXRpb25gcyBmcm9tIHRoZSBIYW5kbGViYXJzIEFTVCwgd2hpY2ggY2FuIGJlXG4gKiAgIGNvbnZlcnRlZCB0byBieXRlIG9mZnNldHMgb24gZGVtYW5kLlxuICogLSBgSW52aXNpYmxlU291cmNlU3BhbmAsIHdoaWNoIHJlcHJlc2VudCBzb3VyY2Ugc3RyaW5ncyB0aGF0IGFyZW4ndCBwcmVzZW50IGluIHRoZSBzb3VyY2UsXG4gKiAgIGJlY2F1c2U6XG4gKiAgICAgLSB0aGV5IHdlcmUgY3JlYXRlZCBzeW50aGV0aWNhbGx5XG4gKiAgICAgLSB0aGVpciBsb2NhdGlvbiBpcyBub25zZW5zaWNhbCAodGhlIHNwYW4gaXMgYnJva2VuKVxuICogICAgIC0gdGhleSByZXByZXNlbnQgbm90aGluZyBpbiB0aGUgc291cmNlICh0aGlzIGN1cnJlbnRseSBoYXBwZW5zIG9ubHkgd2hlbiBhIGJ1ZyBpbiB0aGVcbiAqICAgICAgIHVwc3RyZWFtIEhhbmRsZWJhcnMgcGFyc2VyIGZhaWxzIHRvIGFzc2lnbiBhIGxvY2F0aW9uIHRvIGVtcHR5IGJsb2NrcylcbiAqXG4gKiBBdCBhIGhpZ2ggbGV2ZWwsIGFsbCBgU291cmNlU3BhbmAgb2JqZWN0cyBwcm92aWRlOlxuICpcbiAqIC0gYnl0ZSBvZmZzZXRzXG4gKiAtIHNvdXJjZSBpbiBjb2x1bW4gYW5kIGxpbmUgZm9ybWF0XG4gKlxuICogQW5kIHlvdSBjYW4gZG8gdGhlc2Ugb3BlcmF0aW9ucyBvbiBgU291cmNlU3BhbmBzOlxuICpcbiAqIC0gY29sbGFwc2UgaXQgdG8gYSBgU291cmNlU3BhbmAgcmVwcmVzZW50aW5nIGl0cyBzdGFydGluZyBvciBlbmRpbmcgcG9zaXRpb25cbiAqIC0gc2xpY2Ugb3V0IHNvbWUgY2hhcmFjdGVycywgb3B0aW9uYWxseSBza2lwcGluZyBzb21lIGNoYXJhY3RlcnMgYXQgdGhlIGJlZ2lubmluZyBvciBlbmRcbiAqIC0gY3JlYXRlIGEgbmV3IGBTb3VyY2VTcGFuYCB3aXRoIGEgZGlmZmVyZW50IHN0YXJ0aW5nIG9yIGVuZGluZyBvZmZzZXRcbiAqXG4gKiBBbGwgU291cmNlU3BhbiBvYmplY3RzIGltcGxlbWVudCBgU291cmNlTG9jYXRpb25gLCBmb3IgY29tcGF0aWJpbGl0eS4gQWxsIFNvdXJjZVNwYW5cbiAqIG9iamVjdHMgaGF2ZSBhIGB0b0pTT05gIHRoYXQgZW1pdHMgYFNvdXJjZUxvY2F0aW9uYCwgYWxzbyBmb3IgY29tcGF0aWJpbGl0eS5cbiAqXG4gKiBGb3IgY29tcGF0aWJpbGl0eSwgc3ViY2xhc3NlcyBvZiBgQWJzdHJhY3RTb3VyY2VTcGFuYCBtdXN0IGltcGxlbWVudCBgbG9jRGlkVXBkYXRlYCwgd2hpY2hcbiAqIGhhcHBlbnMgd2hlbiBhbiBBU1QgcGx1Z2luIGF0dGVtcHRzIHRvIG1vZGlmeSB0aGUgYHN0YXJ0YCBvciBgZW5kYCBvZiBhIHNwYW4gZGlyZWN0bHkuXG4gKlxuICogVGhlIGdvYWwgaXMgdG8gYXZvaWQgY3JlYXRpbmcgYW55IHByb2JsZW1zIGZvciB1c2UtY2FzZXMgbGlrZSBBU1QgRXhwbG9yZXIuXG4gKi9cbmV4cG9ydCBjbGFzcyBTb3VyY2VTcGFuIGltcGxlbWVudHMgU291cmNlTG9jYXRpb24ge1xuICBzdGF0aWMgZ2V0IE5PTl9FWElTVEVOVCgpOiBTb3VyY2VTcGFuIHtcbiAgICByZXR1cm4gbmV3IEludmlzaWJsZVNwYW4oT2Zmc2V0S2luZC5Ob25FeGlzdGVudCwgTk9OX0VYSVNURU5UX0xPQ0FUSU9OKS53cmFwKCk7XG4gIH1cblxuICBzdGF0aWMgbG9hZChzb3VyY2U6IFNvdXJjZSwgc2VyaWFsaXplZDogU2VyaWFsaXplZFNvdXJjZVNwYW4pOiBTb3VyY2VTcGFuIHtcbiAgICBpZiAodHlwZW9mIHNlcmlhbGl6ZWQgPT09ICdudW1iZXInKSB7XG4gICAgICByZXR1cm4gU291cmNlU3Bhbi5mb3JDaGFyUG9zaXRpb25zKHNvdXJjZSwgc2VyaWFsaXplZCwgc2VyaWFsaXplZCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygc2VyaWFsaXplZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBTb3VyY2VTcGFuLnN5bnRoZXRpYyhzZXJpYWxpemVkKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoc2VyaWFsaXplZCkpIHtcbiAgICAgIHJldHVybiBTb3VyY2VTcGFuLmZvckNoYXJQb3NpdGlvbnMoc291cmNlLCBzZXJpYWxpemVkWzBdLCBzZXJpYWxpemVkWzFdKTtcbiAgICB9IGVsc2UgaWYgKHNlcmlhbGl6ZWQgPT09IE9mZnNldEtpbmQuTm9uRXhpc3RlbnQpIHtcbiAgICAgIHJldHVybiBTb3VyY2VTcGFuLk5PTl9FWElTVEVOVDtcbiAgICB9IGVsc2UgaWYgKHNlcmlhbGl6ZWQgPT09IE9mZnNldEtpbmQuQnJva2VuKSB7XG4gICAgICByZXR1cm4gU291cmNlU3Bhbi5icm9rZW4oQlJPS0VOX0xPQ0FUSU9OKTtcbiAgICB9XG5cbiAgICBhc3NlcnROZXZlcihzZXJpYWxpemVkKTtcbiAgfVxuXG4gIHN0YXRpYyBmb3JIYnNMb2Moc291cmNlOiBTb3VyY2UsIGxvYzogU291cmNlTG9jYXRpb24pOiBTb3VyY2VTcGFuIHtcbiAgICBsZXQgc3RhcnQgPSBuZXcgSGJzUG9zaXRpb24oc291cmNlLCBsb2Muc3RhcnQpO1xuICAgIGxldCBlbmQgPSBuZXcgSGJzUG9zaXRpb24oc291cmNlLCBsb2MuZW5kKTtcbiAgICByZXR1cm4gbmV3IEhic1NwYW4oc291cmNlLCB7IHN0YXJ0LCBlbmQgfSwgbG9jKS53cmFwKCk7XG4gIH1cblxuICBzdGF0aWMgZm9yQ2hhclBvc2l0aW9ucyhzb3VyY2U6IFNvdXJjZSwgc3RhcnRQb3M6IG51bWJlciwgZW5kUG9zOiBudW1iZXIpOiBTb3VyY2VTcGFuIHtcbiAgICBsZXQgc3RhcnQgPSBuZXcgQ2hhclBvc2l0aW9uKHNvdXJjZSwgc3RhcnRQb3MpO1xuICAgIGxldCBlbmQgPSBuZXcgQ2hhclBvc2l0aW9uKHNvdXJjZSwgZW5kUG9zKTtcblxuICAgIHJldHVybiBuZXcgQ2hhclBvc2l0aW9uU3Bhbihzb3VyY2UsIHsgc3RhcnQsIGVuZCB9KS53cmFwKCk7XG4gIH1cblxuICBzdGF0aWMgc3ludGhldGljKGNoYXJzOiBzdHJpbmcpOiBTb3VyY2VTcGFuIHtcbiAgICByZXR1cm4gbmV3IEludmlzaWJsZVNwYW4oT2Zmc2V0S2luZC5JbnRlcm5hbHNTeW50aGV0aWMsIE5PTl9FWElTVEVOVF9MT0NBVElPTiwgY2hhcnMpLndyYXAoKTtcbiAgfVxuXG4gIHN0YXRpYyBicm9rZW4ocG9zOiBTb3VyY2VMb2NhdGlvbiA9IEJST0tFTl9MT0NBVElPTik6IFNvdXJjZVNwYW4ge1xuICAgIHJldHVybiBuZXcgSW52aXNpYmxlU3BhbihPZmZzZXRLaW5kLkJyb2tlbiwgcG9zKS53cmFwKCk7XG4gIH1cblxuICByZWFkb25seSBpc0ludmlzaWJsZTogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGRhdGE6IFNwYW5EYXRhICYgQW55U3Bhbikge1xuICAgIHRoaXMuaXNJbnZpc2libGUgPVxuICAgICAgZGF0YS5raW5kICE9PSBPZmZzZXRLaW5kLkNoYXJQb3NpdGlvbiAmJiBkYXRhLmtpbmQgIT09IE9mZnNldEtpbmQuSGJzUG9zaXRpb247XG4gIH1cblxuICBnZXRTdGFydCgpOiBTb3VyY2VPZmZzZXQge1xuICAgIHJldHVybiB0aGlzLmRhdGEuZ2V0U3RhcnQoKS53cmFwKCk7XG4gIH1cblxuICBnZXRFbmQoKTogU291cmNlT2Zmc2V0IHtcbiAgICByZXR1cm4gdGhpcy5kYXRhLmdldEVuZCgpLndyYXAoKTtcbiAgfVxuXG4gIGdldCBsb2MoKTogU291cmNlTG9jYXRpb24ge1xuICAgIGxldCBzcGFuID0gdGhpcy5kYXRhLnRvSGJzU3BhbigpO1xuICAgIHJldHVybiBzcGFuID09PSBudWxsID8gQlJPS0VOX0xPQ0FUSU9OIDogc3Bhbi50b0hic0xvYygpO1xuICB9XG5cbiAgZ2V0IG1vZHVsZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmRhdGEuZ2V0TW9kdWxlKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBzdGFydGluZyBgU291cmNlUG9zaXRpb25gIGZvciB0aGlzIGBTb3VyY2VTcGFuYCwgbGF6aWx5IGNvbXB1dGluZyBpdCBpZiBuZWVkZWQuXG4gICAqL1xuICBnZXQgc3RhcnRQb3NpdGlvbigpOiBTb3VyY2VQb3NpdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMubG9jLnN0YXJ0O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZW5kaW5nIGBTb3VyY2VQb3NpdGlvbmAgZm9yIHRoaXMgYFNvdXJjZVNwYW5gLCBsYXppbHkgY29tcHV0aW5nIGl0IGlmIG5lZWRlZC5cbiAgICovXG4gIGdldCBlbmRQb3NpdGlvbigpOiBTb3VyY2VQb3NpdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMubG9jLmVuZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdXBwb3J0IGNvbnZlcnRpbmcgQVNUdjEgbm9kZXMgaW50byBhIHNlcmlhbGl6ZWQgZm9ybWF0IHVzaW5nIEpTT04uc3RyaW5naWZ5LlxuICAgKi9cbiAgdG9KU09OKCk6IFNvdXJjZUxvY2F0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5sb2M7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IHNwYW4gd2l0aCB0aGUgY3VycmVudCBzcGFuJ3MgZW5kIGFuZCBhIG5ldyBiZWdpbm5pbmcuXG4gICAqL1xuICB3aXRoU3RhcnQob3RoZXI6IFNvdXJjZU9mZnNldCk6IFNvdXJjZVNwYW4ge1xuICAgIHJldHVybiBzcGFuKG90aGVyLmRhdGEsIHRoaXMuZGF0YS5nZXRFbmQoKSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IHNwYW4gd2l0aCB0aGUgY3VycmVudCBzcGFuJ3MgYmVnaW5uaW5nIGFuZCBhIG5ldyBlbmRpbmcuXG4gICAqL1xuICB3aXRoRW5kKHRoaXM6IFNvdXJjZVNwYW4sIG90aGVyOiBTb3VyY2VPZmZzZXQpOiBTb3VyY2VTcGFuIHtcbiAgICByZXR1cm4gc3Bhbih0aGlzLmRhdGEuZ2V0U3RhcnQoKSwgb3RoZXIuZGF0YSk7XG4gIH1cblxuICBhc1N0cmluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmRhdGEuYXNTdHJpbmcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IHRoaXMgYFNvdXJjZVNwYW5gIGludG8gYSBgU291cmNlU2xpY2VgLiBJbiBkZWJ1ZyBtb2RlLCB0aGlzIG1ldGhvZCBvcHRpb25hbGx5IGNoZWNrc1xuICAgKiB0aGF0IHRoZSBieXRlIG9mZnNldHMgcmVwcmVzZW50ZWQgYnkgdGhpcyBgU291cmNlU3BhbmAgYWN0dWFsbHkgY29ycmVzcG9uZCB0byB0aGUgZXhwZWN0ZWRcbiAgICogc3RyaW5nLlxuICAgKi9cbiAgdG9TbGljZShleHBlY3RlZD86IHN0cmluZyk6IFNvdXJjZVNsaWNlIHtcbiAgICBsZXQgY2hhcnMgPSB0aGlzLmRhdGEuYXNTdHJpbmcoKTtcblxuICAgIGlmIChERUJVRykge1xuICAgICAgaWYgKGV4cGVjdGVkICE9PSB1bmRlZmluZWQgJiYgY2hhcnMgIT09IGV4cGVjdGVkKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBgdW5leHBlY3RlZGx5IGZvdW5kICR7SlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICBjaGFyc1xuICAgICAgICAgICl9IHdoZW4gc2xpY2luZyBzb3VyY2UsIGJ1dCBleHBlY3RlZCAke0pTT04uc3RyaW5naWZ5KGV4cGVjdGVkKX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBTb3VyY2VTbGljZSh7XG4gICAgICBsb2M6IHRoaXMsXG4gICAgICBjaGFyczogZXhwZWN0ZWQgfHwgY2hhcnMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRm9yIGNvbXBhdGliaWxpdHkgd2l0aCBTb3VyY2VMb2NhdGlvbiBpbiBBU1QgcGx1Z2luc1xuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2Ugc3RhcnRQb3NpdGlvbiBpbnN0ZWFkXG4gICAqL1xuICBnZXQgc3RhcnQoKTogU291cmNlUG9zaXRpb24ge1xuICAgIHJldHVybiB0aGlzLmxvYy5zdGFydDtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3IgY29tcGF0aWJpbGl0eSB3aXRoIFNvdXJjZUxvY2F0aW9uIGluIEFTVCBwbHVnaW5zXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHVzZSB3aXRoU3RhcnQgaW5zdGVhZFxuICAgKi9cbiAgc2V0IHN0YXJ0KHBvc2l0aW9uOiBTb3VyY2VQb3NpdGlvbikge1xuICAgIHRoaXMuZGF0YS5sb2NEaWRVcGRhdGUoeyBzdGFydDogcG9zaXRpb24gfSk7XG4gIH1cblxuICAvKipcbiAgICogRm9yIGNvbXBhdGliaWxpdHkgd2l0aCBTb3VyY2VMb2NhdGlvbiBpbiBBU1QgcGx1Z2luc1xuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2UgZW5kUG9zaXRpb24gaW5zdGVhZFxuICAgKi9cbiAgZ2V0IGVuZCgpOiBTb3VyY2VQb3NpdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMubG9jLmVuZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3IgY29tcGF0aWJpbGl0eSB3aXRoIFNvdXJjZUxvY2F0aW9uIGluIEFTVCBwbHVnaW5zXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHVzZSB3aXRoRW5kIGluc3RlYWRcbiAgICovXG4gIHNldCBlbmQocG9zaXRpb246IFNvdXJjZVBvc2l0aW9uKSB7XG4gICAgdGhpcy5kYXRhLmxvY0RpZFVwZGF0ZSh7IGVuZDogcG9zaXRpb24gfSk7XG4gIH1cblxuICAvKipcbiAgICogRm9yIGNvbXBhdGliaWxpdHkgd2l0aCBTb3VyY2VMb2NhdGlvbiBpbiBBU1QgcGx1Z2luc1xuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2UgbW9kdWxlIGluc3RlYWRcbiAgICovXG4gIGdldCBzb3VyY2UoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5tb2R1bGU7XG4gIH1cblxuICBjb2xsYXBzZSh3aGVyZTogJ3N0YXJ0JyB8ICdlbmQnKTogU291cmNlU3BhbiB7XG4gICAgc3dpdGNoICh3aGVyZSkge1xuICAgICAgY2FzZSAnc3RhcnQnOlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRTdGFydCgpLmNvbGxhcHNlZCgpO1xuICAgICAgY2FzZSAnZW5kJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RW5kKCkuY29sbGFwc2VkKCk7XG4gICAgfVxuICB9XG5cbiAgZXh0ZW5kKG90aGVyOiBTb3VyY2VTcGFuKTogU291cmNlU3BhbiB7XG4gICAgcmV0dXJuIHNwYW4odGhpcy5kYXRhLmdldFN0YXJ0KCksIG90aGVyLmRhdGEuZ2V0RW5kKCkpO1xuICB9XG5cbiAgc2VyaWFsaXplKCk6IFNlcmlhbGl6ZWRTb3VyY2VTcGFuIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhLnNlcmlhbGl6ZSgpO1xuICB9XG5cbiAgc2xpY2UoeyBza2lwU3RhcnQgPSAwLCBza2lwRW5kID0gMCB9OiB7IHNraXBTdGFydD86IG51bWJlcjsgc2tpcEVuZD86IG51bWJlciB9KTogU291cmNlU3BhbiB7XG4gICAgcmV0dXJuIHNwYW4odGhpcy5nZXRTdGFydCgpLm1vdmUoc2tpcFN0YXJ0KS5kYXRhLCB0aGlzLmdldEVuZCgpLm1vdmUoLXNraXBFbmQpLmRhdGEpO1xuICB9XG5cbiAgc2xpY2VTdGFydENoYXJzKHsgc2tpcFN0YXJ0ID0gMCwgY2hhcnMgfTogeyBza2lwU3RhcnQ/OiBudW1iZXI7IGNoYXJzOiBudW1iZXIgfSk6IFNvdXJjZVNwYW4ge1xuICAgIHJldHVybiBzcGFuKHRoaXMuZ2V0U3RhcnQoKS5tb3ZlKHNraXBTdGFydCkuZGF0YSwgdGhpcy5nZXRTdGFydCgpLm1vdmUoc2tpcFN0YXJ0ICsgY2hhcnMpLmRhdGEpO1xuICB9XG5cbiAgc2xpY2VFbmRDaGFycyh7IHNraXBFbmQgPSAwLCBjaGFycyB9OiB7IHNraXBFbmQ/OiBudW1iZXI7IGNoYXJzOiBudW1iZXIgfSk6IFNvdXJjZVNwYW4ge1xuICAgIHJldHVybiBzcGFuKHRoaXMuZ2V0RW5kKCkubW92ZShza2lwRW5kIC0gY2hhcnMpLmRhdGEsIHRoaXMuZ2V0U3RhcnQoKS5tb3ZlKC1za2lwRW5kKS5kYXRhKTtcbiAgfVxufVxuXG50eXBlIEFueVNwYW4gPSBIYnNTcGFuIHwgQ2hhclBvc2l0aW9uU3BhbiB8IEludmlzaWJsZVNwYW47XG5cbmNsYXNzIENoYXJQb3NpdGlvblNwYW4gaW1wbGVtZW50cyBTcGFuRGF0YSB7XG4gIHJlYWRvbmx5IGtpbmQgPSBPZmZzZXRLaW5kLkNoYXJQb3NpdGlvbjtcblxuICBfbG9jUG9zU3BhbjogSGJzU3BhbiB8IEJST0tFTiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IHNvdXJjZTogU291cmNlLFxuICAgIHJlYWRvbmx5IGNoYXJQb3NpdGlvbnM6IHsgc3RhcnQ6IENoYXJQb3NpdGlvbjsgZW5kOiBDaGFyUG9zaXRpb24gfVxuICApIHt9XG5cbiAgd3JhcCgpOiBTb3VyY2VTcGFuIHtcbiAgICByZXR1cm4gbmV3IFNvdXJjZVNwYW4odGhpcyk7XG4gIH1cblxuICBhc1N0cmluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNvdXJjZS5zbGljZSh0aGlzLmNoYXJQb3NpdGlvbnMuc3RhcnQuY2hhclBvcywgdGhpcy5jaGFyUG9zaXRpb25zLmVuZC5jaGFyUG9zKTtcbiAgfVxuXG4gIGdldE1vZHVsZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNvdXJjZS5tb2R1bGU7XG4gIH1cblxuICBnZXRTdGFydCgpOiBBbnlQb3NpdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuY2hhclBvc2l0aW9ucy5zdGFydDtcbiAgfVxuXG4gIGdldEVuZCgpOiBBbnlQb3NpdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuY2hhclBvc2l0aW9ucy5lbmQ7XG4gIH1cblxuICBsb2NEaWRVcGRhdGUoKSB7XG4gICAgaWYgKExPQ0FMX0RFQlVHKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgdXBkYXRpbmcgYSBsb2NhdGlvbiB0aGF0IGNhbWUgZnJvbSBhIENoYXJQb3NpdGlvbiBzcGFuIGRvZXNuJ3Qgd29yayByZWxpYWJseS4gRG9uJ3QgdHJ5IHRvIHVwZGF0ZSBsb2NhdGlvbnMgYWZ0ZXIgdGhlIHBsdWdpbiBwaGFzZWBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgdG9IYnNTcGFuKCk6IEhic1NwYW4gfCBudWxsIHtcbiAgICBsZXQgbG9jUG9zU3BhbiA9IHRoaXMuX2xvY1Bvc1NwYW47XG5cbiAgICBpZiAobG9jUG9zU3BhbiA9PT0gbnVsbCkge1xuICAgICAgbGV0IHN0YXJ0ID0gdGhpcy5jaGFyUG9zaXRpb25zLnN0YXJ0LnRvSGJzUG9zKCk7XG4gICAgICBsZXQgZW5kID0gdGhpcy5jaGFyUG9zaXRpb25zLmVuZC50b0hic1BvcygpO1xuXG4gICAgICBpZiAoc3RhcnQgPT09IG51bGwgfHwgZW5kID09PSBudWxsKSB7XG4gICAgICAgIGxvY1Bvc1NwYW4gPSB0aGlzLl9sb2NQb3NTcGFuID0gQlJPS0VOO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9jUG9zU3BhbiA9IHRoaXMuX2xvY1Bvc1NwYW4gPSBuZXcgSGJzU3Bhbih0aGlzLnNvdXJjZSwge1xuICAgICAgICAgIHN0YXJ0LFxuICAgICAgICAgIGVuZCxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGxvY1Bvc1NwYW4gPT09IEJST0tFTiA/IG51bGwgOiBsb2NQb3NTcGFuO1xuICB9XG5cbiAgc2VyaWFsaXplKCk6IFNlcmlhbGl6ZWRTb3VyY2VTcGFuIHtcbiAgICBsZXQge1xuICAgICAgc3RhcnQ6IHsgY2hhclBvczogc3RhcnQgfSxcbiAgICAgIGVuZDogeyBjaGFyUG9zOiBlbmQgfSxcbiAgICB9ID0gdGhpcy5jaGFyUG9zaXRpb25zO1xuXG4gICAgaWYgKHN0YXJ0ID09PSBlbmQpIHtcbiAgICAgIHJldHVybiBzdGFydDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFtzdGFydCwgZW5kXTtcbiAgICB9XG4gIH1cblxuICB0b0NoYXJQb3NTcGFuKCk6IENoYXJQb3NpdGlvblNwYW4ge1xuICAgIHJldHVybiB0aGlzO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBIYnNTcGFuIGltcGxlbWVudHMgU3BhbkRhdGEge1xuICByZWFkb25seSBraW5kID0gT2Zmc2V0S2luZC5IYnNQb3NpdGlvbjtcblxuICBfY2hhclBvc1NwYW46IENoYXJQb3NpdGlvblNwYW4gfCBCUk9LRU4gfCBudWxsID0gbnVsbDtcblxuICAvLyB0aGUgc291cmNlIGxvY2F0aW9uIGZyb20gSGFuZGxlYmFycyArIEFTVCBQbHVnaW5zIC0tIGNvdWxkIGJlIHdyb25nXG4gIF9wcm92aWRlZEhic0xvYzogU291cmNlTG9jYXRpb24gfCBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IHNvdXJjZTogU291cmNlLFxuICAgIHJlYWRvbmx5IGhic1Bvc2l0aW9uczogeyBzdGFydDogSGJzUG9zaXRpb247IGVuZDogSGJzUG9zaXRpb24gfSxcbiAgICBwcm92aWRlZEhic0xvYzogU291cmNlTG9jYXRpb24gfCBudWxsID0gbnVsbFxuICApIHtcbiAgICB0aGlzLl9wcm92aWRlZEhic0xvYyA9IHByb3ZpZGVkSGJzTG9jO1xuICB9XG5cbiAgc2VyaWFsaXplKCk6IFNlcmlhbGl6ZWRDb25jcmV0ZVNvdXJjZVNwYW4ge1xuICAgIGxldCBjaGFyUG9zID0gdGhpcy50b0NoYXJQb3NTcGFuKCk7XG4gICAgcmV0dXJuIGNoYXJQb3MgPT09IG51bGwgPyBPZmZzZXRLaW5kLkJyb2tlbiA6IGNoYXJQb3Mud3JhcCgpLnNlcmlhbGl6ZSgpO1xuICB9XG5cbiAgd3JhcCgpOiBTb3VyY2VTcGFuIHtcbiAgICByZXR1cm4gbmV3IFNvdXJjZVNwYW4odGhpcyk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVByb3ZpZGVkKHBvczogU291cmNlUG9zaXRpb24sIGVkZ2U6ICdzdGFydCcgfCAnZW5kJykge1xuICAgIGlmICh0aGlzLl9wcm92aWRlZEhic0xvYykge1xuICAgICAgdGhpcy5fcHJvdmlkZWRIYnNMb2NbZWRnZV0gPSBwb3M7XG4gICAgfVxuXG4gICAgLy8gaW52YWxpZGF0ZSBjb21wdXRlZCBjaGFyYWN0ZXIgb2Zmc2V0c1xuICAgIHRoaXMuX2NoYXJQb3NTcGFuID0gbnVsbDtcbiAgICB0aGlzLl9wcm92aWRlZEhic0xvYyA9IHtcbiAgICAgIHN0YXJ0OiBwb3MsXG4gICAgICBlbmQ6IHBvcyxcbiAgICB9O1xuICB9XG5cbiAgbG9jRGlkVXBkYXRlKHsgc3RhcnQsIGVuZCB9OiB7IHN0YXJ0PzogU291cmNlUG9zaXRpb247IGVuZD86IFNvdXJjZVBvc2l0aW9uIH0pOiB2b2lkIHtcbiAgICBpZiAoc3RhcnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy51cGRhdGVQcm92aWRlZChzdGFydCwgJ3N0YXJ0Jyk7XG4gICAgICB0aGlzLmhic1Bvc2l0aW9ucy5zdGFydCA9IG5ldyBIYnNQb3NpdGlvbih0aGlzLnNvdXJjZSwgc3RhcnQsIG51bGwpO1xuICAgIH1cblxuICAgIGlmIChlbmQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy51cGRhdGVQcm92aWRlZChlbmQsICdlbmQnKTtcbiAgICAgIHRoaXMuaGJzUG9zaXRpb25zLmVuZCA9IG5ldyBIYnNQb3NpdGlvbih0aGlzLnNvdXJjZSwgZW5kLCBudWxsKTtcbiAgICB9XG4gIH1cblxuICBhc1N0cmluZygpOiBzdHJpbmcge1xuICAgIGxldCBzcGFuID0gdGhpcy50b0NoYXJQb3NTcGFuKCk7XG4gICAgcmV0dXJuIHNwYW4gPT09IG51bGwgPyAnJyA6IHNwYW4uYXNTdHJpbmcoKTtcbiAgfVxuXG4gIGdldE1vZHVsZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNvdXJjZS5tb2R1bGU7XG4gIH1cblxuICBnZXRTdGFydCgpOiBBbnlQb3NpdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuaGJzUG9zaXRpb25zLnN0YXJ0O1xuICB9XG5cbiAgZ2V0RW5kKCk6IEFueVBvc2l0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5oYnNQb3NpdGlvbnMuZW5kO1xuICB9XG5cbiAgdG9IYnNMb2MoKTogU291cmNlTG9jYXRpb24ge1xuICAgIHJldHVybiB7XG4gICAgICBzdGFydDogdGhpcy5oYnNQb3NpdGlvbnMuc3RhcnQuaGJzUG9zLFxuICAgICAgZW5kOiB0aGlzLmhic1Bvc2l0aW9ucy5lbmQuaGJzUG9zLFxuICAgIH07XG4gIH1cblxuICB0b0hic1NwYW4oKTogSGJzU3BhbiB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICB0b0NoYXJQb3NTcGFuKCk6IENoYXJQb3NpdGlvblNwYW4gfCBudWxsIHtcbiAgICBsZXQgY2hhclBvc1NwYW4gPSB0aGlzLl9jaGFyUG9zU3BhbjtcblxuICAgIGlmIChjaGFyUG9zU3BhbiA9PT0gbnVsbCkge1xuICAgICAgbGV0IHN0YXJ0ID0gdGhpcy5oYnNQb3NpdGlvbnMuc3RhcnQudG9DaGFyUG9zKCk7XG4gICAgICBsZXQgZW5kID0gdGhpcy5oYnNQb3NpdGlvbnMuZW5kLnRvQ2hhclBvcygpO1xuXG4gICAgICBpZiAoc3RhcnQgJiYgZW5kKSB7XG4gICAgICAgIGNoYXJQb3NTcGFuID0gdGhpcy5fY2hhclBvc1NwYW4gPSBuZXcgQ2hhclBvc2l0aW9uU3Bhbih0aGlzLnNvdXJjZSwge1xuICAgICAgICAgIHN0YXJ0LFxuICAgICAgICAgIGVuZCxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGFyUG9zU3BhbiA9IHRoaXMuX2NoYXJQb3NTcGFuID0gQlJPS0VOO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY2hhclBvc1NwYW4gPT09IEJST0tFTiA/IG51bGwgOiBjaGFyUG9zU3BhbjtcbiAgfVxufVxuXG5jbGFzcyBJbnZpc2libGVTcGFuIGltcGxlbWVudHMgU3BhbkRhdGEge1xuICBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSBraW5kOiBPZmZzZXRLaW5kLkJyb2tlbiB8IE9mZnNldEtpbmQuSW50ZXJuYWxzU3ludGhldGljIHwgT2Zmc2V0S2luZC5Ob25FeGlzdGVudCxcbiAgICAvLyB3aGF0ZXZlciB3YXMgcHJvdmlkZWQsIHBvc3NpYmx5IGJyb2tlblxuICAgIHJlYWRvbmx5IGxvYzogU291cmNlTG9jYXRpb24sXG4gICAgLy8gaWYgdGhlIHNwYW4gcmVwcmVzZW50cyBhIHN5bnRoZXRpYyBzdHJpbmdcbiAgICByZWFkb25seSBzdHJpbmc6IHN0cmluZyB8IG51bGwgPSBudWxsXG4gICkge31cblxuICBzZXJpYWxpemUoKTogU2VyaWFsaXplZENvbmNyZXRlU291cmNlU3BhbiB7XG4gICAgc3dpdGNoICh0aGlzLmtpbmQpIHtcbiAgICAgIGNhc2UgT2Zmc2V0S2luZC5Ccm9rZW46XG4gICAgICBjYXNlIE9mZnNldEtpbmQuTm9uRXhpc3RlbnQ6XG4gICAgICAgIHJldHVybiB0aGlzLmtpbmQ7XG4gICAgICBjYXNlIE9mZnNldEtpbmQuSW50ZXJuYWxzU3ludGhldGljOlxuICAgICAgICByZXR1cm4gdGhpcy5zdHJpbmcgfHwgJyc7XG4gICAgfVxuICB9XG5cbiAgd3JhcCgpOiBTb3VyY2VTcGFuIHtcbiAgICByZXR1cm4gbmV3IFNvdXJjZVNwYW4odGhpcyk7XG4gIH1cblxuICBhc1N0cmluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnN0cmluZyB8fCAnJztcbiAgfVxuXG4gIGxvY0RpZFVwZGF0ZSh7IHN0YXJ0LCBlbmQgfTogeyBzdGFydD86IFNvdXJjZVBvc2l0aW9uOyBlbmQ/OiBTb3VyY2VQb3NpdGlvbiB9KSB7XG4gICAgaWYgKHN0YXJ0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubG9jLnN0YXJ0ID0gc3RhcnQ7XG4gICAgfVxuXG4gICAgaWYgKGVuZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmxvYy5lbmQgPSBlbmQ7XG4gICAgfVxuICB9XG5cbiAgZ2V0TW9kdWxlKCk6IHN0cmluZyB7XG4gICAgLy8gVE9ETzogTWFrZSB0aGlzIHJlZmxlY3QgdGhlIGFjdHVhbCBtb2R1bGUgdGhpcyBzcGFuIG9yaWdpbmF0ZWQgZnJvbVxuICAgIHJldHVybiAnYW4gdW5rbm93biBtb2R1bGUnO1xuICB9XG5cbiAgZ2V0U3RhcnQoKTogQW55UG9zaXRpb24ge1xuICAgIHJldHVybiBuZXcgSW52aXNpYmxlUG9zaXRpb24odGhpcy5raW5kLCB0aGlzLmxvYy5zdGFydCk7XG4gIH1cblxuICBnZXRFbmQoKTogQW55UG9zaXRpb24ge1xuICAgIHJldHVybiBuZXcgSW52aXNpYmxlUG9zaXRpb24odGhpcy5raW5kLCB0aGlzLmxvYy5lbmQpO1xuICB9XG5cbiAgdG9DaGFyUG9zU3BhbigpOiBJbnZpc2libGVTcGFuIHtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHRvSGJzU3BhbigpOiBudWxsIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHRvSGJzTG9jKCk6IFNvdXJjZUxvY2F0aW9uIHtcbiAgICByZXR1cm4gQlJPS0VOX0xPQ0FUSU9OO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBzcGFuOiBNYXRjaEZuPFNvdXJjZVNwYW4+ID0gbWF0Y2goKG0pID0+XG4gIG1cbiAgICAud2hlbihPZmZzZXRLaW5kLkhic1Bvc2l0aW9uLCBPZmZzZXRLaW5kLkhic1Bvc2l0aW9uLCAobGVmdCwgcmlnaHQpID0+XG4gICAgICBuZXcgSGJzU3BhbihsZWZ0LnNvdXJjZSwge1xuICAgICAgICBzdGFydDogbGVmdCxcbiAgICAgICAgZW5kOiByaWdodCxcbiAgICAgIH0pLndyYXAoKVxuICAgIClcbiAgICAud2hlbihPZmZzZXRLaW5kLkNoYXJQb3NpdGlvbiwgT2Zmc2V0S2luZC5DaGFyUG9zaXRpb24sIChsZWZ0LCByaWdodCkgPT5cbiAgICAgIG5ldyBDaGFyUG9zaXRpb25TcGFuKGxlZnQuc291cmNlLCB7XG4gICAgICAgIHN0YXJ0OiBsZWZ0LFxuICAgICAgICBlbmQ6IHJpZ2h0LFxuICAgICAgfSkud3JhcCgpXG4gICAgKVxuICAgIC53aGVuKE9mZnNldEtpbmQuQ2hhclBvc2l0aW9uLCBPZmZzZXRLaW5kLkhic1Bvc2l0aW9uLCAobGVmdCwgcmlnaHQpID0+IHtcbiAgICAgIGxldCByaWdodENoYXJQb3MgPSByaWdodC50b0NoYXJQb3MoKTtcblxuICAgICAgaWYgKHJpZ2h0Q2hhclBvcyA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbmV3IEludmlzaWJsZVNwYW4oT2Zmc2V0S2luZC5Ccm9rZW4sIEJST0tFTl9MT0NBVElPTikud3JhcCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHNwYW4obGVmdCwgcmlnaHRDaGFyUG9zKTtcbiAgICAgIH1cbiAgICB9KVxuICAgIC53aGVuKE9mZnNldEtpbmQuSGJzUG9zaXRpb24sIE9mZnNldEtpbmQuQ2hhclBvc2l0aW9uLCAobGVmdCwgcmlnaHQpID0+IHtcbiAgICAgIGxldCBsZWZ0Q2hhclBvcyA9IGxlZnQudG9DaGFyUG9zKCk7XG5cbiAgICAgIGlmIChsZWZ0Q2hhclBvcyA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbmV3IEludmlzaWJsZVNwYW4oT2Zmc2V0S2luZC5Ccm9rZW4sIEJST0tFTl9MT0NBVElPTikud3JhcCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHNwYW4obGVmdENoYXJQb3MsIHJpZ2h0KTtcbiAgICAgIH1cbiAgICB9KVxuICAgIC53aGVuKElzSW52aXNpYmxlLCBNYXRjaEFueSwgKGxlZnQpID0+IG5ldyBJbnZpc2libGVTcGFuKGxlZnQua2luZCwgQlJPS0VOX0xPQ0FUSU9OKS53cmFwKCkpXG4gICAgLndoZW4oTWF0Y2hBbnksIElzSW52aXNpYmxlLCAoXywgcmlnaHQpID0+XG4gICAgICBuZXcgSW52aXNpYmxlU3BhbihyaWdodC5raW5kLCBCUk9LRU5fTE9DQVRJT04pLndyYXAoKVxuICAgIClcbik7XG5cbmV4cG9ydCB0eXBlIFNlcmlhbGl6ZWRDb25jcmV0ZVNvdXJjZVNwYW4gPVxuICB8IC8qKiBjb2xsYXBzZWQgKi8gbnVtYmVyXG4gIHwgLyoqIG5vcm1hbCAqLyBbc3RhcnQ6IG51bWJlciwgc2l6ZTogbnVtYmVyXVxuICB8IC8qKiBzeW50aGV0aWMgKi8gc3RyaW5nO1xuXG5leHBvcnQgdHlwZSBTZXJpYWxpemVkU291cmNlU3BhbiA9XG4gIHwgU2VyaWFsaXplZENvbmNyZXRlU291cmNlU3BhblxuICB8IE9mZnNldEtpbmQuTm9uRXhpc3RlbnRcbiAgfCBPZmZzZXRLaW5kLkJyb2tlbjtcbiJdLCJzb3VyY2VSb290IjoiIn0=