UNPKG

electron-compile

Version:

Electron supporting package to compile JS and CSS in Electron applications

245 lines (196 loc) 24.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.rigHtmlDocumentToInitializeElectronCompile = rigHtmlDocumentToInitializeElectronCompile; exports.addBypassChecker = addBypassChecker; exports.initializeProtocolHook = initializeProtocolHook; var _url = require('url'); var _url2 = _interopRequireDefault(_url); var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs); var _mimeTypes = require('@paulcbetts/mime-types'); var _mimeTypes2 = _interopRequireDefault(_mimeTypes); var _lruCache = require('lru-cache'); var _lruCache2 = _interopRequireDefault(_lruCache); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } const magicWords = "__magic__file__to__help__electron__compile.js"; // NB: These are duped in initialize-renderer so we can save startup time, make // sure to run both! const magicGlobalForRootCacheDir = '__electron_compile_root_cache_dir'; const magicGlobalForAppRootDir = '__electron_compile_app_root_dir'; const d = require('debug')('electron-compile:protocol-hook'); let protocol = null; const mapStatCache = new _lruCache2.default({ length: 512 }); function doesMapFileExist(filePath) { let ret = mapStatCache.get(filePath); if (ret !== undefined) return Promise.resolve(ret); return new Promise(res => { _fs2.default.lstat(filePath, (err, s) => { let failed = err || !s; mapStatCache.set(filePath, !failed); res(!failed); }); }); } /** * Adds our script header to the top of all HTML files * * @private */ function rigHtmlDocumentToInitializeElectronCompile(doc) { let lines = doc.split("\n"); let replacement = `<head><script src="${magicWords}"></script>`; let replacedHead = false; for (let i = 0; i < lines.length; i++) { if (!lines[i].match(/<head>/i)) continue; lines[i] = lines[i].replace(/<head>/i, replacement); replacedHead = true; break; } if (!replacedHead) { replacement = `<html$1><head><script src="${magicWords}"></script></head>`; for (let i = 0; i < lines.length; i++) { if (!lines[i].match(/<html/i)) continue; lines[i] = lines[i].replace(/<html([^>]+)>/i, replacement); break; } } return lines.join("\n"); } function requestFileJob(filePath, finish) { _fs2.default.readFile(filePath, (err, buf) => { if (err) { if (err.errno === 34) { finish(-6); // net::ERR_FILE_NOT_FOUND return; } else { finish(-2); // net::FAILED return; } } finish({ data: buf, mimeType: _mimeTypes2.default.lookup(filePath) || 'text/plain' }); }); } const bypassCheckers = []; /** * Adds a function that will be called on electron-compile's protocol hook * used to intercept file requests. Use this to bypass electron-compile * entirely for certain URI's. * * @param {Function} bypassChecker Function that will be called with the file path to determine whether to bypass or not */ function addBypassChecker(bypassChecker) { bypassCheckers.push(bypassChecker); } /** * Initializes the protocol hook on file: that allows us to intercept files * loaded by Chromium and rewrite them. This method along with * {@link registerRequireExtension} are the top-level methods that electron-compile * actually uses to intercept code that Electron loads. * * @param {CompilerHost} compilerHost The compiler host to use for compilation. */ function initializeProtocolHook(compilerHost) { protocol = protocol || require('electron').protocol; global[magicGlobalForRootCacheDir] = compilerHost.rootCacheDir; global[magicGlobalForAppRootDir] = compilerHost.appRoot; const electronCompileSetupCode = `if (window.require) require('electron-compile/lib/initialize-renderer').initializeRendererProcess(${compilerHost.readOnlyMode});`; protocol.interceptBufferProtocol('file', (() => { var _ref = _asyncToGenerator(function* (request, finish) { let uri = _url2.default.parse(request.url); d(`Intercepting url ${request.url}`); if (request.url.indexOf(magicWords) > -1) { finish({ mimeType: 'application/javascript', data: new Buffer(electronCompileSetupCode, 'utf8') }); return; } // This is a protocol-relative URL that has gone pear-shaped in Electron, // let's rewrite it if (uri.host && uri.host.length > 1) { //let newUri = request.url.replace(/^file:/, "https:"); // TODO: Jump off this bridge later d(`TODO: Found bogus protocol-relative URL, can't fix it up!!`); finish(-2); return; } let filePath = decodeURIComponent(uri.pathname); // NB: pathname has a leading '/' on Win32 for some reason if (process.platform === 'win32') { filePath = filePath.slice(1); } // NB: Special-case files coming from atom.asar or node_modules if (filePath.match(/[\/\\](atom|electron).asar/) || filePath.match(/[\/\\](node_modules|bower_components)/)) { // NBs on NBs: If we're loading an HTML file from node_modules, we still have // to do the HTML document rigging if (filePath.match(/\.html?$/i)) { let riggedContents = null; _fs2.default.readFile(filePath, 'utf8', function (err, contents) { if (err) { if (err.errno === 34) { finish(-6); // net::ERR_FILE_NOT_FOUND return; } else { finish(-2); // net::FAILED return; } } riggedContents = rigHtmlDocumentToInitializeElectronCompile(contents); finish({ data: new Buffer(riggedContents), mimeType: 'text/html' }); return; }); return; } requestFileJob(filePath, finish); return; } // NB: Chromium will somehow decide that external source map references // aren't relative to the file that was loaded for node.js modules, but // relative to the HTML file. Since we can't really figure out what the // real path is, we just need to squelch it. if (filePath.match(/\.map$/i) && !(yield doesMapFileExist(filePath))) { finish({ data: new Buffer("", 'utf8'), mimeType: 'text/plain' }); return; } for (const bypassChecker of bypassCheckers) { if (bypassChecker(filePath)) { d('bypassing compilers for:', filePath); requestFileJob(filePath, finish); return; } } try { let result = yield compilerHost.compile(filePath); if (result.mimeType === 'text/html') { result.code = rigHtmlDocumentToInitializeElectronCompile(result.code); } if (result.binaryData || result.code instanceof Buffer) { finish({ data: result.binaryData || result.code, mimeType: result.mimeType }); return; } else { finish({ data: new Buffer(result.code), mimeType: result.mimeType }); return; } } catch (e) { let err = `Failed to compile ${filePath}: ${e.message}\n${e.stack}`; d(err); if (e.errno === 34 /*ENOENT*/) { finish(-6); // net::ERR_FILE_NOT_FOUND return; } finish({ mimeType: 'text/plain', data: new Buffer(err) }); return; } }); return function (_x, _x2) { return _ref.apply(this, arguments); }; })()); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9wcm90b2NvbC1ob29rLmpzIl0sIm5hbWVzIjpbInJpZ0h0bWxEb2N1bWVudFRvSW5pdGlhbGl6ZUVsZWN0cm9uQ29tcGlsZSIsImFkZEJ5cGFzc0NoZWNrZXIiLCJpbml0aWFsaXplUHJvdG9jb2xIb29rIiwibWFnaWNXb3JkcyIsIm1hZ2ljR2xvYmFsRm9yUm9vdENhY2hlRGlyIiwibWFnaWNHbG9iYWxGb3JBcHBSb290RGlyIiwiZCIsInJlcXVpcmUiLCJwcm90b2NvbCIsIm1hcFN0YXRDYWNoZSIsIkxSVSIsImxlbmd0aCIsImRvZXNNYXBGaWxlRXhpc3QiLCJmaWxlUGF0aCIsInJldCIsImdldCIsInVuZGVmaW5lZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVzIiwiZnMiLCJsc3RhdCIsImVyciIsInMiLCJmYWlsZWQiLCJzZXQiLCJkb2MiLCJsaW5lcyIsInNwbGl0IiwicmVwbGFjZW1lbnQiLCJyZXBsYWNlZEhlYWQiLCJpIiwibWF0Y2giLCJyZXBsYWNlIiwiam9pbiIsInJlcXVlc3RGaWxlSm9iIiwiZmluaXNoIiwicmVhZEZpbGUiLCJidWYiLCJlcnJubyIsImRhdGEiLCJtaW1lVHlwZSIsIm1pbWUiLCJsb29rdXAiLCJieXBhc3NDaGVja2VycyIsImJ5cGFzc0NoZWNrZXIiLCJwdXNoIiwiY29tcGlsZXJIb3N0IiwiZ2xvYmFsIiwicm9vdENhY2hlRGlyIiwiYXBwUm9vdCIsImVsZWN0cm9uQ29tcGlsZVNldHVwQ29kZSIsInJlYWRPbmx5TW9kZSIsImludGVyY2VwdEJ1ZmZlclByb3RvY29sIiwicmVxdWVzdCIsInVyaSIsInVybCIsInBhcnNlIiwiaW5kZXhPZiIsIkJ1ZmZlciIsImhvc3QiLCJkZWNvZGVVUklDb21wb25lbnQiLCJwYXRobmFtZSIsInByb2Nlc3MiLCJwbGF0Zm9ybSIsInNsaWNlIiwicmlnZ2VkQ29udGVudHMiLCJjb250ZW50cyIsInJlc3VsdCIsImNvbXBpbGUiLCJjb2RlIiwiYmluYXJ5RGF0YSIsImUi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QTtBQUFBO0FBQUE7QUF1R0QiLCJmaWxlIjoicHJvdG9jb2wtaG9vay5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB1cmwgZnJvbSAndXJsJztcbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgbWltZSBmcm9tICdAcGF1bGNiZXR0cy9taW1lLXR5cGVzJztcbmltcG9ydCBMUlUgZnJvbSAnbHJ1LWNhY2hlJztcblxuY29uc3QgbWFnaWNXb3JkcyA9IFwiX19tYWdpY19fZmlsZV9fdG9fX2hlbHBfX2VsZWN0cm9uX19jb21waWxlLmpzXCI7XG5cbi8vIE5COiBUaGVzZSBhcmUgZHVwZWQgaW4gaW5pdGlhbGl6ZS1yZW5kZXJlciBzbyB3ZSBjYW4gc2F2ZSBzdGFydHVwIHRpbWUsIG1ha2Vcbi8vIHN1cmUgdG8gcnVuIGJvdGghXG5jb25zdCBtYWdpY0dsb2JhbEZvclJvb3RDYWNoZURpciA9ICdfX2VsZWN0cm9uX2NvbXBpbGVfcm9vdF9jYWNoZV9kaXInO1xuY29uc3QgbWFnaWNHbG9iYWxGb3JBcHBSb290RGlyID0gJ19fZWxlY3Ryb25fY29tcGlsZV9hcHBfcm9vdF9kaXInO1xuXG5jb25zdCBkID0gcmVxdWlyZSgnZGVidWcnKSgnZWxlY3Ryb24tY29tcGlsZTpwcm90b2NvbC1ob29rJyk7XG5cbmxldCBwcm90b2NvbCA9IG51bGw7XG5cbmNvbnN0IG1hcFN0YXRDYWNoZSA9IG5ldyBMUlUoe2xlbmd0aDogNTEyfSk7XG5mdW5jdGlvbiBkb2VzTWFwRmlsZUV4aXN0KGZpbGVQYXRoKSB7XG4gIGxldCByZXQgPSBtYXBTdGF0Q2FjaGUuZ2V0KGZpbGVQYXRoKTtcbiAgaWYgKHJldCAhPT0gdW5kZWZpbmVkKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJldCk7XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXMpID0+IHtcbiAgICBmcy5sc3RhdChmaWxlUGF0aCwgKGVyciwgcykgPT4ge1xuICAgICAgbGV0IGZhaWxlZCA9IChlcnIgfHwgIXMpO1xuXG4gICAgICBtYXBTdGF0Q2FjaGUuc2V0KGZpbGVQYXRoLCAhZmFpbGVkKTtcbiAgICAgIHJlcyghZmFpbGVkKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbi8qKlxuICogQWRkcyBvdXIgc2NyaXB0IGhlYWRlciB0byB0aGUgdG9wIG9mIGFsbCBIVE1MIGZpbGVzXG4gKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJpZ0h0bWxEb2N1bWVudFRvSW5pdGlhbGl6ZUVsZWN0cm9uQ29tcGlsZShkb2MpIHtcbiAgbGV0IGxpbmVzID0gZG9jLnNwbGl0KFwiXFxuXCIpO1xuICBsZXQgcmVwbGFjZW1lbnQgPSBgPGhlYWQ+PHNjcmlwdCBzcmM9XCIke21hZ2ljV29yZHN9XCI+PC9zY3JpcHQ+YDtcbiAgbGV0IHJlcGxhY2VkSGVhZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGk9MDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFsaW5lc1tpXS5tYXRjaCgvPGhlYWQ+L2kpKSBjb250aW51ZTtcblxuICAgIGxpbmVzW2ldID0gKGxpbmVzW2ldKS5yZXBsYWNlKC88aGVhZD4vaSwgcmVwbGFjZW1lbnQpO1xuICAgIHJlcGxhY2VkSGVhZCA9IHRydWU7XG4gICAgYnJlYWs7XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkSGVhZCkge1xuICAgIHJlcGxhY2VtZW50ID0gYDxodG1sJDE+PGhlYWQ+PHNjcmlwdCBzcmM9XCIke21hZ2ljV29yZHN9XCI+PC9zY3JpcHQ+PC9oZWFkPmA7XG4gICAgZm9yIChsZXQgaT0wOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICghbGluZXNbaV0ubWF0Y2goLzxodG1sL2kpKSBjb250aW51ZTtcblxuICAgICAgbGluZXNbaV0gPSAobGluZXNbaV0pLnJlcGxhY2UoLzxodG1sKFtePl0rKT4vaSwgcmVwbGFjZW1lbnQpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGxpbmVzLmpvaW4oXCJcXG5cIik7XG59XG5cbmZ1bmN0aW9uIHJlcXVlc3RGaWxlSm9iKGZpbGVQYXRoLCBmaW5pc2gpIHtcbiAgZnMucmVhZEZpbGUoZmlsZVBhdGgsIChlcnIsIGJ1ZikgPT4ge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGlmIChlcnIuZXJybm8gPT09IDM0KSB7XG4gICAgICAgIGZpbmlzaCgtNik7IC8vIG5ldDo6RVJSX0ZJTEVfTk9UX0ZPVU5EXG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZpbmlzaCgtMik7IC8vIG5ldDo6RkFJTEVEXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmaW5pc2goe1xuICAgICAgZGF0YTogYnVmLFxuICAgICAgbWltZVR5cGU6IG1pbWUubG9va3VwKGZpbGVQYXRoKSB8fCAndGV4dC9wbGFpbidcbiAgICB9KTtcbiAgfSk7XG59XG5cbmNvbnN0IGJ5cGFzc0NoZWNrZXJzID0gW107XG5cbi8qKlxuICogQWRkcyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBjYWxsZWQgb24gZWxlY3Ryb24tY29tcGlsZSdzIHByb3RvY29sIGhvb2tcbiAqIHVzZWQgdG8gaW50ZXJjZXB0IGZpbGUgcmVxdWVzdHMuICBVc2UgdGhpcyB0byBieXBhc3MgZWxlY3Ryb24tY29tcGlsZVxuICogZW50aXJlbHkgZm9yIGNlcnRhaW4gVVJJJ3MuXG4gKiBcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGJ5cGFzc0NoZWNrZXIgRnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCB3aXRoIHRoZSBmaWxlIHBhdGggdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdG8gYnlwYXNzIG9yIG5vdFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWRkQnlwYXNzQ2hlY2tlcihieXBhc3NDaGVja2VyKSB7XG4gIGJ5cGFzc0NoZWNrZXJzLnB1c2goYnlwYXNzQ2hlY2tlcik7XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZXMgdGhlIHByb3RvY29sIGhvb2sgb24gZmlsZTogdGhhdCBhbGxvd3MgdXMgdG8gaW50ZXJjZXB0IGZpbGVzXG4gKiBsb2FkZWQgYnkgQ2hyb21pdW0gYW5kIHJld3JpdGUgdGhlbS4gVGhpcyBtZXRob2QgYWxvbmcgd2l0aFxuICoge0BsaW5rIHJlZ2lzdGVyUmVxdWlyZUV4dGVuc2lvbn0gYXJlIHRoZSB0b3AtbGV2ZWwgbWV0aG9kcyB0aGF0IGVsZWN0cm9uLWNvbXBpbGVcbiAqIGFjdHVhbGx5IHVzZXMgdG8gaW50ZXJjZXB0IGNvZGUgdGhhdCBFbGVjdHJvbiBsb2Fkcy5cbiAqXG4gKiBAcGFyYW0gIHtDb21waWxlckhvc3R9IGNvbXBpbGVySG9zdCAgVGhlIGNvbXBpbGVyIGhvc3QgdG8gdXNlIGZvciBjb21waWxhdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVQcm90b2NvbEhvb2soY29tcGlsZXJIb3N0KSB7XG4gIHByb3RvY29sID0gcHJvdG9jb2wgfHwgcmVxdWlyZSgnZWxlY3Ryb24nKS5wcm90b2NvbDtcblxuICBnbG9iYWxbbWFnaWNHbG9iYWxGb3JSb290Q2FjaGVEaXJdID0gY29tcGlsZXJIb3N0LnJvb3RDYWNoZURpcjtcbiAgZ2xvYmFsW21hZ2ljR2xvYmFsRm9yQXBwUm9vdERpcl0gPSBjb21waWxlckhvc3QuYXBwUm9vdDtcblxuICBjb25zdCBlbGVjdHJvbkNvbXBpbGVTZXR1cENvZGUgPSBgaWYgKHdpbmRvdy5yZXF1aXJlKSByZXF1aXJlKCdlbGVjdHJvbi1jb21waWxlL2xpYi9pbml0aWFsaXplLXJlbmRlcmVyJykuaW5pdGlhbGl6ZVJlbmRlcmVyUHJvY2Vzcygke2NvbXBpbGVySG9zdC5yZWFkT25seU1vZGV9KTtgO1xuXG4gIHByb3RvY29sLmludGVyY2VwdEJ1ZmZlclByb3RvY29sKCdmaWxlJywgYXN5bmMgZnVuY3Rpb24ocmVxdWVzdCwgZmluaXNoKSB7XG4gICAgbGV0IHVyaSA9IHVybC5wYXJzZShyZXF1ZXN0LnVybCk7XG5cbiAgICBkKGBJbnRlcmNlcHRpbmcgdXJsICR7cmVxdWVzdC51cmx9YCk7XG4gICAgaWYgKHJlcXVlc3QudXJsLmluZGV4T2YobWFnaWNXb3JkcykgPiAtMSkge1xuICAgICAgZmluaXNoKHtcbiAgICAgICAgbWltZVR5cGU6ICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0JyxcbiAgICAgICAgZGF0YTogbmV3IEJ1ZmZlcihlbGVjdHJvbkNvbXBpbGVTZXR1cENvZGUsICd1dGY4JylcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVGhpcyBpcyBhIHByb3RvY29sLXJlbGF0aXZlIFVSTCB0aGF0IGhhcyBnb25lIHBlYXItc2hhcGVkIGluIEVsZWN0cm9uLFxuICAgIC8vIGxldCdzIHJld3JpdGUgaXRcbiAgICBpZiAodXJpLmhvc3QgJiYgdXJpLmhvc3QubGVuZ3RoID4gMSkge1xuICAgICAgLy9sZXQgbmV3VXJpID0gcmVxdWVzdC51cmwucmVwbGFjZSgvXmZpbGU6LywgXCJodHRwczpcIik7XG4gICAgICAvLyBUT0RPOiBKdW1wIG9mZiB0aGlzIGJyaWRnZSBsYXRlclxuICAgICAgZChgVE9ETzogRm91bmQgYm9ndXMgcHJvdG9jb2wtcmVsYXRpdmUgVVJMLCBjYW4ndCBmaXggaXQgdXAhIWApO1xuICAgICAgZmluaXNoKC0yKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgZmlsZVBhdGggPSBkZWNvZGVVUklDb21wb25lbnQodXJpLnBhdGhuYW1lKTtcblxuICAgIC8vIE5COiBwYXRobmFtZSBoYXMgYSBsZWFkaW5nICcvJyBvbiBXaW4zMiBmb3Igc29tZSByZWFzb25cbiAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xuICAgICAgZmlsZVBhdGggPSBmaWxlUGF0aC5zbGljZSgxKTtcbiAgICB9XG5cbiAgICAvLyBOQjogU3BlY2lhbC1jYXNlIGZpbGVzIGNvbWluZyBmcm9tIGF0b20uYXNhciBvciBub2RlX21vZHVsZXNcbiAgICBpZiAoZmlsZVBhdGgubWF0Y2goL1tcXC9cXFxcXShhdG9tfGVsZWN0cm9uKS5hc2FyLykgfHwgZmlsZVBhdGgubWF0Y2goL1tcXC9cXFxcXShub2RlX21vZHVsZXN8Ym93ZXJfY29tcG9uZW50cykvKSkge1xuICAgICAgLy8gTkJzIG9uIE5CczogSWYgd2UncmUgbG9hZGluZyBhbiBIVE1MIGZpbGUgZnJvbSBub2RlX21vZHVsZXMsIHdlIHN0aWxsIGhhdmVcbiAgICAgIC8vIHRvIGRvIHRoZSBIVE1MIGRvY3VtZW50IHJpZ2dpbmdcbiAgICAgIGlmIChmaWxlUGF0aC5tYXRjaCgvXFwuaHRtbD8kL2kpKSB7XG4gICAgICAgIGxldCByaWdnZWRDb250ZW50cyA9IG51bGw7XG4gICAgICAgIGZzLnJlYWRGaWxlKGZpbGVQYXRoLCAndXRmOCcsIChlcnIsIGNvbnRlbnRzKSA9PiB7XG4gICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgaWYgKGVyci5lcnJubyA9PT0gMzQpIHtcbiAgICAgICAgICAgICAgZmluaXNoKC02KTsgLy8gbmV0OjpFUlJfRklMRV9OT1RfRk9VTkRcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZmluaXNoKC0yKTsgLy8gbmV0OjpGQUlMRURcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJpZ2dlZENvbnRlbnRzID0gcmlnSHRtbERvY3VtZW50VG9Jbml0aWFsaXplRWxlY3Ryb25Db21waWxlKGNvbnRlbnRzKTtcbiAgICAgICAgICBmaW5pc2goeyBkYXRhOiBuZXcgQnVmZmVyKHJpZ2dlZENvbnRlbnRzKSwgbWltZVR5cGU6ICd0ZXh0L2h0bWwnIH0pO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICByZXF1ZXN0RmlsZUpvYihmaWxlUGF0aCwgZmluaXNoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBOQjogQ2hyb21pdW0gd2lsbCBzb21laG93IGRlY2lkZSB0aGF0IGV4dGVybmFsIHNvdXJjZSBtYXAgcmVmZXJlbmNlc1xuICAgIC8vIGFyZW4ndCByZWxhdGl2ZSB0byB0aGUgZmlsZSB0aGF0IHdhcyBsb2FkZWQgZm9yIG5vZGUuanMgbW9kdWxlcywgYnV0XG4gICAgLy8gcmVsYXRpdmUgdG8gdGhlIEhUTUwgZmlsZS4gU2luY2Ugd2UgY2FuJ3QgcmVhbGx5IGZpZ3VyZSBvdXQgd2hhdCB0aGVcbiAgICAvLyByZWFsIHBhdGggaXMsIHdlIGp1c3QgbmVlZCB0byBzcXVlbGNoIGl0LlxuICAgIGlmIChmaWxlUGF0aC5tYXRjaCgvXFwubWFwJC9pKSAmJiAhKGF3YWl0IGRvZXNNYXBGaWxlRXhpc3QoZmlsZVBhdGgpKSkge1xuICAgICAgZmluaXNoKHsgZGF0YTogbmV3IEJ1ZmZlcihcIlwiLCAndXRmOCcpLCBtaW1lVHlwZTogJ3RleHQvcGxhaW4nIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgYnlwYXNzQ2hlY2tlciBvZiBieXBhc3NDaGVja2Vycykge1xuICAgICAgaWYgKGJ5cGFzc0NoZWNrZXIoZmlsZVBhdGgpKSB7XG4gICAgICAgIGQoJ2J5cGFzc2luZyBjb21waWxlcnMgZm9yOicsIGZpbGVQYXRoKTtcbiAgICAgICAgcmVxdWVzdEZpbGVKb2IoZmlsZVBhdGgsIGZpbmlzaCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgbGV0IHJlc3VsdCA9IGF3YWl0IGNvbXBpbGVySG9zdC5jb21waWxlKGZpbGVQYXRoKTtcblxuICAgICAgaWYgKHJlc3VsdC5taW1lVHlwZSA9PT0gJ3RleHQvaHRtbCcpIHtcbiAgICAgICAgcmVzdWx0LmNvZGUgPSByaWdIdG1sRG9jdW1lbnRUb0luaXRpYWxpemVFbGVjdHJvbkNvbXBpbGUocmVzdWx0LmNvZGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAocmVzdWx0LmJpbmFyeURhdGEgfHwgcmVzdWx0LmNvZGUgaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICAgICAgZmluaXNoKHsgZGF0YTogcmVzdWx0LmJpbmFyeURhdGEgfHwgcmVzdWx0LmNvZGUsIG1pbWVUeXBlOiByZXN1bHQubWltZVR5cGUgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZpbmlzaCh7IGRhdGE6IG5ldyBCdWZmZXIocmVzdWx0LmNvZGUpLCBtaW1lVHlwZTogcmVzdWx0Lm1pbWVUeXBlIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbGV0IGVyciA9IGBGYWlsZWQgdG8gY29tcGlsZSAke2ZpbGVQYXRofTogJHtlLm1lc3NhZ2V9XFxuJHtlLnN0YWNrfWA7XG4gICAgICBkKGVycik7XG5cbiAgICAgIGlmIChlLmVycm5vID09PSAzNCAvKkVOT0VOVCovKSB7XG4gICAgICAgIGZpbmlzaCgtNik7IC8vIG5ldDo6RVJSX0ZJTEVfTk9UX0ZPVU5EXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgZmluaXNoKHsgbWltZVR5cGU6ICd0ZXh0L3BsYWluJywgZGF0YTogbmV3IEJ1ZmZlcihlcnIpIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfSk7XG59XG4iXX0=