@glimmer/runtime
Version:
Minimal runtime needed to render Glimmer templates
389 lines (307 loc) • 36.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.OnModifierState = void 0;
var _destroyable = require("@glimmer/destroyable");
var _env = require("@glimmer/env");
var _manager = require("@glimmer/manager");
var _reference = require("@glimmer/reference");
var _runtime = require("@glimmer/runtime");
var _validator = require("@glimmer/validator");
var _util = require("@glimmer/util");
const untouchableContext = (0, _util.buildUntouchableThis)('`on` modifier');
/*
Internet Explorer 11 does not support `once` and also does not support
passing `eventOptions`. In some situations it then throws a weird script
error, like:
```
Could not complete the operation due to error 80020101
```
This flag determines, whether `{ once: true }` and thus also event options in
general are supported.
*/
const SUPPORTS_EVENT_OPTIONS = (() => {
try {
const div = document.createElement('div');
let counter = 0;
div.addEventListener('click', () => counter++, {
once: true
});
let event;
if (typeof Event === 'function') {
event = new Event('click');
} else {
event = document.createEvent('Event');
event.initEvent('click', true, true);
}
div.dispatchEvent(event);
div.dispatchEvent(event);
return counter === 1;
} catch (error) {
return false;
}
})();
class OnModifierState {
constructor(element, args) {
this.tag = (0, _validator.createUpdatableTag)();
this.shouldUpdate = true;
this.element = element;
this.args = args;
}
updateFromArgs() {
let {
args
} = this;
let {
once,
passive,
capture
} = (0, _runtime.reifyNamed)(args.named);
if (once !== this.once) {
this.once = once;
this.shouldUpdate = true;
}
if (passive !== this.passive) {
this.passive = passive;
this.shouldUpdate = true;
}
if (capture !== this.capture) {
this.capture = capture;
this.shouldUpdate = true;
}
let options; // we want to handle both `true` and `false` because both have a meaning:
// https://bugs.chromium.org/p/chromium/issues/detail?id=770208
if (once !== undefined || passive !== undefined || capture !== undefined) {
options = this.options = {
once,
passive,
capture
};
} else {
this.options = undefined;
}
if (_env.DEBUG && (args.positional[0] === undefined || typeof (0, _reference.valueForRef)(args.positional[0]) !== 'string')) {
throw new Error('You must pass a valid DOM event name as the first argument to the `on` modifier');
}
let eventName = (0, _reference.valueForRef)(args.positional[0]);
if (eventName !== this.eventName) {
this.eventName = eventName;
this.shouldUpdate = true;
}
let userProvidedCallbackReference = args.positional[1];
if (_env.DEBUG) {
if (args.positional[1] === undefined) {
throw new Error(`You must pass a function as the second argument to the \`on\` modifier.`);
}
let value = (0, _reference.valueForRef)(userProvidedCallbackReference);
if (typeof value !== 'function') {
throw new Error(`You must pass a function as the second argument to the \`on\` modifier; you passed ${value === null ? 'null' : typeof value}. While rendering:\n\n${userProvidedCallbackReference.debugLabel}`);
}
}
let userProvidedCallback = (0, _reference.valueForRef)(userProvidedCallbackReference);
if (userProvidedCallback !== this.userProvidedCallback) {
this.userProvidedCallback = userProvidedCallback;
this.shouldUpdate = true;
}
if (_env.DEBUG && args.positional.length !== 2) {
throw new Error(`You can only pass two positional arguments (event name and callback) to the \`on\` modifier, but you provided ${args.positional.length}. Consider using the \`fn\` helper to provide additional arguments to the \`on\` callback.`);
}
let needsCustomCallback = SUPPORTS_EVENT_OPTIONS === false && once ||
/* needs manual once implementation */
_env.DEBUG && passive;
/* needs passive enforcement */
if (this.shouldUpdate) {
if (needsCustomCallback) {
let callback = this.callback = function (event) {
if (_env.DEBUG && passive) {
event.preventDefault = () => {
throw new Error(`You marked this listener as 'passive', meaning that you must not call 'event.preventDefault()': \n\n${userProvidedCallback}`);
};
}
if (!SUPPORTS_EVENT_OPTIONS && once) {
removeEventListener(this, eventName, callback, options);
}
return userProvidedCallback.call(untouchableContext, event);
};
} else if (_env.DEBUG) {
// prevent the callback from being bound to the element
this.callback = userProvidedCallback.bind(untouchableContext);
} else {
this.callback = userProvidedCallback;
}
}
}
}
exports.OnModifierState = OnModifierState;
let adds = 0;
let removes = 0;
function removeEventListener(element, eventName, callback, options) {
removes++;
if (SUPPORTS_EVENT_OPTIONS) {
// when options are supported, use them across the board
element.removeEventListener(eventName, callback, options);
} else if (options !== undefined && options.capture) {
// used only in the following case:
//
// `{ once: true | false, passive: true | false, capture: true }
//
// `once` is handled via a custom callback that removes after first
// invocation so we only care about capture here as a boolean
element.removeEventListener(eventName, callback, true);
} else {
// used only in the following cases:
//
// * where there is no options
// * `{ once: true | false, passive: true | false, capture: false }
element.removeEventListener(eventName, callback);
}
}
function addEventListener(element, eventName, callback, options) {
adds++;
if (SUPPORTS_EVENT_OPTIONS) {
// when options are supported, use them across the board
element.addEventListener(eventName, callback, options);
} else if (options !== undefined && options.capture) {
// used only in the following case:
//
// `{ once: true | false, passive: true | false, capture: true }
//
// `once` is handled via a custom callback that removes after first
// invocation so we only care about capture here as a boolean
element.addEventListener(eventName, callback, true);
} else {
// used only in the following cases:
//
// * where there is no options
// * `{ once: true | false, passive: true | false, capture: false }
element.addEventListener(eventName, callback);
}
}
/**
The `{{on}}` modifier lets you easily add event listeners (it uses
[EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
internally).
For example, if you'd like to run a function on your component when a `<button>`
in the components template is clicked you might do something like:
```app/components/like-post.hbs
<button {{on 'click' this.saveLike}}>Like this post!</button>
```
```app/components/like-post.js
import Component from '@glimmer/component';
import { action } from '@ember/object';
export default class LikePostComponent extends Component {
saveLike = () => {
// someone likes your post!
// better send a request off to your server...
}
}
```
### Arguments
`{{on}}` accepts two positional arguments, and a few named arguments.
The positional arguments are:
- `event` -- the name to use when calling `addEventListener`
- `callback` -- the function to be passed to `addEventListener`
The named arguments are:
- capture -- a `true` value indicates that events of this type will be dispatched
to the registered listener before being dispatched to any EventTarget beneath it
in the DOM tree.
- once -- indicates that the listener should be invoked at most once after being
added. If true, the listener would be automatically removed when invoked.
- passive -- if `true`, indicates that the function specified by listener will never
call preventDefault(). If a passive listener does call preventDefault(), the user
agent will do nothing other than generate a console warning. See
[Improving scrolling performance with passive listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Improving_scrolling_performance_with_passive_listeners)
to learn more.
The callback function passed to `{{on}}` will receive any arguments that are passed
to the event handler. Most commonly this would be the `event` itself.
If you would like to pass additional arguments to the function you should use
the `{{fn}}` helper.
For example, in our example case above if you'd like to pass in the post that
was being liked when the button is clicked you could do something like:
```app/components/like-post.hbs
<button {{on 'click' (fn this.saveLike @post)}}>Like this post!</button>
```
In this case, the `saveLike` function will receive two arguments: the click event
and the value of `@post`.
### Function Context
In the example above, we used an arrow function to ensure that `likePost` is
properly bound to the `items-list`, but let's explore what happens if we
left out the arrow function:
```app/components/like-post.js
import Component from '@glimmer/component';
export default class LikePostComponent extends Component {
saveLike() {
// ...snip...
}
}
```
In this example, when the button is clicked `saveLike` will be invoked,
it will **not** have access to the component instance. In other
words, it will have no `this` context, so please make sure your functions
are bound (via an arrow function or other means) before passing into `on`!
@method on
@public
*/
class OnModifierManager {
constructor() {
this.SUPPORTS_EVENT_OPTIONS = SUPPORTS_EVENT_OPTIONS;
}
getDebugName() {
return 'on';
}
get counters() {
return {
adds,
removes
};
}
create(_owner, element, _state, args) {
return new OnModifierState(element, args);
}
getTag(state) {
if (state === null) {
return null;
}
return state.tag;
}
install(state) {
if (state === null) {
return;
}
state.updateFromArgs();
let {
element,
eventName,
callback,
options
} = state;
addEventListener(element, eventName, callback, options);
(0, _destroyable.registerDestructor)(state, () => removeEventListener(element, eventName, callback, options));
state.shouldUpdate = false;
}
update(state) {
if (state === null) {
return;
} // stash prior state for el.removeEventListener
let {
element,
eventName,
callback,
options
} = state;
state.updateFromArgs();
if (!state.shouldUpdate) {
return;
} // use prior state values for removal
removeEventListener(element, eventName, callback, options); // read updated values from the state object
addEventListener(state.element, state.eventName, state.callback, state.options);
state.shouldUpdate = false;
}
getDestroyable(state) {
return state;
}
}
var _default = (0, _manager.setInternalModifierManager)(new OnModifierManager(), {});
exports.default = _default;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL21vZGlmaWVycy9vbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBRUE7O0FBRUEsTUFBTSxrQkFBa0IsR0FBRyxnQ0FBM0IsZUFBMkIsQ0FBM0I7QUFFQTs7Ozs7Ozs7Ozs7OztBQVlBLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxNQUFLO0FBQ25DLE1BQUk7QUFDRixVQUFNLEdBQUcsR0FBRyxRQUFRLENBQVIsYUFBQSxDQUFaLEtBQVksQ0FBWjtBQUNBLFFBQUksT0FBTyxHQUFYLENBQUE7QUFDQSxJQUFBLEdBQUcsQ0FBSCxnQkFBQSxDQUFBLE9BQUEsRUFBOEIsTUFBTSxPQUFwQyxFQUFBLEVBQStDO0FBQUUsTUFBQSxJQUFJLEVBQUU7QUFBUixLQUEvQztBQUVBLFFBQUEsS0FBQTs7QUFDQSxRQUFJLE9BQUEsS0FBQSxLQUFKLFVBQUEsRUFBaUM7QUFDL0IsTUFBQSxLQUFLLEdBQUcsSUFBQSxLQUFBLENBQVIsT0FBUSxDQUFSO0FBREYsS0FBQSxNQUVPO0FBQ0wsTUFBQSxLQUFLLEdBQUcsUUFBUSxDQUFSLFdBQUEsQ0FBUixPQUFRLENBQVI7QUFDQSxNQUFBLEtBQUssQ0FBTCxTQUFBLENBQUEsT0FBQSxFQUFBLElBQUEsRUFBQSxJQUFBO0FBQ0Q7O0FBRUQsSUFBQSxHQUFHLENBQUgsYUFBQSxDQUFBLEtBQUE7QUFDQSxJQUFBLEdBQUcsQ0FBSCxhQUFBLENBQUEsS0FBQTtBQUVBLFdBQU8sT0FBTyxLQUFkLENBQUE7QUFoQkYsR0FBQSxDQWlCRSxPQUFBLEtBQUEsRUFBYztBQUNkLFdBQUEsS0FBQTtBQUNEO0FBcEJILENBQStCLEdBQS9COztBQXVCTSxNQUFBLGVBQUEsQ0FBc0I7QUFhMUIsRUFBQSxXQUFBLENBQUEsT0FBQSxFQUFBLElBQUEsRUFBcUQ7QUFaOUMsU0FBQSxHQUFB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QWdCLEtBQUssQ0FBckIsU0FBQSxFQUFpQyxLQUFLLENBQXRDLFFBQUEsRUFBaUQsS0FBSyxDQUF0RSxPQUFnQixDQUFoQjtBQUVBLElBQUEsS0FBSyxDQUFMLFlBQUEsR0FBQSxLQUFBO0FBQ0Q7O0FBRUQsRUFBQSxjQUFjLENBQUEsS0FBQSxFQUE4QjtBQUMxQyxXQUFBLEtBQUE7QUFDRDs7QUFyRW9COztlQXdFUix5Q0FBMkIsSUFBRCxpQkFBQyxFQUEzQixFQUFmLEVBQWUsQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJlZ2lzdGVyRGVzdHJ1Y3RvciB9IGZyb20gJ0BnbGltbWVyL2Rlc3Ryb3lhYmxlJztcbmltcG9ydCB7IERFQlVHIH0gZnJvbSAnQGdsaW1tZXIvZW52JztcbmltcG9ydCB7IENhcHR1cmVkQXJndW1lbnRzLCBJbnRlcm5hbE1vZGlmaWVyTWFuYWdlciwgT3duZXIgfSBmcm9tICdAZ2xpbW1lci9pbnRlcmZhY2VzJztcbmltcG9ydCB7IHNldEludGVybmFsTW9kaWZpZXJNYW5hZ2VyIH0gZnJvbSAnQGdsaW1tZXIvbWFuYWdlcic7XG5pbXBvcnQgeyB2YWx1ZUZvclJlZiB9IGZyb20gJ0BnbGltbWVyL3JlZmVyZW5jZSc7XG5pbXBvcnQgeyByZWlmeU5hbWVkIH0gZnJvbSAnQGdsaW1tZXIvcnVudGltZSc7XG5pbXBvcnQgeyBjcmVhdGVVcGRhdGFibGVUYWcsIFVwZGF0YWJsZVRhZyB9IGZyb20gJ0BnbGltbWVyL3ZhbGlkYXRvcic7XG5pbXBvcnQgeyBTaW1wbGVFbGVtZW50IH0gZnJvbSAnQHNpbXBsZS1kb20vaW50ZXJmYWNlJztcbmltcG9ydCB7IGJ1aWxkVW50b3VjaGFibGVUaGlzIH0gZnJvbSAnQGdsaW1tZXIvdXRpbCc7XG5cbmNvbnN0IHVudG91Y2hhYmxlQ29udGV4dCA9IGJ1aWxkVW50b3VjaGFibGVUaGlzKCdgb25gIG1vZGlmaWVyJyk7XG5cbi8qXG4gIEludGVybmV0IEV4cGxvcmVyIDExIGRvZXMgbm90IHN1cHBvcnQgYG9uY2VgIGFuZCBhbHNvIGRvZXMgbm90IHN1cHBvcnRcbiAgcGFzc2luZyBgZXZlbnRPcHRpb25zYC4gSW4gc29tZSBzaXR1YXRpb25zIGl0IHRoZW4gdGhyb3dzIGEgd2VpcmQgc2NyaXB0XG4gIGVycm9yLCBsaWtlOlxuXG4gIGBgYFxuICBDb3VsZCBub3QgY29tcGxldGUgdGhlIG9wZXJhdGlvbiBkdWUgdG8gZXJyb3IgODAwMjAxMDFcbiAgYGBgXG5cbiAgVGhpcyBmbGFnIGRldGVybWluZXMsIHdoZXRoZXIgYHsgb25jZTogdHJ1ZSB9YCBhbmQgdGh1cyBhbHNvIGV2ZW50IG9wdGlvbnMgaW5cbiAgZ2VuZXJhbCBhcmUgc3VwcG9ydGVkLlxuKi9cbmNvbnN0IFNVUFBPUlRTX0VWRU5UX09QVElPTlMgPSAoKCkgPT4ge1xuICB0cnkge1xuICAgIGNvbnN0IGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGxldCBjb3VudGVyID0gMDtcbiAgICBkaXYuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiBjb3VudGVyKyssIHsgb25jZTogdHJ1ZSB9KTtcblxuICAgIGxldCBldmVudDtcbiAgICBpZiAodHlwZW9mIEV2ZW50ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBldmVudCA9IG5ldyBFdmVudCgnY2xpY2snKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnRXZlbnQnKTtcbiAgICAgIGV2ZW50LmluaXRFdmVudCgnY2xpY2snLCB0cnVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBkaXYuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgZGl2LmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuXG4gICAgcmV0dXJuIGNvdW50ZXIgPT09IDE7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59KSgpO1xuXG5leHBvcnQgY2xhc3MgT25Nb2RpZmllclN0YXRlIHtcbiAgcHVibGljIHRhZyA9IGNyZWF0ZVVwZGF0YWJsZVRhZygpO1xuICBwdWJsaWMgZWxlbWVudDogRWxlbWVudDtcbiAgcHVibGljIGFyZ3M6IENhcHR1cmVkQXJndW1lbnRzO1xuICBwdWJsaWMgZXZlbnROYW1lITogc3RyaW5nO1xuICBwdWJsaWMgY2FsbGJhY2shOiBFdmVudExpc3RlbmVyO1xuICBwcml2YXRlIHVzZXJQcm92aWRlZENhbGxiYWNrITogRXZlbnRMaXN0ZW5lcjtcbiAgcHVibGljIG9uY2U/OiBib29sZWFuO1xuICBwdWJsaWMgcGFzc2l2ZT86IGJvb2xlYW47XG4gIHB1YmxpYyBjYXB0dXJlPzogYm9vbGVhbjtcbiAgcHVibGljIG9wdGlvbnM/OiBBZGRFdmVudExpc3RlbmVyT3B0aW9ucztcbiAgcHVibGljIHNob3VsZFVwZGF0ZSA9IHRydWU7XG5cbiAgY29uc3RydWN0b3IoZWxlbWVudDogRWxlbWVudCwgYXJnczogQ2FwdHVyZWRBcmd1bWVudHMpIHtcbiAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIHRoaXMuYXJncyA9IGFyZ3M7XG4gIH1cblxuICB1cGRhdGVGcm9tQXJncygpOiB2b2lkIHtcbiAgICBsZXQgeyBhcmdzIH0gPSB0aGlzO1xuXG4gICAgbGV0IHsgb25jZSwgcGFzc2l2ZSwgY2FwdHVyZSB9OiBBZGRFdmVudExpc3RlbmVyT3B0aW9ucyA9IHJlaWZ5TmFtZWQoYXJncy5uYW1lZCk7XG4gICAgaWYgKG9uY2UgIT09IHRoaXMub25jZSkge1xuICAgICAgdGhpcy5vbmNlID0gb25jZTtcbiAgICAgIHRoaXMuc2hvdWxkVXBkYXRlID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAocGFzc2l2ZSAhPT0gdGhpcy5wYXNzaXZlKSB7XG4gICAgICB0aGlzLnBhc3NpdmUgPSBwYXNzaXZlO1xuICAgICAgdGhpcy5zaG91bGRVcGRhdGUgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChjYXB0dXJlICE9PSB0aGlzLmNhcHR1cmUpIHtcbiAgICAgIHRoaXMuY2FwdHVyZSA9IGNhcHR1cmU7XG4gICAgICB0aGlzLnNob3VsZFVwZGF0ZSA9IHRydWU7XG4gICAgfVxuXG4gICAgbGV0IG9wdGlvbnM6IEFkZEV2ZW50TGlzdGVuZXJPcHRpb25zO1xuICAgIC8vIHdlIHdhbnQgdG8gaGFuZGxlIGJvdGggYHRydWVgIGFuZCBgZmFsc2VgIGJlY2F1c2UgYm90aCBoYXZlIGEgbWVhbmluZzpcbiAgICAvLyBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD03NzAyMDhcbiAgICBpZiAob25jZSAhPT0gdW5kZWZpbmVkIHx8IHBhc3NpdmUgIT09IHVuZGVmaW5lZCB8fCBjYXB0dXJlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgPSB7IG9uY2UsIHBhc3NpdmUsIGNhcHR1cmUgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vcHRpb25zID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIERFQlVHICYmXG4gICAgICAoYXJncy5wb3NpdGlvbmFsWzBdID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIHZhbHVlRm9yUmVmKGFyZ3MucG9zaXRpb25hbFswXSkgIT09ICdzdHJpbmcnKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnWW91IG11c3QgcGFzcyBhIHZhbGlkIERPTSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudCB0byB0aGUgYG9uYCBtb2RpZmllcidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgbGV0IGV2ZW50TmFtZSA9IHZhbHVlRm9yUmVmKGFyZ3MucG9zaXRpb25hbFswXSkgYXMgc3RyaW5nO1xuICAgIGlmIChldmVudE5hbWUgIT09IHRoaXMuZXZlbnROYW1lKSB7XG4gICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgIHRoaXMuc2hvdWxkVXBkYXRlID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBsZXQgdXNlclByb3ZpZGVkQ2FsbGJhY2tSZWZlcmVuY2UgPSBhcmdzLnBvc2l0aW9uYWxbMV07XG5cbiAgICBpZiAoREVCVUcpIHtcbiAgICAgIGlmIChhcmdzLnBvc2l0aW9uYWxbMV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFlvdSBtdXN0IHBhc3MgYSBmdW5jdGlvbiBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHRvIHRoZSBcXGBvblxcYCBtb2RpZmllci5gKTtcbiAgICAgIH1cblxuICAgICAgbGV0IHZhbHVlID0gdmFsdWVGb3JSZWYodXNlclByb3ZpZGVkQ2FsbGJhY2tSZWZlcmVuY2UpO1xuXG4gICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgWW91IG11c3QgcGFzcyBhIGZ1bmN0aW9uIGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgdG8gdGhlIFxcYG9uXFxgIG1vZGlmaWVyOyB5b3UgcGFzc2VkICR7XG4gICAgICAgICAgICB2YWx1ZSA9PT0gbnVsbCA/ICdudWxsJyA6IHR5cGVvZiB2YWx1ZVxuICAgICAgICAgIH0uIFdoaWxlIHJlbmRlcmluZzpcXG5cXG4ke3VzZXJQcm92aWRlZENhbGxiYWNrUmVmZXJlbmNlLmRlYnVnTGFiZWx9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCB1c2VyUHJvdmlkZWRDYWxsYmFjayA9IHZhbHVlRm9yUmVmKHVzZXJQcm92aWRlZENhbGxiYWNrUmVmZXJlbmNlKSBhcyBFdmVudExpc3RlbmVyO1xuICAgIGlmICh1c2VyUHJvdmlkZWRDYWxsYmFjayAhPT0gdGhpcy51c2VyUHJvdmlkZWRDYWxsYmFjaykge1xuICAgICAgdGhpcy51c2VyUHJvdmlkZWRDYWxsYmFjayA9IHVzZXJQcm92aWRlZENhbGxiYWNrO1xuICAgICAgdGhpcy5zaG91bGRVcGRhdGUgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChERUJVRyAmJiBhcmdzLnBvc2l0aW9uYWwubGVuZ3RoICE9PSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBZb3UgY2FuIG9ubHkgcGFzcyB0d28gcG9zaXRpb25hbCBhcmd1bWVudHMgKGV2ZW50IG5hbWUgYW5kIGNhbGxiYWNrKSB0byB0aGUgXFxgb25cXGAgbW9kaWZpZXIsIGJ1dCB5b3UgcHJvdmlkZWQgJHthcmdzLnBvc2l0aW9uYWwubGVuZ3RofS4gQ29uc2lkZXIgdXNpbmcgdGhlIFxcYGZuXFxgIGhlbHBlciB0byBwcm92aWRlIGFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHRoZSBcXGBvblxcYCBjYWxsYmFjay5gXG4gICAgICApO1xuICAgIH1cblxuICAgIGxldCBuZWVkc0N1c3RvbUNhbGxiYWNrID1cbiAgICAgIChTVVBQT1JUU19FVkVOVF9PUFRJT05TID09PSBmYWxzZSAmJiBvbmNlKSAvKiBuZWVkcyBtYW51YWwgb25jZSBpbXBsZW1lbnRhdGlvbiAqLyB8fFxuICAgICAgKERFQlVHICYmIHBhc3NpdmUpOyAvKiBuZWVkcyBwYXNzaXZlIGVuZm9yY2VtZW50ICovXG5cbiAgICBpZiAodGhpcy5zaG91bGRVcGRhdGUpIHtcbiAgICAgIGlmIChuZWVkc0N1c3RvbUNhbGxiYWNrKSB7XG4gICAgICAgIGxldCBjYWxsYmFjayA9ICh0aGlzLmNhbGxiYWNrID0gZnVuY3Rpb24gKHRoaXM6IEVsZW1lbnQsIGV2ZW50KSB7XG4gICAgICAgICAgaWYgKERFQlVHICYmIHBhc3NpdmUpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0ID0gKCkgPT4ge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgYFlvdSBtYXJrZWQgdGhpcyBsaXN0ZW5lciBhcyAncGFzc2l2ZScsIG1lYW5pbmcgdGhhdCB5b3UgbXVzdCBub3QgY2FsbCAnZXZlbnQucHJldmVudERlZmF1bHQoKSc6IFxcblxcbiR7dXNlclByb3ZpZGVkQ2FsbGJhY2t9YFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIVNVUFBPUlRTX0VWRU5UX09QVElPTlMgJiYgb25jZSkge1xuICAgICAgICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcih0aGlzLCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHVzZXJQcm92aWRlZENhbGxiYWNrLmNhbGwodW50b3VjaGFibGVDb250ZXh0LCBldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChERUJVRykge1xuICAgICAgICAvLyBwcmV2ZW50IHRoZSBjYWxsYmFjayBmcm9tIGJlaW5nIGJvdW5kIHRvIHRoZSBlbGVtZW50XG4gICAgICAgIHRoaXMuY2FsbGJhY2sgPSB1c2VyUHJvdmlkZWRDYWxsYmFjay5iaW5kKHVudG91Y2hhYmxlQ29udGV4dCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmNhbGxiYWNrID0gdXNlclByb3ZpZGVkQ2FsbGJhY2s7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmxldCBhZGRzID0gMDtcbmxldCByZW1vdmVzID0gMDtcblxuZnVuY3Rpb24gcmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgZWxlbWVudDogRWxlbWVudCxcbiAgZXZlbnROYW1lOiBzdHJpbmcsXG4gIGNhbGxiYWNrOiBFdmVudExpc3RlbmVyLFxuICBvcHRpb25zPzogQWRkRXZlbnRMaXN0ZW5lck9wdGlvbnNcbik6IHZvaWQge1xuICByZW1vdmVzKys7XG5cbiAgaWYgKFNVUFBPUlRTX0VWRU5UX09QVElPTlMpIHtcbiAgICAvLyB3aGVuIG9wdGlvbnMgYXJlIHN1cHBvcnRlZCwgdXNlIHRoZW0gYWNyb3NzIHRoZSBib2FyZFxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKTtcbiAgfSBlbHNlIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5jYXB0dXJlKSB7XG4gICAgLy8gdXNlZCBvbmx5IGluIHRoZSBmb2xsb3dpbmcgY2FzZTpcbiAgICAvL1xuICAgIC8vIGB7IG9uY2U6IHRydWUgfCBmYWxzZSwgcGFzc2l2ZTogdHJ1ZSB8IGZhbHNlLCBjYXB0dXJlOiB0cnVlIH1cbiAgICAvL1xuICAgIC8vIGBvbmNlYCBpcyBoYW5kbGVkIHZpYSBhIGN1c3RvbSBjYWxsYmFjayB0aGF0IHJlbW92ZXMgYWZ0ZXIgZmlyc3RcbiAgICAvLyBpbnZvY2F0aW9uIHNvIHdlIG9ubHkgY2FyZSBhYm91dCBjYXB0dXJlIGhlcmUgYXMgYSBib29sZWFuXG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIHRydWUpO1xuICB9IGVsc2Uge1xuICAgIC8vIHVzZWQgb25seSBpbiB0aGUgZm9sbG93aW5nIGNhc2VzOlxuICAgIC8vXG4gICAgLy8gKiB3aGVyZSB0aGVyZSBpcyBubyBvcHRpb25zXG4gICAgLy8gKiBgeyBvbmNlOiB0cnVlIHwgZmFsc2UsIHBhc3NpdmU6IHRydWUgfCBmYWxzZSwgY2FwdHVyZTogZmFsc2UgfVxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBhZGRFdmVudExpc3RlbmVyKFxuICBlbGVtZW50OiBFbGVtZW50LFxuICBldmVudE5hbWU6IHN0cmluZyxcbiAgY2FsbGJhY2s6IEV2ZW50TGlzdGVuZXIsXG4gIG9wdGlvbnM/OiBBZGRFdmVudExpc3RlbmVyT3B0aW9uc1xuKTogdm9pZCB7XG4gIGFkZHMrKztcblxuICBpZiAoU1VQUE9SVFNfRVZFTlRfT1BUSU9OUykge1xuICAgIC8vIHdoZW4gb3B0aW9ucyBhcmUgc3VwcG9ydGVkLCB1c2UgdGhlbSBhY3Jvc3MgdGhlIGJvYXJkXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG9wdGlvbnMpO1xuICB9IGVsc2UgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLmNhcHR1cmUpIHtcbiAgICAvLyB1c2VkIG9ubHkgaW4gdGhlIGZvbGxvd2luZyBjYXNlOlxuICAgIC8vXG4gICAgLy8gYHsgb25jZTogdHJ1ZSB8IGZhbHNlLCBwYXNzaXZlOiB0cnVlIHwgZmFsc2UsIGNhcHR1cmU6IHRydWUgfVxuICAgIC8vXG4gICAgLy8gYG9uY2VgIGlzIGhhbmRsZWQgdmlhIGEgY3VzdG9tIGNhbGxiYWNrIHRoYXQgcmVtb3ZlcyBhZnRlciBmaXJzdFxuICAgIC8vIGludm9jYXRpb24gc28gd2Ugb25seSBjYXJlIGFib3V0IGNhcHR1cmUgaGVyZSBhcyBhIGJvb2xlYW5cbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjaywgdHJ1ZSk7XG4gIH0gZWxzZSB7XG4gICAgLy8gdXNlZCBvbmx5IGluIHRoZSBmb2xsb3dpbmcgY2FzZXM6XG4gICAgLy9cbiAgICAvLyAqIHdoZXJlIHRoZXJlIGlzIG5vIG9wdGlvbnNcbiAgICAvLyAqIGB7IG9uY2U6IHRydWUgfCBmYWxzZSwgcGFzc2l2ZTogdHJ1ZSB8IGZhbHNlLCBjYXB0dXJlOiBmYWxzZSB9XG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2spO1xuICB9XG59XG5cbi8qKlxuICBUaGUgYHt7b259fWAgbW9kaWZpZXIgbGV0cyB5b3UgZWFzaWx5IGFkZCBldmVudCBsaXN0ZW5lcnMgKGl0IHVzZXNcbiAgW0V2ZW50VGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXJdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9FdmVudFRhcmdldC9hZGRFdmVudExpc3RlbmVyKVxuICBpbnRlcm5hbGx5KS5cblxuICBGb3IgZXhhbXBsZSwgaWYgeW91J2QgbGlrZSB0byBydW4gYSBmdW5jdGlvbiBvbiB5b3VyIGNvbXBvbmVudCB3aGVuIGEgYDxidXR0b24+YFxuICBpbiB0aGUgY29tcG9uZW50cyB0ZW1wbGF0ZSBpcyBjbGlja2VkIHlvdSBtaWdodCBkbyBzb21ldGhpbmcgbGlrZTpcblxuICBgYGBhcHAvY29tcG9uZW50cy9saWtlLXBvc3QuaGJzXG4gIDxidXR0b24ge3tvbiAnY2xpY2snIHRoaXMuc2F2ZUxpa2V9fT5MaWtlIHRoaXMgcG9zdCE8L2J1dHRvbj5cbiAgYGBgXG5cbiAgYGBgYXBwL2NvbXBvbmVudHMvbGlrZS1wb3N0LmpzXG4gIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGdsaW1tZXIvY29tcG9uZW50JztcbiAgaW1wb3J0IHsgYWN0aW9uIH0gZnJvbSAnQGVtYmVyL29iamVjdCc7XG5cbiAgZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGlrZVBvc3RDb21wb25lbnQgZXh0ZW5kcyBDb21wb25lbnQge1xuICAgIHNhdmVMaWtlID0gKCkgPT4ge1xuICAgICAgLy8gc29tZW9uZSBsaWtlcyB5b3VyIHBvc3QhXG4gICAgICAvLyBiZXR0ZXIgc2VuZCBhIHJlcXVlc3Qgb2ZmIHRvIHlvdXIgc2VydmVyLi4uXG4gICAgfVxuICB9XG4gIGBgYFxuXG4gICMjIyBBcmd1bWVudHNcblxuICBge3tvbn19YCBhY2NlcHRzIHR3byBwb3NpdGlvbmFsIGFyZ3VtZW50cywgYW5kIGEgZmV3IG5hbWVkIGFyZ3VtZW50cy5cblxuICBUaGUgcG9zaXRpb25hbCBhcmd1bWVudHMgYXJlOlxuXG4gIC0gYGV2ZW50YCAtLSB0aGUgbmFtZSB0byB1c2Ugd2hlbiBjYWxsaW5nIGBhZGRFdmVudExpc3RlbmVyYFxuICAtIGBjYWxsYmFja2AgLS0gdGhlIGZ1bmN0aW9uIHRvIGJlIHBhc3NlZCB0byBgYWRkRXZlbnRMaXN0ZW5lcmBcblxuICBUaGUgbmFtZWQgYXJndW1lbnRzIGFyZTpcblxuICAtIGNhcHR1cmUgLS0gYSBgdHJ1ZWAgdmFsdWUgaW5kaWNhdGVzIHRoYXQgZXZlbnRzIG9mIHRoaXMgdHlwZSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICB0byB0aGUgcmVnaXN0ZXJlZCBsaXN0ZW5lciBiZWZvcmUgYmVpbmcgZGlzcGF0Y2hlZCB0byBhbnkgRXZlbnRUYXJnZXQgYmVuZWF0aCBpdFxuICAgIGluIHRoZSBET00gdHJlZS5cbiAgLSBvbmNlIC0tIGluZGljYXRlcyB0aGF0IHRoZSBsaXN0ZW5lciBzaG91bGQgYmUgaW52b2tlZCBhdCBtb3N0IG9uY2UgYWZ0ZXIgYmVpbmdcbiAgICBhZGRlZC4gSWYgdHJ1ZSwgdGhlIGxpc3RlbmVyIHdvdWxkIGJlIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZCB3aGVuIGludm9rZWQuXG4gIC0gcGFzc2l2ZSAtLSBpZiBgdHJ1ZWAsIGluZGljYXRlcyB0aGF0IHRoZSBmdW5jdGlvbiBzcGVjaWZpZWQgYnkgbGlzdGVuZXIgd2lsbCBuZXZlclxuICAgIGNhbGwgcHJldmVudERlZmF1bHQoKS4gSWYgYSBwYXNzaXZlIGxpc3RlbmVyIGRvZXMgY2FsbCBwcmV2ZW50RGVmYXVsdCgpLCB0aGUgdXNlclxuICAgIGFnZW50IHdpbGwgZG8gbm90aGluZyBvdGhlciB0aGFuIGdlbmVyYXRlIGEgY29uc29sZSB3YXJuaW5nLiBTZWVcbiAgICBbSW1wcm92aW5nIHNjcm9sbGluZyBwZXJmb3JtYW5jZSB3aXRoIHBhc3NpdmUgbGlzdGVuZXJzXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRXZlbnRUYXJnZXQvYWRkRXZlbnRMaXN0ZW5lciNJbXByb3Zpbmdfc2Nyb2xsaW5nX3BlcmZvcm1hbmNlX3dpdGhfcGFzc2l2ZV9saXN0ZW5lcnMpXG4gICAgdG8gbGVhcm4gbW9yZS5cblxuICBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gcGFzc2VkIHRvIGB7e29ufX1gIHdpbGwgcmVjZWl2ZSBhbnkgYXJndW1lbnRzIHRoYXQgYXJlIHBhc3NlZFxuICB0byB0aGUgZXZlbnQgaGFuZGxlci4gTW9zdCBjb21tb25seSB0aGlzIHdvdWxkIGJlIHRoZSBgZXZlbnRgIGl0c2VsZi5cblxuICBJZiB5b3Ugd291bGQgbGlrZSB0byBwYXNzIGFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHRoZSBmdW5jdGlvbiB5b3Ugc2hvdWxkIHVzZVxuICB0aGUgYHt7Zm59fWAgaGVscGVyLlxuXG4gIEZvciBleGFtcGxlLCBpbiBvdXIgZXhhbXBsZSBjYXNlIGFib3ZlIGlmIHlvdSdkIGxpa2UgdG8gcGFzcyBpbiB0aGUgcG9zdCB0aGF0XG4gIHdhcyBiZWluZyBsaWtlZCB3aGVuIHRoZSBidXR0b24gaXMgY2xpY2tlZCB5b3UgY291bGQgZG8gc29tZXRoaW5nIGxpa2U6XG5cbiAgYGBgYXBwL2NvbXBvbmVudHMvbGlrZS1wb3N0Lmhic1xuICA8YnV0dG9uIHt7b24gJ2NsaWNrJyAoZm4gdGhpcy5zYXZlTGlrZSBAcG9zdCl9fT5MaWtlIHRoaXMgcG9zdCE8L2J1dHRvbj5cbiAgYGBgXG5cbiAgSW4gdGhpcyBjYXNlLCB0aGUgYHNhdmVMaWtlYCBmdW5jdGlvbiB3aWxsIHJlY2VpdmUgdHdvIGFyZ3VtZW50czogdGhlIGNsaWNrIGV2ZW50XG4gIGFuZCB0aGUgdmFsdWUgb2YgYEBwb3N0YC5cblxuICAjIyMgRnVuY3Rpb24gQ29udGV4dFxuXG4gIEluIHRoZSBleGFtcGxlIGFib3ZlLCB3ZSB1c2VkIGFuIGFycm93IGZ1bmN0aW9uIHRvIGVuc3VyZSB0aGF0IGBsaWtlUG9zdGAgaXNcbiAgcHJvcGVybHkgYm91bmQgdG8gdGhlIGBpdGVtcy1saXN0YCwgYnV0IGxldCdzIGV4cGxvcmUgd2hhdCBoYXBwZW5zIGlmIHdlXG4gIGxlZnQgb3V0IHRoZSBhcnJvdyBmdW5jdGlvbjpcblxuICBgYGBhcHAvY29tcG9uZW50cy9saWtlLXBvc3QuanNcbiAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZ2xpbW1lci9jb21wb25lbnQnO1xuXG4gIGV4cG9ydCBkZWZhdWx0IGNsYXNzIExpa2VQb3N0Q29tcG9uZW50IGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgICBzYXZlTGlrZSgpIHtcbiAgICAgIC8vIC4uLnNuaXAuLi5cbiAgICB9XG4gIH1cbiAgYGBgXG5cbiAgSW4gdGhpcyBleGFtcGxlLCB3aGVuIHRoZSBidXR0b24gaXMgY2xpY2tlZCBgc2F2ZUxpa2VgIHdpbGwgYmUgaW52b2tlZCxcbiAgaXQgd2lsbCAqKm5vdCoqIGhhdmUgYWNjZXNzIHRvIHRoZSBjb21wb25lbnQgaW5zdGFuY2UuIEluIG90aGVyXG4gIHdvcmRzLCBpdCB3aWxsIGhhdmUgbm8gYHRoaXNgIGNvbnRleHQsIHNvIHBsZWFzZSBtYWtlIHN1cmUgeW91ciBmdW5jdGlvbnNcbiAgYXJlIGJvdW5kICh2aWEgYW4gYXJyb3cgZnVuY3Rpb24gb3Igb3RoZXIgbWVhbnMpIGJlZm9yZSBwYXNzaW5nIGludG8gYG9uYCFcblxuICBAbWV0aG9kIG9uXG4gIEBwdWJsaWNcbiovXG5jbGFzcyBPbk1vZGlmaWVyTWFuYWdlciBpbXBsZW1lbnRzIEludGVybmFsTW9kaWZpZXJNYW5hZ2VyPE9uTW9kaWZpZXJTdGF0ZSB8IG51bGwsIG9iamVjdD4ge1xuICBwdWJsaWMgU1VQUE9SVFNfRVZFTlRfT1BUSU9OUzogYm9vbGVhbiA9IFNVUFBPUlRTX0VWRU5UX09QVElPTlM7XG5cbiAgZ2V0RGVidWdOYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdvbic7XG4gIH1cblxuICBnZXQgY291bnRlcnMoKTogeyBhZGRzOiBudW1iZXI7IHJlbW92ZXM6IG51bWJlciB9IHtcbiAgICByZXR1cm4geyBhZGRzLCByZW1vdmVzIH07XG4gIH1cblxuICBjcmVhdGUoXG4gICAgX293bmVyOiBPd25lcixcbiAgICBlbGVtZW50OiBTaW1wbGVFbGVtZW50IHwgRWxlbWVudCxcbiAgICBfc3RhdGU6IG9iamVjdCxcbiAgICBhcmdzOiBDYXB0dXJlZEFyZ3VtZW50c1xuICApOiBPbk1vZGlmaWVyU3RhdGUgfCBudWxsIHtcbiAgICByZXR1cm4gbmV3IE9uTW9kaWZpZXJTdGF0ZShlbGVtZW50IGFzIEVsZW1lbnQsIGFyZ3MpO1xuICB9XG5cbiAgZ2V0VGFnKHN0YXRlOiBPbk1vZGlmaWVyU3RhdGUgfCBudWxsKTogVXBkYXRhYmxlVGFnIHwgbnVsbCB7XG4gICAgaWYgKHN0YXRlID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gc3RhdGUudGFnO1xuICB9XG5cbiAgaW5zdGFsbChzdGF0ZTogT25Nb2RpZmllclN0YXRlIHwgbnVsbCk6IHZvaWQge1xuICAgIGlmIChzdGF0ZSA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHN0YXRlLnVwZGF0ZUZyb21BcmdzKCk7XG5cbiAgICBsZXQgeyBlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zIH0gPSBzdGF0ZTtcblxuICAgIGFkZEV2ZW50TGlzdGVuZXIoZWxlbWVudCwgZXZlbnROYW1lLCBjYWxsYmFjaywgb3B0aW9ucyk7XG5cbiAgICByZWdpc3RlckRlc3RydWN0b3Ioc3RhdGUsICgpID0+IHJlbW92ZUV2ZW50TGlzdGVuZXIoZWxlbWVudCwgZXZlbnROYW1lLCBjYWxsYmFjaywgb3B0aW9ucykpO1xuXG4gICAgc3RhdGUuc2hvdWxkVXBkYXRlID0gZmFsc2U7XG4gIH1cblxuICB1cGRhdGUoc3RhdGU6IE9uTW9kaWZpZXJTdGF0ZSB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAoc3RhdGUgPT09IG51bGwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBzdGFzaCBwcmlvciBzdGF0ZSBmb3IgZWwucmVtb3ZlRXZlbnRMaXN0ZW5lclxuICAgIGxldCB7IGVsZW1lbnQsIGV2ZW50TmFtZSwgY2FsbGJhY2ssIG9wdGlvbnMgfSA9IHN0YXRlO1xuXG4gICAgc3RhdGUudXBkYXRlRnJvbUFyZ3MoKTtcblxuICAgIGlmICghc3RhdGUuc2hvdWxkVXBkYXRlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gdXNlIHByaW9yIHN0YXRlIHZhbHVlcyBmb3IgcmVtb3ZhbFxuICAgIHJlbW92ZUV2ZW50TGlzdGVuZXIoZWxlbWVudCwgZXZlbnROYW1lLCBjYWxsYmFjaywgb3B0aW9ucyk7XG5cbiAgICAvLyByZWFkIHVwZGF0ZWQgdmFsdWVzIGZyb20gdGhlIHN0YXRlIG9iamVjdFxuICAgIGFkZEV2ZW50TGlzdGVuZXIoc3RhdGUuZWxlbWVudCwgc3RhdGUuZXZlbnROYW1lLCBzdGF0ZS5jYWxsYmFjaywgc3RhdGUub3B0aW9ucyk7XG5cbiAgICBzdGF0ZS5zaG91bGRVcGRhdGUgPSBmYWxzZTtcbiAgfVxuXG4gIGdldERlc3Ryb3lhYmxlKHN0YXRlOiBPbk1vZGlmaWVyU3RhdGUgfCBudWxsKTogT25Nb2RpZmllclN0YXRlIHwgbnVsbCB7XG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IHNldEludGVybmFsTW9kaWZpZXJNYW5hZ2VyKG5ldyBPbk1vZGlmaWVyTWFuYWdlcigpLCB7fSk7XG4iXSwic291cmNlUm9vdCI6IiJ9