canonical
Version:
Canonical code style linter and formatter for JavaScript, SCSS, CSS and JSON.
282 lines (224 loc) • 20.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _set = require('babel-runtime/core-js/set');
var _set2 = _interopRequireDefault(_set);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _map = require('babel-runtime/core-js/map');
var _map2 = _interopRequireDefault(_map);
exports.recursivePatternCapture = recursivePatternCapture;
var _fs = require('fs');
var fs = _interopRequireWildcard(_fs);
var _crypto = require('crypto');
var _parse2 = require('./parse');
var _parse3 = _interopRequireDefault(_parse2);
var _resolve = require('./resolve');
var _resolve2 = _interopRequireDefault(_resolve);
var _ignore = require('./ignore');
var _ignore2 = _interopRequireDefault(_ignore);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// map from settings sha1 => path => export map objects
var exportCaches = new _map2.default();
var ExportMap = function () {
function ExportMap(context) {
(0, _classCallCheck3.default)(this, ExportMap);
this.context = context;
this.named = new _set2.default();
this.errors = [];
}
(0, _createClass3.default)(ExportMap, [{
key: 'resolveReExport',
value: function resolveReExport(node, base) {
var remotePath = _resolve2.default.relative(node.source.value, base, this.settings);
if (remotePath == null) return null;
return ExportMap.for(remotePath, this.context);
}
}, {
key: 'captureDefault',
value: function captureDefault(n) {
if (n.type !== 'ExportDefaultDeclaration') return;
this.named.add('default');
}
/**
* capture all named exports from remote module.
*
* returns null if this node wasn't an ExportAllDeclaration
* returns false if it was not resolved
* returns true if it was resolved + parsed
*
* @param {node} n
* @param {string} path - the path of the module currently parsing
* @return {boolean?}
*/
}, {
key: 'captureAll',
value: function captureAll(n, path) {
if (n.type !== 'ExportAllDeclaration') return null;
var remoteMap = this.resolveReExport(n, path);
if (remoteMap == null) return false;
remoteMap.named.forEach(function (name) {
this.named.add(name);
}.bind(this));
return true;
}
}, {
key: 'captureNamedDeclaration',
value: function captureNamedDeclaration(n, path) {
var _this = this;
if (n.type !== 'ExportNamedDeclaration') return;
// capture declaration
if (n.declaration != null) {
switch (n.declaration.type) {
case 'FunctionDeclaration':
case 'ClassDeclaration':
case 'TypeAlias':
// flowtype with babel-eslint parser
this.named.add(n.declaration.id.name);
break;
case 'VariableDeclaration':
n.declaration.declarations.forEach(function (d) {
return recursivePatternCapture(d.id, function (id) {
return _this.named.add(id.name);
});
});
break;
}
}
// capture specifiers
var remoteMap = undefined;
if (n.source) remoteMap = this.resolveReExport(n, path);
n.specifiers.forEach(function (s) {
if (s.type === 'ExportDefaultSpecifier') {
// don't add it if it is not present in the exported module
if (!remoteMap || !remoteMap.hasDefault) return;
}
this.named.add(s.exported.name);
}.bind(this));
}
}, {
key: 'reportErrors',
value: function reportErrors(context, declaration) {
context.report({
node: declaration.source,
message: 'Parse errors in imported module \'' + declaration.source.value + '\': ' + ('' + this.errors.map(function (e) {
return e.message + ' (' + e.lineNumber + ':' + e.column + ')';
}).join(', '))
});
}
}, {
key: 'settings',
get: function get() {
return this.context && this.context.settings;
}
}, {
key: 'hasDefault',
get: function get() {
return this.named.has('default');
}
}, {
key: 'hasNamed',
get: function get() {
return this.named.size > (this.hasDefault ? 1 : 0);
}
}], [{
key: 'get',
value: function get(source, context) {
var path = (0, _resolve2.default)(source, context);
if (path == null) return null;
return ExportMap.for(path, context);
}
}, {
key: 'for',
value: function _for(path, context) {
var exportMap = undefined;
var cacheKey = hashObject({
settings: context.settings,
parserPath: context.parserPath,
parserOptions: context.parserOptions
});
var exportCache = exportCaches.get(cacheKey);
if (exportCache === undefined) {
exportCache = new _map2.default();
exportCaches.set(cacheKey, exportCache);
}
exportMap = exportCache.get(path);
// return cached ignore
if (exportMap === null) return null;
var stats = fs.statSync(path);
if (exportMap != null) {
// date equality check
if (exportMap.mtime - stats.mtime === 0) {
return exportMap;
}
// future: check content equality?
}
exportMap = ExportMap.parse(path, context);
exportMap.mtime = stats.mtime;
// ignore empties, optionally
if (exportMap.named.size === 0 && (0, _ignore2.default)(path, context)) {
exportMap = null;
}
exportCache.set(path, exportMap);
return exportMap;
}
}, {
key: 'parse',
value: function parse(path, context) {
var m = new ExportMap(context);
try {
var ast = (0, _parse3.default)(path, context);
} catch (err) {
m.errors.push(err);
return m; // can't continue
}
ast.body.forEach(function (n) {
m.captureDefault(n);
m.captureAll(n, path);
m.captureNamedDeclaration(n, path);
});
return m;
}
}]);
return ExportMap;
}();
/**
* Traverse a patter/identifier node, calling 'callback'
* for each leaf identifier.
* @param {node} pattern
* @param {Function} callback
* @return {void}
*/
exports.default = ExportMap;
function recursivePatternCapture(pattern, callback) {
switch (pattern.type) {
case 'Identifier':
// base case
callback(pattern);
break;
case 'ObjectPattern':
pattern.properties.forEach(function (_ref) {
var value = _ref.value;
recursivePatternCapture(value, callback);
});
break;
case 'ArrayPattern':
pattern.elements.forEach(function (element) {
if (element == null) return;
recursivePatternCapture(element, callback);
});
break;
}
}
function hashObject(object) {
var settingsShasum = (0, _crypto.createHash)('sha1');
settingsShasum.update((0, _stringify2.default)(object));
return settingsShasum.digest('hex');
}
//# sourceMappingURL=data:application/json;base64,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QkFBRixDQUEwQixDQUExQixFQUE2QixJQUE3QixFQUg0QjtPQUFiLENBQWpCLENBVjBCOztBQWdCMUIsYUFBTyxDQUFQLENBaEIwQjs7O1NBN0RUOzs7Ozs7Ozs7Ozs7O0FBcUtkLFNBQVMsdUJBQVQsQ0FBaUMsT0FBakMsRUFBMEMsUUFBMUMsRUFBb0Q7QUFDekQsVUFBUSxRQUFRLElBQVI7QUFDTixTQUFLLFlBQUw7O0FBQ0UsZUFBUyxPQUFULEVBREY7QUFFRSxZQUZGOztBQURGLFNBS08sZUFBTDtBQUNFLGNBQVEsVUFBUixDQUFtQixPQUFuQixDQUEyQixnQkFBZTtZQUFaLG1CQUFZOztBQUN4QyxnQ0FBd0IsS0FBeEIsRUFBK0IsUUFBL0IsRUFEd0M7T0FBZixDQUEzQixDQURGO0FBSUUsWUFKRjs7QUFMRixTQVdPLGNBQUw7QUFDRSxjQUFRLFFBQVIsQ0FBaUIsT0FBakIsQ0FBeUIsVUFBQyxPQUFELEVBQWE7QUFDcEMsWUFBSSxXQUFXLElBQVgsRUFBaUIsT0FBckI7QUFDQSxnQ0FBd0IsT0FBeEIsRUFBaUMsUUFBakMsRUFGb0M7T0FBYixDQUF6QixDQURGO0FBS0UsWUFMRjtBQVhGLEdBRHlEO0NBQXBEOztBQXFCUCxTQUFTLFVBQVQsQ0FBb0IsTUFBcEIsRUFBNEI7QUFDMUIsTUFBTSxpQkFBaUIsd0JBQVcsTUFBWCxDQUFqQixDQURvQjtBQUUxQixpQkFBZSxNQUFmLENBQXNCLHlCQUFlLE1BQWYsQ0FBdEIsRUFGMEI7QUFHMUIsU0FBTyxlQUFlLE1BQWYsQ0FBc0IsS0FBdEIsQ0FBUCxDQUgwQjtDQUE1QiIsImZpbGUiOiJjb3JlL2dldEV4cG9ydHMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tICdmcydcblxuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0bydcblxuaW1wb3J0IHBhcnNlIGZyb20gJy4vcGFyc2UnXG5pbXBvcnQgcmVzb2x2ZSBmcm9tICcuL3Jlc29sdmUnXG5pbXBvcnQgaXNJZ25vcmVkIGZyb20gJy4vaWdub3JlJ1xuXG4vLyBtYXAgZnJvbSBzZXR0aW5ncyBzaGExID0+IHBhdGggPT4gZXhwb3J0IG1hcCBvYmplY3RzXG5jb25zdCBleHBvcnRDYWNoZXMgPSBuZXcgTWFwKClcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRXhwb3J0TWFwIHtcbiAgY29uc3RydWN0b3IoY29udGV4dCkge1xuICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHRcbiAgICB0aGlzLm5hbWVkID0gbmV3IFNldCgpXG5cbiAgICB0aGlzLmVycm9ycyA9IFtdXG4gIH1cblxuICBnZXQgc2V0dGluZ3MoKSB7IHJldHVybiB0aGlzLmNvbnRleHQgJiYgdGhpcy5jb250ZXh0LnNldHRpbmdzIH1cblxuICBnZXQgaGFzRGVmYXVsdCgpIHsgcmV0dXJuIHRoaXMubmFtZWQuaGFzKCdkZWZhdWx0JykgfVxuICBnZXQgaGFzTmFtZWQoKSB7IHJldHVybiB0aGlzLm5hbWVkLnNpemUgPiAodGhpcy5oYXNEZWZhdWx0ID8gMSA6IDApIH1cblxuICBzdGF0aWMgZ2V0KHNvdXJjZSwgY29udGV4dCkge1xuXG4gICAgdmFyIHBhdGggPSByZXNvbHZlKHNvdXJjZSwgY29udGV4dClcbiAgICBpZiAocGF0aCA9PSBudWxsKSByZXR1cm4gbnVsbFxuXG4gICAgcmV0dXJuIEV4cG9ydE1hcC5mb3IocGF0aCwgY29udGV4dClcbiAgfVxuXG4gIHN0YXRpYyBmb3IocGF0aCwgY29udGV4dCkge1xuICAgIGxldCBleHBvcnRNYXBcblxuICAgIGNvbnN0IGNhY2hlS2V5ID0gaGFzaE9iamVjdCh7XG4gICAgICBzZXR0aW5nczogY29udGV4dC5zZXR0aW5ncyxcbiAgICAgIHBhcnNlclBhdGg6IGNvbnRleHQucGFyc2VyUGF0aCxcbiAgICAgIHBhcnNlck9wdGlvbnM6IGNvbnRleHQucGFyc2VyT3B0aW9ucyxcbiAgICB9KVxuICAgIGxldCBleHBvcnRDYWNoZSA9IGV4cG9ydENhY2hlcy5nZXQoY2FjaGVLZXkpXG4gICAgaWYgKGV4cG9ydENhY2hlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGV4cG9ydENhY2hlID0gbmV3IE1hcCgpXG4gICAgICBleHBvcnRDYWNoZXMuc2V0KGNhY2hlS2V5LCBleHBvcnRDYWNoZSlcbiAgICB9XG5cbiAgICBleHBvcnRNYXAgPSBleHBvcnRDYWNoZS5nZXQocGF0aClcbiAgICAvLyByZXR1cm4gY2FjaGVkIGlnbm9yZVxuICAgIGlmIChleHBvcnRNYXAgPT09IG51bGwpIHJldHVybiBudWxsXG5cbiAgICBjb25zdCBzdGF0cyA9IGZzLnN0YXRTeW5jKHBhdGgpXG4gICAgaWYgKGV4cG9ydE1hcCAhPSBudWxsKSB7XG4gICAgICAvLyBkYXRlIGVxdWFsaXR5IGNoZWNrXG4gICAgICBpZiAoZXhwb3J0TWFwLm10aW1lIC0gc3RhdHMubXRpbWUgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIGV4cG9ydE1hcFxuICAgICAgfVxuICAgICAgLy8gZnV0dXJlOiBjaGVjayBjb250ZW50IGVxdWFsaXR5P1xuICAgIH1cblxuICAgIGV4cG9ydE1hcCA9IEV4cG9ydE1hcC5wYXJzZShwYXRoLCBjb250ZXh0KVxuICAgIGV4cG9ydE1hcC5tdGltZSA9IHN0YXRzLm10aW1lXG5cbiAgICAvLyBpZ25vcmUgZW1wdGllcywgb3B0aW9uYWxseVxuICAgIGlmIChleHBvcnRNYXAubmFtZWQuc2l6ZSA9PT0gMCAmJiBpc0lnbm9yZWQocGF0aCwgY29udGV4dCkpIHtcbiAgICAgIGV4cG9ydE1hcCA9IG51bGxcbiAgICB9XG5cbiAgICBleHBvcnRDYWNoZS5zZXQocGF0aCwgZXhwb3J0TWFwKVxuXG4gICAgcmV0dXJuIGV4cG9ydE1hcFxuICB9XG5cbiAgc3RhdGljIHBhcnNlKHBhdGgsIGNvbnRleHQpIHtcbiAgICB2YXIgbSA9IG5ldyBFeHBvcnRNYXAoY29udGV4dClcblxuICAgIHRyeSB7XG4gICAgICB2YXIgYXN0ID0gcGFyc2UocGF0aCwgY29udGV4dClcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIG0uZXJyb3JzLnB1c2goZXJyKVxuICAgICAgcmV0dXJuIG0gLy8gY2FuJ3QgY29udGludWVcbiAgICB9XG5cbiAgICBhc3QuYm9keS5mb3JFYWNoKGZ1bmN0aW9uIChuKSB7XG4gICAgICBtLmNhcHR1cmVEZWZhdWx0KG4pXG4gICAgICBtLmNhcHR1cmVBbGwobiwgcGF0aClcbiAgICAgIG0uY2FwdHVyZU5hbWVkRGVjbGFyYXRpb24obiwgcGF0aClcbiAgICB9KVxuXG4gICAgcmV0dXJuIG1cbiAgfVxuXG4gIHJlc29sdmVSZUV4cG9ydChub2RlLCBiYXNlKSB7XG4gICAgdmFyIHJlbW90ZVBhdGggPSByZXNvbHZlLnJlbGF0aXZlKG5vZGUuc291cmNlLnZhbHVlLCBiYXNlLCB0aGlzLnNldHRpbmdzKVxuICAgIGlmIChyZW1vdGVQYXRoID09IG51bGwpIHJldHVybiBudWxsXG5cbiAgICByZXR1cm4gRXhwb3J0TWFwLmZvcihyZW1vdGVQYXRoLCB0aGlzLmNvbnRleHQpXG4gIH1cblxuICBjYXB0dXJlRGVmYXVsdChuKSB7XG4gICAgaWYgKG4udHlwZSAhPT0gJ0V4cG9ydERlZmF1bHREZWNsYXJhdGlvbicpIHJldHVyblxuICAgIHRoaXMubmFtZWQuYWRkKCdkZWZhdWx0JylcbiAgfVxuXG4gIC8qKlxuICAgKiBjYXB0dXJlIGFsbCBuYW1lZCBleHBvcnRzIGZyb20gcmVtb3RlIG1vZHVsZS5cbiAgICpcbiAgICogcmV0dXJucyBudWxsIGlmIHRoaXMgbm9kZSB3YXNuJ3QgYW4gRXhwb3J0QWxsRGVjbGFyYXRpb25cbiAgICogcmV0dXJucyBmYWxzZSBpZiBpdCB3YXMgbm90IHJlc29sdmVkXG4gICAqIHJldHVybnMgdHJ1ZSBpZiBpdCB3YXMgcmVzb2x2ZWQgKyBwYXJzZWRcbiAgICpcbiAgICogQHBhcmFtICB7bm9kZX0gblxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHBhdGggLSB0aGUgcGF0aCBvZiB0aGUgbW9kdWxlIGN1cnJlbnRseSBwYXJzaW5nXG4gICAqIEByZXR1cm4ge2Jvb2xlYW4/fVxuICAgKi9cbiAgY2FwdHVyZUFsbChuLCBwYXRoKSB7XG4gICAgaWYgKG4udHlwZSAhPT0gJ0V4cG9ydEFsbERlY2xhcmF0aW9uJykgcmV0dXJuIG51bGxcblxuICAgIHZhciByZW1vdGVNYXAgPSB0aGlzLnJlc29sdmVSZUV4cG9ydChuLCBwYXRoKVxuICAgIGlmIChyZW1vdGVNYXAgPT0gbnVsbCkgcmV0dXJuIGZhbHNlXG5cbiAgICByZW1vdGVNYXAubmFtZWQuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkgeyB0aGlzLm5hbWVkLmFkZChuYW1lKSB9LmJpbmQodGhpcykpXG5cbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgY2FwdHVyZU5hbWVkRGVjbGFyYXRpb24obiwgcGF0aCkge1xuICAgIGlmIChuLnR5cGUgIT09ICdFeHBvcnROYW1lZERlY2xhcmF0aW9uJykgcmV0dXJuXG5cbiAgICAvLyBjYXB0dXJlIGRlY2xhcmF0aW9uXG4gICAgaWYgKG4uZGVjbGFyYXRpb24gIT0gbnVsbCkge1xuICAgICAgc3dpdGNoIChuLmRlY2xhcmF0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnRnVuY3Rpb25EZWNsYXJhdGlvbic6XG4gICAgICAgIGNhc2UgJ0NsYXNzRGVjbGFyYXRpb24nOlxuICAgICAgICBjYXNlICdUeXBlQWxpYXMnOiAvLyBmbG93dHlwZSB3aXRoIGJhYmVsLWVzbGludCBwYXJzZXJcbiAgICAgICAgICB0aGlzLm5hbWVkLmFkZChuLmRlY2xhcmF0aW9uLmlkLm5hbWUpXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAnVmFyaWFibGVEZWNsYXJhdGlvbic6XG4gICAgICAgICAgbi5kZWNsYXJhdGlvbi5kZWNsYXJhdGlvbnMuZm9yRWFjaCgoZCkgPT5cbiAgICAgICAgICAgIHJlY3Vyc2l2ZVBhdHRlcm5DYXB0dXJlKGQuaWQsIGlkID0+IHRoaXMubmFtZWQuYWRkKGlkLm5hbWUpKSlcbiAgICAgICAgICBicmVha1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNhcHR1cmUgc3BlY2lmaWVyc1xuICAgIGxldCByZW1vdGVNYXBcbiAgICBpZiAobi5zb3VyY2UpIHJlbW90ZU1hcCA9IHRoaXMucmVzb2x2ZVJlRXhwb3J0KG4sIHBhdGgpXG5cbiAgICBuLnNwZWNpZmllcnMuZm9yRWFjaChmdW5jdGlvbiAocykge1xuICAgICAgaWYgKHMudHlwZSA9PT0gJ0V4cG9ydERlZmF1bHRTcGVjaWZpZXInKSB7XG4gICAgICAgIC8vIGRvbid0IGFkZCBpdCBpZiBpdCBpcyBub3QgcHJlc2VudCBpbiB0aGUgZXhwb3J0ZWQgbW9kdWxlXG4gICAgICAgIGlmICghcmVtb3RlTWFwIHx8ICFyZW1vdGVNYXAuaGFzRGVmYXVsdCkgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIHRoaXMubmFtZWQuYWRkKHMuZXhwb3J0ZWQubmFtZSlcbiAgICB9LmJpbmQodGhpcykpXG4gIH1cblxuICByZXBvcnRFcnJvcnMoY29udGV4dCwgZGVjbGFyYXRpb24pIHtcbiAgICBjb250ZXh0LnJlcG9ydCh7XG4gICAgICBub2RlOiBkZWNsYXJhdGlvbi5zb3VyY2UsXG4gICAgICBtZXNzYWdlOiBgUGFyc2UgZXJyb3JzIGluIGltcG9ydGVkIG1vZHVsZSAnJHtkZWNsYXJhdGlvbi5zb3VyY2UudmFsdWV9JzogYCArXG4gICAgICAgICAgICAgICAgICBgJHt0aGlzLmVycm9yc1xuICAgICAgICAgICAgICAgICAgICAgICAgLm1hcChlID0+IGAke2UubWVzc2FnZX0gKCR7ZS5saW5lTnVtYmVyfToke2UuY29sdW1ufSlgKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmpvaW4oJywgJyl9YCxcbiAgICB9KVxuICB9XG59XG5cblxuLyoqXG4gKiBUcmF2ZXJzZSBhIHBhdHRlci9pZGVudGlmaWVyIG5vZGUsIGNhbGxpbmcgJ2NhbGxiYWNrJ1xuICogZm9yIGVhY2ggbGVhZiBpZGVudGlmaWVyLlxuICogQHBhcmFtICB7bm9kZX0gICBwYXR0ZXJuXG4gKiBAcGFyYW0gIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWN1cnNpdmVQYXR0ZXJuQ2FwdHVyZShwYXR0ZXJuLCBjYWxsYmFjaykge1xuICBzd2l0Y2ggKHBhdHRlcm4udHlwZSkge1xuICAgIGNhc2UgJ0lkZW50aWZpZXInOiAvLyBiYXNlIGNhc2VcbiAgICAgIGNhbGxiYWNrKHBhdHRlcm4pXG4gICAgICBicmVha1xuXG4gICAgY2FzZSAnT2JqZWN0UGF0dGVybic6XG4gICAgICBwYXR0ZXJuLnByb3BlcnRpZXMuZm9yRWFjaCgoeyB2YWx1ZSB9KSA9PiB7XG4gICAgICAgIHJlY3Vyc2l2ZVBhdHRlcm5DYXB0dXJlKHZhbHVlLCBjYWxsYmFjaylcbiAgICAgIH0pXG4gICAgICBicmVha1xuXG4gICAgY2FzZSAnQXJyYXlQYXR0ZXJuJzpcbiAgICAgIHBhdHRlcm4uZWxlbWVudHMuZm9yRWFjaCgoZWxlbWVudCkgPT4ge1xuICAgICAgICBpZiAoZWxlbWVudCA9PSBudWxsKSByZXR1cm5cbiAgICAgICAgcmVjdXJzaXZlUGF0dGVybkNhcHR1cmUoZWxlbWVudCwgY2FsbGJhY2spXG4gICAgICB9KVxuICAgICAgYnJlYWtcbiAgfVxufVxuXG5mdW5jdGlvbiBoYXNoT2JqZWN0KG9iamVjdCkge1xuICBjb25zdCBzZXR0aW5nc1NoYXN1bSA9IGNyZWF0ZUhhc2goJ3NoYTEnKVxuICBzZXR0aW5nc1NoYXN1bS51cGRhdGUoSlNPTi5zdHJpbmdpZnkob2JqZWN0KSlcbiAgcmV0dXJuIHNldHRpbmdzU2hhc3VtLmRpZ2VzdCgnaGV4Jylcbn1cbiJdfQ==