UNPKG

@glimmer/syntax

Version:
362 lines (293 loc) 29.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InvisiblePosition = exports.HbsPosition = exports.CharPosition = exports.SourceOffset = exports.BROKEN = void 0; var _location = require("../location"); var _match = require("./match"); var _span = require("./span"); // eslint-disable-next-line import/no-extraneous-dependencies /** * Used to indicate that an attempt to convert a `SourcePosition` to a character offset failed. It * is separate from `null` so that `null` can be used to indicate that the computation wasn't yet * attempted (and therefore to cache the failure) */ const BROKEN = 'BROKEN'; /** * A `SourceOffset` represents a single position in the source. * * There are three kinds of backing data for `SourceOffset` objects: * * - `CharPosition`, which contains a character offset into the raw source string * - `HbsPosition`, which contains a `SourcePosition` from the Handlebars AST, which can be * converted to a `CharPosition` on demand. * - `InvisiblePosition`, which represents a position not in source (@see {InvisiblePosition}) */ exports.BROKEN = BROKEN; class SourceOffset { constructor(data) { this.data = data; } /** * Create a `SourceOffset` from a Handlebars `SourcePosition`. It's stored as-is, and converted * into a character offset on demand, which avoids unnecessarily computing the offset of every * `SourceLocation`, but also means that broken `SourcePosition`s are not always detected. */ static forHbsPos(source, pos) { return new HbsPosition(source, pos, null).wrap(); } /** * Create a `SourceOffset` that corresponds to a broken `SourcePosition`. This means that the * calling code determined (or knows) that the `SourceLocation` doesn't correspond correctly to * any part of the source. */ static broken(pos = _location.UNKNOWN_POSITION) { return new InvisiblePosition("Broken" /* Broken */ , pos).wrap(); } /** * Get the character offset for this `SourceOffset`, if possible. */ get offset() { let charPos = this.data.toCharPos(); return charPos === null ? null : charPos.offset; } /** * Compare this offset with another one. * * If both offsets are `HbsPosition`s, they're equivalent as long as their lines and columns are * the same. This avoids computing offsets unnecessarily. * * Otherwise, two `SourceOffset`s are equivalent if their successfully computed character offsets * are the same. */ eql(right) { return eql(this.data, right.data); } /** * Create a span that starts from this source offset and ends with another source offset. Avoid * computing character offsets if both `SourceOffset`s are still lazy. */ until(other) { return (0, _span.span)(this.data, other.data); } /** * Create a `SourceOffset` by moving the character position represented by this source offset * forward or backward (if `by` is negative), if possible. * * If this `SourceOffset` can't compute a valid character offset, `move` returns a broken offset. * * If the resulting character offset is less than 0 or greater than the size of the source, `move` * returns a broken offset. */ move(by) { let charPos = this.data.toCharPos(); if (charPos === null) { return SourceOffset.broken(); } else { let result = charPos.offset + by; if (charPos.source.check(result)) { return new CharPosition(charPos.source, result).wrap(); } else { return SourceOffset.broken(); } } } /** * Create a new `SourceSpan` that represents a collapsed range at this source offset. Avoid * computing the character offset if it has not already been computed. */ collapsed() { return (0, _span.span)(this.data, this.data); } /** * Convert this `SourceOffset` into a Handlebars {@see SourcePosition} for compatibility with * existing plugins. */ toJSON() { return this.data.toJSON(); } } exports.SourceOffset = SourceOffset; class CharPosition { constructor(source, charPos) { this.source = source; this.charPos = charPos; this.kind = "CharPosition" /* CharPosition */ ; /** Computed from char offset */ this._locPos = null; } /** * This is already a `CharPosition`. * * {@see HbsPosition} for the alternative. * * @implements {PositionData} */ toCharPos() { return this; } /** * Produce a Handlebars {@see SourcePosition} for this `CharPosition`. If this `CharPosition` was * computed using {@see SourceOffset#move}, this will compute the `SourcePosition` for the offset. * * @implements {PositionData} */ toJSON() { let hbs = this.toHbsPos(); return hbs === null ? _location.UNKNOWN_POSITION : hbs.toJSON(); } wrap() { return new SourceOffset(this); } /** * A `CharPosition` always has an offset it can produce without any additional computation. */ get offset() { return this.charPos; } /** * Convert the current character offset to an `HbsPosition`, if it was not already computed. Once * a `CharPosition` has computed its `HbsPosition`, it will not need to do compute it again, and * the same `CharPosition` is retained when used as one of the ends of a `SourceSpan`, so * computing the `HbsPosition` should be a one-time operation. */ toHbsPos() { let locPos = this._locPos; if (locPos === null) { let hbsPos = this.source.hbsPosFor(this.charPos); if (hbsPos === null) { this._locPos = locPos = BROKEN; } else { this._locPos = locPos = new HbsPosition(this.source, hbsPos, this.charPos); } } return locPos === BROKEN ? null : locPos; } } exports.CharPosition = CharPosition; class HbsPosition { constructor(source, hbsPos, charPos = null) { this.source = source; this.hbsPos = hbsPos; this.kind = "HbsPosition" /* HbsPosition */ ; this._charPos = charPos === null ? null : new CharPosition(source, charPos); } /** * Lazily compute the character offset from the {@see SourcePosition}. Once an `HbsPosition` has * computed its `CharPosition`, it will not need to do compute it again, and the same * `HbsPosition` is retained when used as one of the ends of a `SourceSpan`, so computing the * `CharPosition` should be a one-time operation. * * @implements {PositionData} */ toCharPos() { let charPos = this._charPos; if (charPos === null) { let charPosNumber = this.source.charPosFor(this.hbsPos); if (charPosNumber === null) { this._charPos = charPos = BROKEN; } else { this._charPos = charPos = new CharPosition(this.source, charPosNumber); } } return charPos === BROKEN ? null : charPos; } /** * Return the {@see SourcePosition} that this `HbsPosition` was instantiated with. This operation * does not need to compute anything. * * @implements {PositionData} */ toJSON() { return this.hbsPos; } wrap() { return new SourceOffset(this); } /** * This is already an `HbsPosition`. * * {@see CharPosition} for the alternative. */ toHbsPos() { return this; } } exports.HbsPosition = HbsPosition; class InvisiblePosition { constructor(kind, // whatever was provided, possibly broken pos) { this.kind = kind; this.pos = pos; } /** * A broken position cannot be turned into a {@see CharacterPosition}. */ toCharPos() { return null; } /** * The serialization of an `InvisiblePosition is whatever Handlebars {@see SourcePosition} was * originally identified as broken, non-existent or synthetic. * * If an `InvisiblePosition` never had an source offset at all, this method returns * {@see UNKNOWN_POSITION} for compatibility. */ toJSON() { return this.pos; } wrap() { return new SourceOffset(this); } get offset() { return null; } } /** * Compare two {@see AnyPosition} and determine whether they are equal. * * @see {SourceOffset#eql} */ exports.InvisiblePosition = InvisiblePosition; const eql = (0, _match.match)(m => m.when("HbsPosition" /* HbsPosition */ , "HbsPosition" /* HbsPosition */ , ({ hbsPos: left }, { hbsPos: right }) => left.column === right.column && left.line === right.line).when("CharPosition" /* CharPosition */ , "CharPosition" /* CharPosition */ , ({ charPos: left }, { charPos: right }) => left === right).when("CharPosition" /* CharPosition */ , "HbsPosition" /* HbsPosition */ , ({ offset: left }, right) => { var _a; return left === ((_a = right.toCharPos()) === null || _a === void 0 ? void 0 : _a.offset); }).when("HbsPosition" /* HbsPosition */ , "CharPosition" /* CharPosition */ , (left, { offset: right }) => { var _a; return ((_a = left.toCharPos()) === null || _a === void 0 ? void 0 : _a.offset) === right; }).when(_match.MatchAny, _match.MatchAny, () => false)); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3N5bnRheC9saWIvc291cmNlL2xvYy9vZmZzZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUNBOztBQUVBOztBQUNBOztBQUpBOztBQWdEQTs7Ozs7QUFLTyxNQUFNLE1BQU0sR0FBWixRQUFBO0FBS1A7Ozs7Ozs7Ozs7Ozs7QUFVTSxNQUFBLFlBQUEsQ0FBbUI7QUFtQnZCLEVBQUEsV0FBQSxDQUFBLElBQUEsRUFBcUQ7QUFBaEMsU0FBQSxJQUFBLEdBQUEsSUFBQTtBQUFvQztBQWxCekQ7Ozs7Ozs7QUFLQSxTQUFBLFNBQUEsQ0FBQSxNQUFBLEVBQUEsR0FBQSxFQUFvRDtBQUNsRCxXQUFPLElBQUEsV0FBQSxDQUFBLE1BQUEsRUFBQSxHQUFBLEVBQUEsSUFBQSxFQUFQLElBQU8sRUFBUDtBQUNEO0FBRUQ7Ozs7Ozs7QUFLQSxTQUFBLE1BQUEsQ0FBYyxHQUFBLEdBQWQsMEJBQUEsRUFBb0Q7QUFDbEQsV0FBTyxJQUFBLGlCQUFBLENBQXFCO0FBQUE7QUFBckIsTUFBQSxHQUFBLEVBQVAsSUFBTyxFQUFQO0FBQ0Q7QUFJRDs7Ozs7QUFHQSxNQUFBLE1BQUEsR0FBVTtBQUNSLFFBQUksT0FBTyxHQUFHLEtBQUEsSUFBQSxDQUFkLFNBQWMsRUFBZDtBQUNBLFdBQU8sT0FBTyxLQUFQLElBQUEsR0FBQSxJQUFBLEdBQTBCLE9BQU8sQ0FBeEMsTUFBQTtBQUNEO0FBRUQ7Ozs7Ozs7Ozs7O0FBU0EsRUFBQSxHQUFHLENBQUEsS0FBQSxFQUFvQjtBQUNyQixXQUFPLEdBQUcsQ0FBQyxLQUFELElBQUEsRUFBWSxLQUFLLENBQTNCLElBQVUsQ0FBVjtBQUNEO0FBRUQ7Ozs7OztBQUlBLEVBQUEsS0FBSyxDQUFBLEtBQUEsRUFBb0I7QUFDdkIsV0FBTyxnQkFBSyxLQUFELElBQUosRUFBZ0IsS0FBSyxDQUE1QixJQUFPLENBQVA7QUFDRDtBQUVEOzs7Ozs7Ozs7OztBQVNBLEVB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Q29udGVudCI6WyIvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBTb3VyY2VQb3NpdGlvbiwgVU5LTk9XTl9QT1NJVElPTiB9IGZyb20gJy4uL2xvY2F0aW9uJztcbmltcG9ydCB7IFNvdXJjZSB9IGZyb20gJy4uL3NvdXJjZSc7XG5pbXBvcnQgeyBtYXRjaCwgTWF0Y2hBbnkgfSBmcm9tICcuL21hdGNoJztcbmltcG9ydCB7IFNvdXJjZVNwYW4sIHNwYW4gfSBmcm9tICcuL3NwYW4nO1xuXG5leHBvcnQgY29uc3QgZW51bSBPZmZzZXRLaW5kIHtcbiAgLyoqXG4gICAqIFdlIGhhdmUgYWxyZWFkeSBjb21wdXRlZCB0aGUgY2hhcmFjdGVyIHBvc2l0aW9uIG9mIHRoaXMgb2Zmc2V0IG9yIHNwYW4uXG4gICAqL1xuICBDaGFyUG9zaXRpb24gPSAnQ2hhclBvc2l0aW9uJyxcblxuICAvKipcbiAgICogVGhpcyBvZmZzZXQgb3Igc3BhbiB3YXMgaW5zdGFudGlhdGVkIHdpdGggYSBIYW5kbGViYXJzIFNvdXJjZVBvc2l0aW9uIG9yIFNvdXJjZUxvY2F0aW9uLiBJdHNcbiAgICogY2hhcmFjdGVyIHBvc2l0aW9uIHdpbGwgYmUgY29tcHV0ZWQgb24gZGVtYW5kLlxuICAgKi9cbiAgSGJzUG9zaXRpb24gPSAnSGJzUG9zaXRpb24nLFxuXG4gIC8qKlxuICAgKiBmb3IgKHJhcmUpIHNpdHVhdGlvbnMgd2hlcmUgYSBub2RlIGlzIGNyZWF0ZWQgYnV0IHRoZXJlIHdhcyBubyBzb3VyY2UgbG9jYXRpb24gKGUuZy4gdGhlIG5hbWVcbiAgICogXCJkZWZhdWx0XCIgaW4gZGVmYXVsdCBibG9ja3Mgd2hlbiB0aGUgd29yZCBcImRlZmF1bHRcIiBuZXZlciBhcHBlYXJlZCBpbiBzb3VyY2UpLiBUaGlzIGlzIHVzZWRcbiAgICogYnkgdGhlIGludGVybmFscyB3aGVuIHRoZXJlIGlzIGEgbGVnaXRpbWF0ZSByZWFzb24gZm9yIHRoZSBpbnRlcm5hbHMgdG8gc3ludGhlc2l6ZSBhIG5vZGVcbiAgICogd2l0aCBubyBsb2NhdGlvbi5cbiAgICovXG4gIEludGVybmFsc1N5bnRoZXRpYyA9ICdJbnRlcm5hbHNTeW50aGV0aWMnLFxuICAvKipcbiAgICogRm9yIHNpdHVhdGlvbnMgd2hlcmUgYSBub2RlIHJlcHJlc2VudHMgemVybyBwYXJ0cyBvZiB0aGUgc291cmNlIChmb3IgZXhhbXBsZSwgZW1wdHkgYXJndW1lbnRzKS5cbiAgICogSW4gZ2VuZXJhbCwgd2UgYXR0ZW1wdCB0byBhc3NpZ24gdGhlc2Ugbm9kZXMgKnNvbWUqIHBvc2l0aW9uIChlbXB0eSBhcmd1bWVudHMgY2FuIGJlXG4gICAqIHBvc2l0aW9uZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhlIGNhbGxlZSksIGJ1dCBpdCdzIG5vdCBhbHdheXMgcG9zc2libGVcbiAgICovXG4gIE5vbkV4aXN0ZW50ID0gJ05vbkV4aXN0ZW50JyxcbiAgLyoqXG4gICAqIEZvciBzaXR1YXRpb25zIHdoZXJlIGEgc291cmNlIGxvY2F0aW9uIHdhcyBleHBlY3RlZCwgYnV0IGl0IGRpZG4ndCBjb3JyZXNwb25kIHRvIHRoZSBub2RlIGluXG4gICAqIHRoZSBzb3VyY2UuIFRoaXMgaGFwcGVucyBpZiBhIHBsdWdpbiBjcmVhdGVzIGJyb2tlbiBsb2NhdGlvbnMuXG4gICAqL1xuICBCcm9rZW4gPSAnQnJva2VuJyxcbn1cblxuLyoqXG4gKiBBbGwgcG9zaXRpb25zIGhhdmUgdGhlc2UgZGV0YWlscyBpbiBjb21tb24uIE1vc3Qgbm90YWJseSwgYWxsIHRocmVlIGtpbmRzIG9mIHBvc2l0aW9ucyBjYW5cbiAqIG11c3QgYmUgYWJsZSB0byBhdHRlbXB0IHRvIGNvbnZlcnQgdGhlbXNlbHZlcyBpbnRvIHtAc2VlIENoYXJQb3NpdGlvbn0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9zaXRpb25EYXRhIHtcbiAgcmVhZG9ubHkga2luZDogT2Zmc2V0S2luZDtcbiAgdG9DaGFyUG9zKCk6IENoYXJQb3NpdGlvbiB8IG51bGw7XG4gIHRvSlNPTigpOiBTb3VyY2VQb3NpdGlvbjtcbn1cblxuLyoqXG4gKiBVc2VkIHRvIGluZGljYXRlIHRoYXQgYW4gYXR0ZW1wdCB0byBjb252ZXJ0IGEgYFNvdXJjZVBvc2l0aW9uYCB0byBhIGNoYXJhY3RlciBvZmZzZXQgZmFpbGVkLiBJdFxuICogaXMgc2VwYXJhdGUgZnJvbSBgbnVsbGAgc28gdGhhdCBgbnVsbGAgY2FuIGJlIHVzZWQgdG8gaW5kaWNhdGUgdGhhdCB0aGUgY29tcHV0YXRpb24gd2Fzbid0IHlldFxuICogYXR0ZW1wdGVkIChhbmQgdGhlcmVmb3JlIHRvIGNhY2hlIHRoZSBmYWlsdXJlKVxuICovXG5leHBvcnQgY29uc3QgQlJPS0VOID0gJ0JST0tFTic7XG5leHBvcnQgdHlwZSBCUk9LRU4gPSAnQlJPS0VOJztcblxuZXhwb3J0IHR5cGUgQW55UG9zaXRpb24gPSBIYnNQb3NpdGlvbiB8IENoYXJQb3NpdGlvbiB8IEludmlzaWJsZVBvc2l0aW9uO1xuXG4vKipcbiAqIEEgYFNvdXJjZU9mZnNldGAgcmVwcmVzZW50cyBhIHNpbmdsZSBwb3NpdGlvbiBpbiB0aGUgc291cmNlLlxuICpcbiAqIFRoZXJlIGFyZSB0aHJlZSBraW5kcyBvZiBiYWNraW5nIGRhdGEgZm9yIGBTb3VyY2VPZmZzZXRgIG9iamVjdHM6XG4gKlxuICogLSBgQ2hhclBvc2l0aW9uYCwgd2hpY2ggY29udGFpbnMgYSBjaGFyYWN0ZXIgb2Zmc2V0IGludG8gdGhlIHJhdyBzb3VyY2Ugc3RyaW5nXG4gKiAtIGBIYnNQb3NpdGlvbmAsIHdoaWNoIGNvbnRhaW5zIGEgYFNvdXJjZVBvc2l0aW9uYCBmcm9tIHRoZSBIYW5kbGViYXJzIEFTVCwgd2hpY2ggY2FuIGJlXG4gKiAgIGNvbnZlcnRlZCB0byBhIGBDaGFyUG9zaXRpb25gIG9uIGRlbWFuZC5cbiAqIC0gYEludmlzaWJsZVBvc2l0aW9uYCwgd2hpY2ggcmVwcmVzZW50cyBhIHBvc2l0aW9uIG5vdCBpbiBzb3VyY2UgKEBzZWUge0ludmlzaWJsZVBvc2l0aW9ufSlcbiAqL1xuZXhwb3J0IGNsYXNzIFNvdXJjZU9mZnNldCB7XG4gIC8qKlxuICAgKiBDcmVhdGUgYSBgU291cmNlT2Zmc2V0YCBmcm9tIGEgSGFuZGxlYmFycyBgU291cmNlUG9zaXRpb25gLiBJdCdzIHN0b3JlZCBhcy1pcywgYW5kIGNvbnZlcnRlZFxuICAgKiBpbnRvIGEgY2hhcmFjdGVyIG9mZnNldCBvbiBkZW1hbmQsIHdoaWNoIGF2b2lkcyB1bm5lY2Vzc2FyaWx5IGNvbXB1dGluZyB0aGUgb2Zmc2V0IG9mIGV2ZXJ5XG4gICAqIGBTb3VyY2VMb2NhdGlvbmAsIGJ1dCBhbHNvIG1lYW5zIHRoYXQgYnJva2VuIGBTb3VyY2VQb3NpdGlvbmBzIGFyZSBub3QgYWx3YXlzIGRldGVjdGVkLlxuICAgKi9cbiAgc3RhdGljIGZvckhic1Bvcyhzb3VyY2U6IFNvdXJjZSwgcG9zOiBTb3VyY2VQb3NpdGlvbik6IFNvdXJjZU9mZnNldCB7XG4gICAgcmV0dXJuIG5ldyBIYnNQb3NpdGlvbihzb3VyY2UsIHBvcywgbnVsbCkud3JhcCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIGBTb3VyY2VPZmZzZXRgIHRoYXQgY29ycmVzcG9uZHMgdG8gYSBicm9rZW4gYFNvdXJjZVBvc2l0aW9uYC4gVGhpcyBtZWFucyB0aGF0IHRoZVxuICAgKiBjYWxsaW5nIGNvZGUgZGV0ZXJtaW5lZCAob3Iga25vd3MpIHRoYXQgdGhlIGBTb3VyY2VMb2NhdGlvbmAgZG9lc24ndCBjb3JyZXNwb25kIGNvcnJlY3RseSB0b1xuICAgKiBhbnkgcGFydCBvZiB0aGUgc291cmNlLlxuICAgKi9cbiAgc3RhdGljIGJyb2tlbihwb3M6IFNvdXJjZVBvc2l0aW9uID0gVU5LTk9XTl9QT1NJVElPTik6IFNvdXJjZU9mZnNldCB7XG4gICAgcmV0dXJuIG5ldyBJbnZpc2libGVQb3NpdGlvbihPZmZzZXRLaW5kLkJyb2tlbiwgcG9zKS53cmFwKCk7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihyZWFkb25seSBkYXRhOiBQb3NpdGlvbkRhdGEgJiBBbnlQb3NpdGlvbikge31cblxuICAvKipcbiAgICogR2V0IHRoZSBjaGFyYWN0ZXIgb2Zmc2V0IGZvciB0aGlzIGBTb3VyY2VPZmZzZXRgLCBpZiBwb3NzaWJsZS5cbiAgICovXG4gIGdldCBvZmZzZXQoKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgbGV0IGNoYXJQb3MgPSB0aGlzLmRhdGEudG9DaGFyUG9zKCk7XG4gICAgcmV0dXJuIGNoYXJQb3MgPT09IG51bGwgPyBudWxsIDogY2hhclBvcy5vZmZzZXQ7XG4gIH1cblxuICAvKipcbiAgICogQ29tcGFyZSB0aGlzIG9mZnNldCB3aXRoIGFub3RoZXIgb25lLlxuICAgKlxuICAgKiBJZiBib3RoIG9mZnNldHMgYXJlIGBIYnNQb3NpdGlvbmBzLCB0aGV5J3JlIGVxdWl2YWxlbnQgYXMgbG9uZyBhcyB0aGVpciBsaW5lcyBhbmQgY29sdW1ucyBhcmVcbiAgICogdGhlIHNhbWUuIFRoaXMgYXZvaWRzIGNvbXB1dGluZyBvZmZzZXRzIHVubmVjZXNzYXJpbHkuXG4gICAqXG4gICAqIE90aGVyd2lzZSwgdHdvIGBTb3VyY2VPZmZzZXRgcyBhcmUgZXF1aXZhbGVudCBpZiB0aGVpciBzdWNjZXNzZnVsbHkgY29tcHV0ZWQgY2hhcmFjdGVyIG9mZnNldHNcbiAgICogYXJlIHRoZSBzYW1lLlxuICAgKi9cbiAgZXFsKHJpZ2h0OiBTb3VyY2VPZmZzZXQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZXFsKHRoaXMuZGF0YSwgcmlnaHQuZGF0YSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgc3BhbiB0aGF0IHN0YXJ0cyBmcm9tIHRoaXMgc291cmNlIG9mZnNldCBhbmQgZW5kcyB3aXRoIGFub3RoZXIgc291cmNlIG9mZnNldC4gQXZvaWRcbiAgICogY29tcHV0aW5nIGNoYXJhY3RlciBvZmZzZXRzIGlmIGJvdGggYFNvdXJjZU9mZnNldGBzIGFyZSBzdGlsbCBsYXp5LlxuICAgKi9cbiAgdW50aWwob3RoZXI6IFNvdXJjZU9mZnNldCk6IFNvdXJjZVNwYW4ge1xuICAgIHJldHVybiBzcGFuKHRoaXMuZGF0YSwgb3RoZXIuZGF0YSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgYFNvdXJjZU9mZnNldGAgYnkgbW92aW5nIHRoZSBjaGFyYWN0ZXIgcG9zaXRpb24gcmVwcmVzZW50ZWQgYnkgdGhpcyBzb3VyY2Ugb2Zmc2V0XG4gICAqIGZvcndhcmQgb3IgYmFja3dhcmQgKGlmIGBieWAgaXMgbmVnYXRpdmUpLCBpZiBwb3NzaWJsZS5cbiAgICpcbiAgICogSWYgdGhpcyBgU291cmNlT2Zmc2V0YCBjYW4ndCBjb21wdXRlIGEgdmFsaWQgY2hhcmFjdGVyIG9mZnNldCwgYG1vdmVgIHJldHVybnMgYSBicm9rZW4gb2Zmc2V0LlxuICAgKlxuICAgKiBJZiB0aGUgcmVzdWx0aW5nIGNoYXJhY3RlciBvZmZzZXQgaXMgbGVzcyB0aGFuIDAgb3IgZ3JlYXRlciB0aGFuIHRoZSBzaXplIG9mIHRoZSBzb3VyY2UsIGBtb3ZlYFxuICAgKiByZXR1cm5zIGEgYnJva2VuIG9mZnNldC5cbiAgICovXG4gIG1vdmUoYnk6IG51bWJlcik6IFNvdXJjZU9mZnNldCB7XG4gICAgbGV0IGNoYXJQb3MgPSB0aGlzLmRhdGEudG9DaGFyUG9zKCk7XG5cbiAgICBpZiAoY2hhclBvcyA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIFNvdXJjZU9mZnNldC5icm9rZW4oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHJlc3VsdCA9IGNoYXJQb3Mub2Zmc2V0ICsgYnk7XG5cbiAgICAgIGlmIChjaGFyUG9zLnNvdXJjZS5jaGVjayhyZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ2hhclBvc2l0aW9uKGNoYXJQb3Muc291cmNlLCByZXN1bHQpLndyYXAoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBTb3VyY2VPZmZzZXQuYnJva2VuKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBgU291cmNlU3BhbmAgdGhhdCByZXByZXNlbnRzIGEgY29sbGFwc2VkIHJhbmdlIGF0IHRoaXMgc291cmNlIG9mZnNldC4gQXZvaWRcbiAgICogY29tcHV0aW5nIHRoZSBjaGFyYWN0ZXIgb2Zmc2V0IGlmIGl0IGhhcyBub3QgYWxyZWFkeSBiZWVuIGNvbXB1dGVkLlxuICAgKi9cbiAgY29sbGFwc2VkKCk6IFNvdXJjZVNwYW4ge1xuICAgIHJldHVybiBzcGFuKHRoaXMuZGF0YSwgdGhpcy5kYXRhKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IHRoaXMgYFNvdXJjZU9mZnNldGAgaW50byBhIEhhbmRsZWJhcnMge0BzZWUgU291cmNlUG9zaXRpb259IGZvciBjb21wYXRpYmlsaXR5IHdpdGhcbiAgICogZXhpc3RpbmcgcGx1Z2lucy5cbiAgICovXG4gIHRvSlNPTigpOiBTb3VyY2VQb3NpdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YS50b0pTT04oKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQ2hhclBvc2l0aW9uIGltcGxlbWVudHMgUG9zaXRpb25EYXRhIHtcbiAgcmVhZG9ubHkga2luZCA9IE9mZnNldEtpbmQuQ2hhclBvc2l0aW9uO1xuXG4gIC8qKiBDb21wdXRlZCBmcm9tIGNoYXIgb2Zmc2V0ICovXG4gIF9sb2NQb3M6IEhic1Bvc2l0aW9uIHwgQlJPS0VOIHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IocmVhZG9ubHkgc291cmNlOiBTb3VyY2UsIHJlYWRvbmx5IGNoYXJQb3M6IG51bWJlcikge31cblxuICAvKipcbiAgICogVGhpcyBpcyBhbHJlYWR5IGEgYENoYXJQb3NpdGlvbmAuXG4gICAqXG4gICAqIHtAc2VlIEhic1Bvc2l0aW9ufSBmb3IgdGhlIGFsdGVybmF0aXZlLlxuICAgKlxuICAgKiBAaW1wbGVtZW50cyB7UG9zaXRpb25EYXRhfVxuICAgKi9cbiAgdG9DaGFyUG9zKCk6IENoYXJQb3NpdGlvbiB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogUHJvZHVjZSBhIEhhbmRsZWJhcnMge0BzZWUgU291cmNlUG9zaXRpb259IGZvciB0aGlzIGBDaGFyUG9zaXRpb25gLiBJZiB0aGlzIGBDaGFyUG9zaXRpb25gIHdhc1xuICAgKiBjb21wdXRlZCB1c2luZyB7QHNlZSBTb3VyY2VPZmZzZXQjbW92ZX0sIHRoaXMgd2lsbCBjb21wdXRlIHRoZSBgU291cmNlUG9zaXRpb25gIGZvciB0aGUgb2Zmc2V0LlxuICAgKlxuICAgKiBAaW1wbGVtZW50cyB7UG9zaXRpb25EYXRhfVxuICAgKi9cbiAgdG9KU09OKCk6IFNvdXJjZVBvc2l0aW9uIHtcbiAgICBsZXQgaGJzID0gdGhpcy50b0hic1BvcygpO1xuICAgIHJldHVybiBoYnMgPT09IG51bGwgPyBVTktOT1dOX1BPU0lUSU9OIDogaGJzLnRvSlNPTigpO1xuICB9XG5cbiAgd3JhcCgpOiBTb3VyY2VPZmZzZXQge1xuICAgIHJldHVybiBuZXcgU291cmNlT2Zmc2V0KHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgYENoYXJQb3NpdGlvbmAgYWx3YXlzIGhhcyBhbiBvZmZzZXQgaXQgY2FuIHByb2R1Y2Ugd2l0aG91dCBhbnkgYWRkaXRpb25hbCBjb21wdXRhdGlvbi5cbiAgICovXG4gIGdldCBvZmZzZXQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5jaGFyUG9zO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgdGhlIGN1cnJlbnQgY2hhcmFjdGVyIG9mZnNldCB0byBhbiBgSGJzUG9zaXRpb25gLCBpZiBpdCB3YXMgbm90IGFscmVhZHkgY29tcHV0ZWQuIE9uY2VcbiAgICogYSBgQ2hhclBvc2l0aW9uYCBoYXMgY29tcHV0ZWQgaXRzIGBIYnNQb3NpdGlvbmAsIGl0IHdpbGwgbm90IG5lZWQgdG8gZG8gY29tcHV0ZSBpdCBhZ2FpbiwgYW5kXG4gICAqIHRoZSBzYW1lIGBDaGFyUG9zaXRpb25gIGlzIHJldGFpbmVkIHdoZW4gdXNlZCBhcyBvbmUgb2YgdGhlIGVuZHMgb2YgYSBgU291cmNlU3BhbmAsIHNvXG4gICAqIGNvbXB1dGluZyB0aGUgYEhic1Bvc2l0aW9uYCBzaG91bGQgYmUgYSBvbmUtdGltZSBvcGVyYXRpb24uXG4gICAqL1xuICB0b0hic1BvcygpOiBIYnNQb3NpdGlvbiB8IG51bGwge1xuICAgIGxldCBsb2NQb3MgPSB0aGlzLl9sb2NQb3M7XG5cbiAgICBpZiAobG9jUG9zID09PSBudWxsKSB7XG4gICAgICBsZXQgaGJzUG9zID0gdGhpcy5zb3VyY2UuaGJzUG9zRm9yKHRoaXMuY2hhclBvcyk7XG5cbiAgICAgIGlmIChoYnNQb3MgPT09IG51bGwpIHtcbiAgICAgICAgdGhpcy5fbG9jUG9zID0gbG9jUG9zID0gQlJPS0VOO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fbG9jUG9zID0gbG9jUG9zID0gbmV3IEhic1Bvc2l0aW9uKHRoaXMuc291cmNlLCBoYnNQb3MsIHRoaXMuY2hhclBvcyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGxvY1BvcyA9PT0gQlJPS0VOID8gbnVsbCA6IGxvY1BvcztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgSGJzUG9zaXRpb24gaW1wbGVtZW50cyBQb3NpdGlvbkRhdGEge1xuICByZWFkb25seSBraW5kID0gT2Zmc2V0S2luZC5IYnNQb3NpdGlvbjtcblxuICBfY2hhclBvczogQ2hhclBvc2l0aW9uIHwgQlJPS0VOIHwgbnVsbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSBzb3VyY2U6IFNvdXJjZSxcbiAgICByZWFkb25seSBoYnNQb3M6IFNvdXJjZVBvc2l0aW9uLFxuICAgIGNoYXJQb3M6IG51bWJlciB8IG51bGwgPSBudWxsXG4gICkge1xuICAgIHRoaXMuX2NoYXJQb3MgPSBjaGFyUG9zID09PSBudWxsID8gbnVsbCA6IG5ldyBDaGFyUG9zaXRpb24oc291cmNlLCBjaGFyUG9zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMYXppbHkgY29tcHV0ZSB0aGUgY2hhcmFjdGVyIG9mZnNldCBmcm9tIHRoZSB7QHNlZSBTb3VyY2VQb3NpdGlvbn0uIE9uY2UgYW4gYEhic1Bvc2l0aW9uYCBoYXNcbiAgICogY29tcHV0ZWQgaXRzIGBDaGFyUG9zaXRpb25gLCBpdCB3aWxsIG5vdCBuZWVkIHRvIGRvIGNvbXB1dGUgaXQgYWdhaW4sIGFuZCB0aGUgc2FtZVxuICAgKiBgSGJzUG9zaXRpb25gIGlzIHJldGFpbmVkIHdoZW4gdXNlZCBhcyBvbmUgb2YgdGhlIGVuZHMgb2YgYSBgU291cmNlU3BhbmAsIHNvIGNvbXB1dGluZyB0aGVcbiAgICogYENoYXJQb3NpdGlvbmAgc2hvdWxkIGJlIGEgb25lLXRpbWUgb3BlcmF0aW9uLlxuICAgKlxuICAgKiBAaW1wbGVtZW50cyB7UG9zaXRpb25EYXRhfVxuICAgKi9cbiAgdG9DaGFyUG9zKCk6IENoYXJQb3NpdGlvbiB8IG51bGwge1xuICAgIGxldCBjaGFyUG9zID0gdGhpcy5fY2hhclBvcztcblxuICAgIGlmIChjaGFyUG9zID09PSBudWxsKSB7XG4gICAgICBsZXQgY2hhclBvc051bWJlciA9IHRoaXMuc291cmNlLmNoYXJQb3NGb3IodGhpcy5oYnNQb3MpO1xuXG4gICAgICBpZiAoY2hhclBvc051bWJlciA9PT0gbnVsbCkge1xuICAgICAgICB0aGlzLl9jaGFyUG9zID0gY2hhclBvcyA9IEJST0tFTjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2NoYXJQb3MgPSBjaGFyUG9zID0gbmV3IENoYXJQb3NpdGlvbih0aGlzLnNvdXJjZSwgY2hhclBvc051bWJlcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNoYXJQb3MgPT09IEJST0tFTiA/IG51bGwgOiBjaGFyUG9zO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUge0BzZWUgU291cmNlUG9zaXRpb259IHRoYXQgdGhpcyBgSGJzUG9zaXRpb25gIHdhcyBpbnN0YW50aWF0ZWQgd2l0aC4gVGhpcyBvcGVyYXRpb25cbiAgICogZG9lcyBub3QgbmVlZCB0byBjb21wdXRlIGFueXRoaW5nLlxuICAgKlxuICAgKiBAaW1wbGVtZW50cyB7UG9zaXRpb25EYXRhfVxuICAgKi9cbiAgdG9KU09OKCk6IFNvdXJjZVBvc2l0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5oYnNQb3M7XG4gIH1cblxuICB3cmFwKCk6IFNvdXJjZU9mZnNldCB7XG4gICAgcmV0dXJuIG5ldyBTb3VyY2VPZmZzZXQodGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBpcyBhbHJlYWR5IGFuIGBIYnNQb3NpdGlvbmAuXG4gICAqXG4gICAqIHtAc2VlIENoYXJQb3NpdGlvbn0gZm9yIHRoZSBhbHRlcm5hdGl2ZS5cbiAgICovXG4gIHRvSGJzUG9zKCk6IEhic1Bvc2l0aW9uIHtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgSW52aXNpYmxlUG9zaXRpb24gaW1wbGVtZW50cyBQb3NpdGlvbkRhdGEge1xuICBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSBraW5kOiBPZmZzZXRLaW5kLkJyb2tlbiB8IE9mZnNldEtpbmQuSW50ZXJuYWxzU3ludGhldGljIHwgT2Zmc2V0S2luZC5Ob25FeGlzdGVudCxcbiAgICAvLyB3aGF0ZXZlciB3YXMgcHJvdmlkZWQsIHBvc3NpYmx5IGJyb2tlblxuICAgIHJlYWRvbmx5IHBvczogU291cmNlUG9zaXRpb25cbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBBIGJyb2tlbiBwb3NpdGlvbiBjYW5ub3QgYmUgdHVybmVkIGludG8gYSB7QHNlZSBDaGFyYWN0ZXJQb3NpdGlvbn0uXG4gICAqL1xuICB0b0NoYXJQb3MoKTogbnVsbCB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHNlcmlhbGl6YXRpb24gb2YgYW4gYEludmlzaWJsZVBvc2l0aW9uIGlzIHdoYXRldmVyIEhhbmRsZWJhcnMge0BzZWUgU291cmNlUG9zaXRpb259IHdhc1xuICAgKiBvcmlnaW5hbGx5IGlkZW50aWZpZWQgYXMgYnJva2VuLCBub24tZXhpc3RlbnQgb3Igc3ludGhldGljLlxuICAgKlxuICAgKiBJZiBhbiBgSW52aXNpYmxlUG9zaXRpb25gIG5ldmVyIGhhZCBhbiBzb3VyY2Ugb2Zmc2V0IGF0IGFsbCwgdGhpcyBtZXRob2QgcmV0dXJuc1xuICAgKiB7QHNlZSBVTktOT1dOX1BPU0lUSU9OfSBmb3IgY29tcGF0aWJpbGl0eS5cbiAgICovXG4gIHRvSlNPTigpOiBTb3VyY2VQb3NpdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMucG9zO1xuICB9XG5cbiAgd3JhcCgpOiBTb3VyY2VPZmZzZXQge1xuICAgIHJldHVybiBuZXcgU291cmNlT2Zmc2V0KHRoaXMpO1xuICB9XG5cbiAgZ2V0IG9mZnNldCgpOiBudWxsIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG4vKipcbiAqIENvbXBhcmUgdHdvIHtAc2VlIEFueVBvc2l0aW9ufSBhbmQgZGV0ZXJtaW5lIHdoZXRoZXIgdGhleSBhcmUgZXF1YWwuXG4gKlxuICogQHNlZSB7U291cmNlT2Zmc2V0I2VxbH1cbiAqL1xuY29uc3QgZXFsID0gbWF0Y2g8Ym9vbGVhbj4oKG0pID0+XG4gIG1cbiAgICAud2hlbihcbiAgICAgIE9mZnNldEtpbmQuSGJzUG9zaXRpb24sXG4gICAgICBPZmZzZXRLaW5kLkhic1Bvc2l0aW9uLFxuICAgICAgKHsgaGJzUG9zOiBsZWZ0IH0sIHsgaGJzUG9zOiByaWdodCB9KSA9PlxuICAgICAgICBsZWZ0LmNvbHVtbiA9PT0gcmlnaHQuY29sdW1uICYmIGxlZnQubGluZSA9PT0gcmlnaHQubGluZVxuICAgIClcbiAgICAud2hlbihcbiAgICAgIE9mZnNldEtpbmQuQ2hhclBvc2l0aW9uLFxuICAgICAgT2Zmc2V0S2luZC5DaGFyUG9zaXRpb24sXG4gICAgICAoeyBjaGFyUG9zOiBsZWZ0IH0sIHsgY2hhclBvczogcmlnaHQgfSkgPT4gbGVmdCA9PT0gcmlnaHRcbiAgICApXG4gICAgLndoZW4oXG4gICAgICBPZmZzZXRLaW5kLkNoYXJQb3NpdGlvbixcbiAgICAgIE9mZnNldEtpbmQuSGJzUG9zaXRpb24sXG4gICAgICAoeyBvZmZzZXQ6IGxlZnQgfSwgcmlnaHQpID0+IGxlZnQgPT09IHJpZ2h0LnRvQ2hhclBvcygpPy5vZmZzZXRcbiAgICApXG4gICAgLndoZW4oXG4gICAgICBPZmZzZXRLaW5kLkhic1Bvc2l0aW9uLFxuICAgICAgT2Zmc2V0S2luZC5DaGFyUG9zaXRpb24sXG4gICAgICAobGVmdCwgeyBvZmZzZXQ6IHJpZ2h0IH0pID0+IGxlZnQudG9DaGFyUG9zKCk/Lm9mZnNldCA9PT0gcmlnaHRcbiAgICApXG4gICAgLndoZW4oTWF0Y2hBbnksIE1hdGNoQW55LCAoKSA9PiBmYWxzZSlcbik7XG4iXSwic291cmNlUm9vdCI6IiJ9