/** * @license * Copyright 2017 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================================= */ import { isPromise } from './util_base'; // Expects flags from URL in the format ?tfjsflags=FLAG1:1,FLAG2:true. const TENSORFLOWJS_FLAGS_PREFIX = 'tfjsflags'; /** * The environment contains evaluated flags as well as the registered platform. * This is always used as a global singleton and can be retrieved with * `tf.env()`. * * @doc {heading: 'Environment'} */ export class Environment { // tslint:disable-next-line: no-any constructor(global) { this.global = global; this.flags = {}; this.flagRegistry = {}; this.urlFlags = {}; // Jasmine spies on this in 'environment_test.ts' this.getQueryParams = getQueryParams; this.populateURLFlags(); } setPlatform(platformName, platform) { if (this.platform != null) { if (!(env().getBool('IS_TEST') || env().getBool('PROD'))) { console.warn(`Platform ${this.platformName} has already been set. ` + `Overwriting the platform with ${platformName}.`); } } this.platformName = platformName; this.platform = platform; } registerFlag(flagName, evaluationFn, setHook) { this.flagRegistry[flagName] = { evaluationFn, setHook }; // Override the flag value from the URL. This has to happen here because // the environment is initialized before flags get registered. if (this.urlFlags[flagName] != null) { const flagValue = this.urlFlags[flagName]; if (!(env().getBool('IS_TEST') || env().getBool('PROD'))) { console.warn(`Setting feature override from URL ${flagName}: ${flagValue}.`); } this.set(flagName, flagValue); } } async getAsync(flagName) { if (flagName in this.flags) { return this.flags[flagName]; } this.flags[flagName] = await this.evaluateFlag(flagName); return this.flags[flagName]; } get(flagName) { if (flagName in this.flags) { return this.flags[flagName]; } const flagValue = this.evaluateFlag(flagName); if (isPromise(flagValue)) { throw new Error(`Flag ${flagName} cannot be synchronously evaluated. ` + `Please use getAsync() instead.`); } this.flags[flagName] = flagValue; return this.flags[flagName]; } getNumber(flagName) { return this.get(flagName); } getBool(flagName) { return this.get(flagName); } getString(flagName) { return this.get(flagName); } getFlags() { return this.flags; } // For backwards compatibility. get features() { return this.flags; } set(flagName, value) { if (this.flagRegistry[flagName] == null) { throw new Error(`Cannot set flag ${flagName} as it has not been registered.`); } this.flags[flagName] = value; if (this.flagRegistry[flagName].setHook != null) { this.flagRegistry[flagName].setHook(value); } } evaluateFlag(flagName) { if (this.flagRegistry[flagName] == null) { throw new Error(`Cannot evaluate flag '${flagName}': no evaluation function found.`); } return this.flagRegistry[flagName].evaluationFn(); } setFlags(flags) { this.flags = Object.assign({}, flags); } reset() { this.flags = {}; this.urlFlags = {}; this.populateURLFlags(); } populateURLFlags() { if (typeof this.global === 'undefined' || typeof this.global.location === 'undefined' || typeof this.global.location.search === 'undefined') { return; } const urlParams = this.getQueryParams(this.global.location.search); if (TENSORFLOWJS_FLAGS_PREFIX in urlParams) { const keyValues = urlParams[TENSORFLOWJS_FLAGS_PREFIX].split(','); keyValues.forEach(keyValue => { const [key, value] = keyValue.split(':'); this.urlFlags[key] = parseValue(key, value); }); } } } export function getQueryParams(queryString) { const params = {}; queryString.replace(/[?&]([^=?&]+)(?:=([^&]*))?/g, (s, ...t) => { decodeParam(params, t[0], t[1]); return t.join('='); }); return params; } function decodeParam(params, name, value) { params[decodeURIComponent(name)] = decodeURIComponent(value || ''); } function parseValue(flagName, value) { const lowerCaseValue = value.toLowerCase(); if (lowerCaseValue === 'true' || lowerCaseValue === 'false') { return lowerCaseValue === 'true'; } else if (`${+lowerCaseValue}` === lowerCaseValue) { return +lowerCaseValue; } else { return value; } } /** * Returns the current environment (a global singleton). * * The environment object contains the evaluated feature values as well as the * active platform. * * @doc {heading: 'Environment'} */ export function env() { return ENV; } export let ENV = null; export function setEnvironmentGlobal(environment) { ENV = environment; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW52aXJvbm1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi90ZmpzLWNvcmUvc3JjL2Vudmlyb25tZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUdILE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFFdEMsc0VBQXNFO0FBQ3RFLE1BQU0seUJBQXlCLEdBQUcsV0FBVyxDQUFDO0FBWTlDOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxXQUFXO0lBWXRCLG1DQUFtQztJQUNuQyxZQUFtQixNQUFXO1FBQVgsV0FBTSxHQUFOLE1BQU0sQ0FBSztRQVp0QixVQUFLLEdBQVUsRUFBRSxDQUFDO1FBQ2xCLGlCQUFZLEdBQTRDLEVBQUUsQ0FBQztRQUUzRCxhQUFRLEdBQVUsRUFBRSxDQUFDO1FBSzdCLGlEQUFpRDtRQUNqRCxtQkFBYyxHQUFHLGNBQWMsQ0FBQztRQUk5QixJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRUQsV0FBVyxDQUFDLFlBQW9CLEVBQUUsUUFBa0I7UUFDbEQsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksRUFBRTtZQUN6QixJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUU7Z0JBQ3hELE9BQU8sQ0FBQyxJQUFJLENBQ1IsWUFBWSxJQUFJLENBQUMsWUFBWSx5QkFBeUI7b0JBQ3RELGlDQUFpQyxZQUFZLEdBQUcsQ0FBQyxDQUFDO2FBQ3ZEO1NBQ0Y7UUFDRCxJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztRQUNqQyxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztJQUMzQixDQUFDO0lBRUQsWUFBWSxDQUNSLFFBQWdCLEVBQUUsWUFBOEIsRUFDaEQsT0FB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O0FBQ0gsTUFBTSxVQUFVLEdBQUc7SUFDakIsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQsTUFBTSxDQUFDLElBQUksR0FBRyxHQUFnQixJQUFJLENBQUM7QUFDbkMsTUFBTSxVQUFVLG9CQUFvQixDQUFDLFdBQXdCO0lBQzNELEdBQUcsR0FBRyxXQUFXLENBQUM7QUFDcEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuaW1wb3J0IHtQbGF0Zm9ybX0gZnJvbSAnLi9wbGF0Zm9ybXMvcGxhdGZvcm0nO1xuaW1wb3J0IHtpc1Byb21pc2V9IGZyb20gJy4vdXRpbF9iYXNlJztcblxuLy8gRXhwZWN0cyBmbGFncyBmcm9tIFVSTCBpbiB0aGUgZm9ybWF0ID90ZmpzZmxhZ3M9RkxBRzE6MSxGTEFHMjp0cnVlLlxuY29uc3QgVEVOU09SRkxPV0pTX0ZMQUdTX1BSRUZJWCA9ICd0ZmpzZmxhZ3MnO1xuXG50eXBlIEZsYWdWYWx1ZSA9IG51bWJlcnxib29sZWFufHN0cmluZztcbnR5cGUgRmxhZ0V2YWx1YXRpb25GbiA9ICgoKSA9PiBGbGFnVmFsdWUpfCgoKSA9PiBQcm9taXNlPEZsYWdWYWx1ZT4pO1xuZXhwb3J0IHR5cGUgRmxhZ3MgPSB7XG4gIFtmZWF0dXJlTmFtZTogc3RyaW5nXTogRmxhZ1ZhbHVlXG59O1xuZXhwb3J0IHR5cGUgRmxhZ1JlZ2lzdHJ5RW50cnkgPSB7XG4gIGV2YWx1YXRpb25GbjogRmxhZ0V2YWx1YXRpb25GbjtcbiAgc2V0SG9vaz86ICh2YWx1ZTogRmxhZ1ZhbHVlKSA9PiB2b2lkO1xufTtcblxuLyoqXG4gKiBUaGUgZW52aXJvbm1lbnQgY29udGFpbnMgZXZhbHVhdGVkIGZsYWdzIGFzIHdlbGwgYXMgdGhlIHJlZ2lzdGVyZWQgcGxhdGZvcm0uXG4gKiBUaGlzIGlzIGFsd2F5cyB1c2VkIGFzIGEgZ2xvYmFsIHNpbmdsZXRvbiBhbmQgY2FuIGJlIHJldHJpZXZlZCB3aXRoXG4gKiBgdGYuZW52KClgLlxuICpcbiAqIEBkb2Mge2hlYWRpbmc6ICdFbnZpcm9ubWVudCd9XG4gKi9cbmV4cG9ydCBjbGFzcyBFbnZpcm9ubWVudCB7XG4gIHByaXZhdGUgZmxhZ3M6IEZsYWdzID0ge307XG4gIHByaXZhdGUgZmxhZ1JlZ2lzdHJ5OiB7W2ZsYWdOYW1lOiBzdHJpbmddOiBGbGFnUmVnaXN0cnlFbnRyeX0gPSB7fTtcblxuICBwcml2YXRlIHVybEZsYWdzOiBGbGFncyA9IHt9O1xuXG4gIHBsYXRmb3JtTmFtZTogc3RyaW5nO1xuICBwbGF0Zm9ybTogUGxhdGZvcm07XG5cbiAgLy8gSmFzbWluZSBzcGllcyBvbiB0aGlzIGluICdlbnZpcm9ubWVudF90ZXN0LnRzJ1xuICBnZXRRdWVyeVBhcmFtcyA9IGdldFF1ZXJ5UGFyYW1zO1xuXG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogbm8tYW55XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBnbG9iYWw6IGFueSkge1xuICAgIHRoaXMucG9wdWxhdGVVUkxGbGFncygpO1xuICB9XG5cbiAgc2V0UGxhdGZvcm0ocGxhdGZvcm1OYW1lOiBzdHJpbmcsIHBsYXRmb3JtOiBQbGF0Zm9ybSkge1xuICAgIGlmICh0aGlzLnBsYXRmb3JtICE9IG51bGwpIHtcbiAgICAgIGlmICghKGVudigpLmdldEJvb2woJ0lTX1RFU1QnKSB8fCBlbnYoKS5nZXRCb29sKCdQUk9EJykpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgIGBQbGF0Zm9ybSAke3RoaXMucGxhdGZvcm1OYW1lfSBoYXMgYWxyZWFkeSBiZWVuIHNldC4gYCArXG4gICAgICAgICAgICBgT3ZlcndyaXRpbmcgdGhlIHBsYXRmb3JtIHdpdGggJHtwbGF0Zm9ybU5hbWV9LmApO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnBsYXRmb3JtTmFtZSA9IHBsYXRmb3JtTmFtZTtcbiAgICB0aGlzLnBsYXRmb3JtID0gcGxhdGZvcm07XG4gIH1cblxuICByZWdpc3RlckZsYWcoXG4gICAgICBmbGFnTmFtZTogc3RyaW5nLCBldmFsdWF0aW9uRm46IEZsYWdFdmFsdWF0aW9uRm4sXG4gICAgICBzZXRIb29rPzogKHZhbHVlOiBGbGFnVmFsdWUpID0+IHZvaWQpIHtcbiAgICB0aGlzLmZsYWdSZWdpc3RyeVtmbGFnTmFtZV0gPSB7ZXZhbHVhdGlvbkZuLCBzZXRIb29rfTtcblxuICAgIC8vIE92ZXJyaWRlIHRoZSBmbGFnIHZhbHVlIGZyb20gdGhlIFVSTC4gVGhpcyBoYXMgdG8gaGFwcGVuIGhlcmUgYmVjYXVzZVxuICAgIC8vIHRoZSBlbnZpcm9ubWVudCBpcyBpbml0aWFsaXplZCBiZWZvcmUgZmxhZ3MgZ2V0IHJlZ2lzdGVyZWQuXG4gICAgaWYgKHRoaXMudXJsRmxhZ3NbZmxhZ05hbWVdICE9IG51bGwpIHtcbiAgICAgIGNvbnN0IGZsYWdWYWx1ZSA9IHRoaXMudXJsRmxhZ3NbZmxhZ05hbWVdO1xuICAgICAgaWYgKCEoZW52KCkuZ2V0Qm9vbCgnSVNfVEVTVCcpIHx8IGVudigpLmdldEJvb2woJ1BST0QnKSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgYFNldHRpbmcgZmVhdHVyZSBvdmVycmlkZSBmcm9tIFVSTCAke2ZsYWdOYW1lfTogJHtmbGFnVmFsdWV9LmApO1xuICAgICAgfVxuICAgICAgdGhpcy5zZXQoZmxhZ05hbWUsIGZsYWdWYWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZ2V0QXN5bmMoZmxhZ05hbWU6IHN0cmluZyk6IFByb21pc2U8RmxhZ1ZhbHVlPiB7XG4gICAgaWYgKGZsYWdOYW1lIGluIHRoaXMuZmxhZ3MpIHtcbiAgICAgIHJldHVybiB0aGlzLmZsYWdzW2ZsYWdOYW1lXTtcbiAgICB9XG5cbiAgICB0aGlzLmZsYWdzW2ZsYWdOYW1lXSA9IGF3YWl0IHRoaXMuZXZhbHVhdGVGbGFnKGZsYWdOYW1lKTtcbiAgICByZXR1cm4gdGhpcy5mbGFnc1tmbGFnTmFtZV07XG4gIH1cblxuICBnZXQoZmxhZ05hbWU6IHN0cmluZyk6IEZsYWdWYWx1ZSB7XG4gICAgaWYgKGZsYWdOYW1lIGluIHRoaXMuZmxhZ3MpIHtcbiAgICAgIHJldHVybiB0aGlzLmZsYWdzW2ZsYWdOYW1lXTtcbiAgICB9XG5cbiAgICBjb25zdCBmbGFnVmFsdWUgPSB0aGlzLmV2YWx1YXRlRmxhZyhmbGFnTmFtZSk7XG4gICAgaWYgKGlzUHJvbWlzZShmbGFnVmFsdWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEZsYWcgJHtmbGFnTmFtZX0gY2Fubm90IGJlIHN5bmNocm9ub3VzbHkgZXZhbHVhdGVkLiBgICtcbiAgICAgICAgICBgUGxlYXNlIHVzZSBnZXRBc3luYygpIGluc3RlYWQuYCk7XG4gICAgfVxuXG4gICAgdGhpcy5mbGFnc1tmbGFnTmFtZV0gPSBmbGFnVmFsdWU7XG4gICAgcmV0dXJuIHRoaXMuZmxhZ3NbZmxhZ05hbWVdO1xuICB9XG5cbiAgZ2V0TnVtYmVyKGZsYWdOYW1lOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmdldChmbGFnTmFtZSkgYXMgbnVtYmVyO1xuICB9XG5cbiAgZ2V0Qm9vbChmbGFnTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KGZsYWdOYW1lKSBhcyBib29sZWFuO1xuICB9XG5cbiAgZ2V0U3RyaW5nKGZsYWdOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmdldChmbGFnTmFtZSkgYXMgc3RyaW5nO1xuICB9XG5cbiAgZ2V0RmxhZ3MoKTogRmxhZ3Mge1xuICAgIHJldHVybiB0aGlzLmZsYWdzO1xuICB9XG4gIC8vIEZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbiAgZ2V0IGZlYXR1cmVzKCk6IEZsYWdzIHtcbiAgICByZXR1cm4gdGhpcy5mbGFncztcbiAgfVxuXG4gIHNldChmbGFnTmFtZTogc3RyaW5nLCB2YWx1ZTogRmxhZ1ZhbHVlKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZmxhZ1JlZ2lzdHJ5W2ZsYWdOYW1lXSA9PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYENhbm5vdCBzZXQgZmxhZyAke2ZsYWdOYW1lfSBhcyBpdCBoYXMgbm90IGJlZW4gcmVnaXN0ZXJlZC5gKTtcbiAgICB9XG4gICAgdGhpcy5mbGFnc1tmbGFnTmFtZV0gPSB2YWx1ZTtcbiAgICBpZiAodGhpcy5mbGFnUmVnaXN0cnlbZmxhZ05hbWVdLnNldEhvb2sgIT0gbnVsbCkge1xuICAgICAgdGhpcy5mbGFnUmVnaXN0cnlbZmxhZ05hbWVdLnNldEhvb2sodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZXZhbHVhdGVGbGFnKGZsYWdOYW1lOiBzdHJpbmcpOiBGbGFnVmFsdWV8UHJvbWlzZTxGbGFnVmFsdWU+IHtcbiAgICBpZiAodGhpcy5mbGFnUmVnaXN0cnlbZmxhZ05hbWVdID09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgQ2Fubm90IGV2YWx1YXRlIGZsYWcgJyR7ZmxhZ05hbWV9Jzogbm8gZXZhbHVhdGlvbiBmdW5jdGlvbiBmb3VuZC5gKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZmxhZ1JlZ2lzdHJ5W2ZsYWdOYW1lXS5ldmFsdWF0aW9uRm4oKTtcbiAgfVxuXG4gIHNldEZsYWdzKGZsYWdzOiBGbGFncykge1xuICAgIHRoaXMuZmxhZ3MgPSBPYmplY3QuYXNzaWduKHt9LCBmbGFncyk7XG4gIH1cblxuICByZXNldCgpIHtcbiAgICB0aGlzLmZsYWdzID0ge307XG4gICAgdGhpcy51cmxGbGFncyA9IHt9O1xuICAgIHRoaXMucG9wdWxhdGVVUkxGbGFncygpO1xuICB9XG5cbiAgcHJpdmF0ZSBwb3B1bGF0ZVVSTEZsYWdzKCk6IHZvaWQge1xuICAgIGlmICh0eXBlb2YgdGhpcy5nbG9iYWwgPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgIHR5cGVvZiB0aGlzLmdsb2JhbC5sb2NhdGlvbiA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgdHlwZW9mIHRoaXMuZ2xvYmFsLmxvY2F0aW9uLnNlYXJjaCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cmxQYXJhbXMgPSB0aGlzLmdldFF1ZXJ5UGFyYW1zKHRoaXMuZ2xvYmFsLmxvY2F0aW9uLnNlYXJjaCk7XG4gICAgaWYgKFRFTlNPUkZMT1dKU19GTEFHU19QUkVGSVggaW4gdXJsUGFyYW1zKSB7XG4gICAgICBjb25zdCBrZXlWYWx1ZXMgPSB1cmxQYXJhbXNbVEVOU09SRkxPV0pTX0ZMQUdTX1BSRUZJWF0uc3BsaXQoJywnKTtcbiAgICAgIGtleVZhbHVlcy5mb3JFYWNoKGtleVZhbHVlID0+IHtcbiAgICAgICAgY29uc3QgW2tleSwgdmFsdWVdID0ga2V5VmFsdWUuc3BsaXQoJzonKSBhcyBbc3RyaW5nLCBzdHJpbmddO1xuICAgICAgICB0aGlzLnVybEZsYWdzW2tleV0gPSBwYXJzZVZhbHVlKGtleSwgdmFsdWUpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRRdWVyeVBhcmFtcyhxdWVyeVN0cmluZzogc3RyaW5nKToge1trZXk6IHN0cmluZ106IHN0cmluZ30ge1xuICBjb25zdCBwYXJhbXMgPSB7fTtcbiAgcXVlcnlTdHJpbmcucmVwbGFjZSgvWz8mXShbXj0/Jl0rKSg/Oj0oW14mXSopKT8vZywgKHMsIC4uLnQpID0+IHtcbiAgICBkZWNvZGVQYXJhbShwYXJhbXMsIHRbMF0sIHRbMV0pO1xuICAgIHJldHVybiB0LmpvaW4oJz0nKTtcbiAgfSk7XG4gIHJldHVybiBwYXJhbXM7XG59XG5cbmZ1bmN0aW9uIGRlY29kZVBhcmFtKFxuICAgIHBhcmFtczoge1trZXk6IHN0cmluZ106IHN0cmluZ30sIG5hbWU6IHN0cmluZywgdmFsdWU/OiBzdHJpbmcpIHtcbiAgcGFyYW1zW2RlY29kZVVSSUNvbXBvbmVudChuYW1lKV0gPSBkZWNvZGVVUklDb21wb25lbnQodmFsdWUgfHwgJycpO1xufVxuXG5mdW5jdGlvbiBwYXJzZVZhbHVlKGZsYWdOYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiBGbGFnVmFsdWUge1xuICBjb25zdCBsb3dlckNhc2VWYWx1ZSA9IHZhbHVlLnRvTG93ZXJDYXNlKCk7XG4gIGlmIChsb3dlckNhc2VWYWx1ZSA9PT0gJ3RydWUnIHx8IGxvd2VyQ2FzZVZhbHVlID09PSAnZmFsc2UnKSB7XG4gICAgcmV0dXJuIGxvd2VyQ2FzZVZhbHVlID09PSAndHJ1ZSc7XG4gIH0gZWxzZSBpZiAoYCR7KyBsb3dlckNhc2VWYWx1ZX1gID09PSBsb3dlckNhc2VWYWx1ZSkge1xuICAgIHJldHVybiArbG93ZXJDYXNlVmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgY3VycmVudCBlbnZpcm9ubWVudCAoYSBnbG9iYWwgc2luZ2xldG9uKS5cbiAqXG4gKiBUaGUgZW52aXJvbm1lbnQgb2JqZWN0IGNvbnRhaW5zIHRoZSBldmFsdWF0ZWQgZmVhdHVyZSB2YWx1ZXMgYXMgd2VsbCBhcyB0aGVcbiAqIGFjdGl2ZSBwbGF0Zm9ybS5cbiAqXG4gKiBAZG9jIHtoZWFkaW5nOiAnRW52aXJvbm1lbnQnfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZW52KCkge1xuICByZXR1cm4gRU5WO1xufVxuXG5leHBvcnQgbGV0IEVOVjogRW52aXJvbm1lbnQgPSBudWxsO1xuZXhwb3J0IGZ1bmN0aW9uIHNldEVudmlyb25tZW50R2xvYmFsKGVudmlyb25tZW50OiBFbnZpcm9ubWVudCkge1xuICBFTlYgPSBlbnZpcm9ubWVudDtcbn1cbiJdfQ==