parse-imports
Version:
A blazing fast ES module imports parser.
205 lines (194 loc) • 23.1 kB
JavaScript
import module, { createRequire } from "node:module";
import { init, parse } from "es-module-lexer";
import assert from "node:assert";
import { removeSlashes } from "slashes";
import { dirname } from "node:path";
//#region src/parse-import-clause/skip.js
const separatorRegex = /^(?:\s+|,)$/u;
const skipSeparators = (imported, i) => {
while (i < imported.length && separatorRegex.test(imported[i])) i++;
return i;
};
const skipNonSeparators = (imported, i) => {
while (i < imported.length && !separatorRegex.test(imported[i])) i++;
return i;
};
//#endregion
//#region src/parse-import-clause/parse-default-import.js
const parseDefaultImport = (importClauseString, i) => {
const startIndex = i;
i = skipNonSeparators(importClauseString, i);
return {
defaultImport: importClauseString.slice(startIndex, i),
i
};
};
var parse_default_import_default = parseDefaultImport;
//#endregion
//#region src/parse-import-clause/parse-named-imports.js
const parseNamedImports = (importClauseString, i) => {
const startIndex = ++i;
while (i < importClauseString.length && importClauseString[i] !== `}`) i++;
const namedImports = importClauseString.slice(startIndex, i++).split(`,`).map((namedImport) => {
namedImport = namedImport.trim();
if (namedImport.includes(` `)) {
const components = namedImport.split(` `);
return {
specifier: components[0],
binding: components.at(-1)
};
}
return {
specifier: namedImport,
binding: namedImport
};
}).filter(({ specifier }) => specifier.length > 0);
return {
namedImports,
i
};
};
var parse_named_imports_default = parseNamedImports;
//#endregion
//#region src/parse-import-clause/parse-namespace-import.js
const parseNamespaceImport = (importClauseString, i) => {
i++;
i = skipSeparators(importClauseString, i);
i += `as`.length;
i = skipSeparators(importClauseString, i);
const startIndex = i;
i = skipNonSeparators(importClauseString, i);
return {
namespaceImport: importClauseString.slice(startIndex, i),
i
};
};
var parse_namespace_import_default = parseNamespaceImport;
//#endregion
//#region src/parse-import-clause/index.js
const parseImportClause = (importClauseString) => {
let defaultImport;
let namespaceImport;
const namedImports = [];
for (let i = 0; i < importClauseString.length; i++) {
if (separatorRegex.test(importClauseString[i])) continue;
if (importClauseString[i] === `{`) {
let newNamedImports;
({namedImports: newNamedImports, i} = parse_named_imports_default(importClauseString, i));
namedImports.push(...newNamedImports);
} else if (importClauseString[i] === `*`) ({namespaceImport, i} = parse_namespace_import_default(importClauseString, i));
else ({defaultImport, i} = parse_default_import_default(importClauseString, i));
}
return {
default: defaultImport,
namespace: namespaceImport,
named: namedImports
};
};
var parse_import_clause_default = parseImportClause;
//#endregion
//#region src/parse-module-specifier/is-constant-string-literal.js
const isConstantStringLiteral = (stringLiteral) => {
const quote = [
`'`,
`"`,
`\``
].find((quoteCandidate) => stringLiteral.startsWith(quoteCandidate) && stringLiteral.endsWith(quoteCandidate));
if (quote == null) return false;
for (let i = 1; i < stringLiteral.length - 1; i++) {
if (stringLiteral[i] === quote && stringLiteral[i - 1] !== `\\`) return false;
if (quote === `\`` && stringLiteral.slice(i, i + 2) === `\${` && stringLiteral[i - 1] !== `\\`) return false;
}
return true;
};
var is_constant_string_literal_default = isConstantStringLiteral;
//#endregion
//#region src/parse-module-specifier/parse-type.js
const builtinModules = new Set(module.builtinModules);
const parseType = (moduleSpecifier) => {
if (moduleSpecifier.length === 0) return `invalid`;
if (moduleSpecifier.startsWith(`/`)) return `absolute`;
if (moduleSpecifier.startsWith(`.`)) return `relative`;
if (builtinModules.has(moduleSpecifier)) return `builtin`;
return `package`;
};
var parse_type_default = parseType;
//#endregion
//#region src/parse-module-specifier/resolve.js
const require = createRequire(import.meta.url);
const resolve = (from, to) => {
try {
return require.resolve(to, { paths: [dirname(from)] });
} catch {
return void 0;
}
};
var resolve_default = resolve;
//#endregion
//#region src/parse-module-specifier/index.js
const parseModuleSpecifier = (moduleSpecifierString, { isDynamicImport, resolveFrom }) => {
assert(isDynamicImport || is_constant_string_literal_default(moduleSpecifierString));
const { isConstant, value } = !isDynamicImport || is_constant_string_literal_default(moduleSpecifierString) ? {
isConstant: true,
value: removeSlashes(moduleSpecifierString.slice(1, -1))
} : {
isConstant: false,
value: void 0
};
return {
type: isConstant ? parse_type_default(value) : `unknown`,
isConstant,
code: moduleSpecifierString,
value,
resolved: typeof resolveFrom === `string` && isConstant ? resolve_default(resolveFrom, value) : void 0
};
};
var parse_module_specifier_default = parseModuleSpecifier;
//#endregion
//#region src/index.js
const wasmLoadPromise = init;
const parseImports = async (code, options) => {
await wasmLoadPromise;
return parseImportsSync(code, options);
};
const parseImportsSync = (code, { resolveFrom } = {}) => {
const result = parse(code, resolveFrom == null ? void 0 : resolveFrom);
if (!Array.isArray(result)) throw new TypeError(`Expected WASM to be loaded before calling parseImportsSync`);
const [imports] = result;
return { *[Symbol.iterator]() {
for (let { d: dynamicImportStartIndex, ss: statementStartIndex, s: moduleSpecifierStartIndex, e: moduleSpecifierEndIndexExclusive } of imports) {
const isImportMeta = dynamicImportStartIndex === -2;
if (isImportMeta) continue;
const isDynamicImport = dynamicImportStartIndex > -1;
if (!isDynamicImport) {
moduleSpecifierStartIndex--;
moduleSpecifierEndIndexExclusive++;
}
const moduleSpecifierString = code.slice(moduleSpecifierStartIndex, moduleSpecifierEndIndexExclusive);
const moduleSpecifier = {
startIndex: moduleSpecifierStartIndex,
endIndex: moduleSpecifierEndIndexExclusive,
...parse_module_specifier_default(moduleSpecifierString, {
isDynamicImport,
resolveFrom
})
};
let importClause;
if (!isDynamicImport) {
let importClauseString = code.slice(statementStartIndex + `import`.length, moduleSpecifierStartIndex).trim();
if (importClauseString.endsWith(`from`)) importClauseString = importClauseString.slice(0, Math.max(0, importClauseString.length - `from`.length));
importClause = parse_import_clause_default(importClauseString);
}
yield {
startIndex: statementStartIndex,
endIndex: isDynamicImport ? moduleSpecifierEndIndexExclusive + 1 : moduleSpecifierEndIndexExclusive,
isDynamicImport,
moduleSpecifier,
importClause
};
}
} };
};
//#endregion
export { parseImports, parseImportsSync, wasmLoadPromise };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJuYW1lcyI6WyJwYXJzZU5hbWVkSW1wb3J0cyIsInBhcnNlTmFtZXNwYWNlSW1wb3J0IiwicGFyc2VEZWZhdWx0SW1wb3J0IiwiaXNDb25zdGFudFN0cmluZ0xpdGVyYWwiLCJwYXJzZVR5cGUiLCJyZXNvbHZlIiwicGFyc2VNb2R1bGVTcGVjaWZpZXIiLCJwYXJzZUltcG9ydENsYXVzZSJdLCJzb3VyY2VzIjpbIi4uL3NyYy9wYXJzZS1pbXBvcnQtY2xhdXNlL3NraXAuanMiLCIuLi9zcmMvcGFyc2UtaW1wb3J0LWNsYXVzZS9wYXJzZS1kZWZhdWx0LWltcG9ydC5qcyIsIi4uL3NyYy9wYXJzZS1pbXBvcnQtY2xhdXNlL3BhcnNlLW5hbWVkLWltcG9ydHMuanMiLCIuLi9zcmMvcGFyc2UtaW1wb3J0LWNsYXVzZS9wYXJzZS1uYW1lc3BhY2UtaW1wb3J0LmpzIiwiLi4vc3JjL3BhcnNlLWltcG9ydC1jbGF1c2UvaW5kZXguanMiLCIuLi9zcmMvcGFyc2UtbW9kdWxlLXNwZWNpZmllci9pcy1jb25zdGFudC1zdHJpbmctbGl0ZXJhbC5qcyIsIi4uL3NyYy9wYXJzZS1tb2R1bGUtc3BlY2lmaWVyL3BhcnNlLXR5cGUuanMiLCIuLi9zcmMvcGFyc2UtbW9kdWxlLXNwZWNpZmllci9yZXNvbHZlLmpzIiwiLi4vc3JjL3BhcnNlLW1vZHVsZS1zcGVjaWZpZXIvaW5kZXguanMiLCIuLi9zcmMvaW5kZXguanMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNvbnN0IHNlcGFyYXRvclJlZ2V4ID0gL14oPzpcXHMrfCwpJC91XG5cbmV4cG9ydCBjb25zdCBza2lwU2VwYXJhdG9ycyA9IChpbXBvcnRlZCwgaSkgPT4ge1xuICB3aGlsZSAoaSA8IGltcG9ydGVkLmxlbmd0aCAmJiBzZXBhcmF0b3JSZWdleC50ZXN0KGltcG9ydGVkW2ldKSkge1xuICAgIGkrK1xuICB9XG5cbiAgcmV0dXJuIGlcbn1cblxuZXhwb3J0IGNvbnN0IHNraXBOb25TZXBhcmF0b3JzID0gKGltcG9ydGVkLCBpKSA9PiB7XG4gIHdoaWxlIChpIDwgaW1wb3J0ZWQubGVuZ3RoICYmICFzZXBhcmF0b3JSZWdleC50ZXN0KGltcG9ydGVkW2ldKSkge1xuICAgIGkrK1xuICB9XG5cbiAgcmV0dXJuIGlcbn1cbiIsImltcG9ydCB7IHNraXBOb25TZXBhcmF0b3JzIH0gZnJvbSAnLi9za2lwLmpzJ1xuXG5jb25zdCBwYXJzZURlZmF1bHRJbXBvcnQgPSAoaW1wb3J0Q2xhdXNlU3RyaW5nLCBpKSA9PiB7XG4gIGNvbnN0IHN0YXJ0SW5kZXggPSBpXG4gIGkgPSBza2lwTm9uU2VwYXJhdG9ycyhpbXBvcnRDbGF1c2VTdHJpbmcsIGkpXG5cbiAgcmV0dXJuIHsgZGVmYXVsdEltcG9ydDogaW1wb3J0Q2xhdXNlU3RyaW5nLnNsaWNlKHN0YXJ0SW5kZXgsIGkpLCBpIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgcGFyc2VEZWZhdWx0SW1wb3J0XG4iLCJjb25zdCBwYXJzZU5hbWVkSW1wb3J0cyA9IChpbXBvcnRDbGF1c2VTdHJpbmcsIGkpID0+IHtcbiAgY29uc3Qgc3RhcnRJbmRleCA9ICsraVxuXG4gIHdoaWxlIChpIDwgaW1wb3J0Q2xhdXNlU3RyaW5nLmxlbmd0aCAmJiBpbXBvcnRDbGF1c2VTdHJpbmdbaV0gIT09IGB9YCkge1xuICAgIGkrK1xuICB9XG5cbiAgY29uc3QgbmFtZWRJbXBvcnRzID0gaW1wb3J0Q2xhdXNlU3RyaW5nXG4gICAgLnNsaWNlKHN0YXJ0SW5kZXgsIGkrKylcbiAgICAuc3BsaXQoYCxgKVxuICAgIC5tYXAobmFtZWRJbXBvcnQgPT4ge1xuICAgICAgbmFtZWRJbXBvcnQgPSBuYW1lZEltcG9ydC50cmltKClcbiAgICAgIGlmIChuYW1lZEltcG9ydC5pbmNsdWRlcyhgIGApKSB7XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudHMgPSBuYW1lZEltcG9ydC5zcGxpdChgIGApXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgc3BlY2lmaWVyOiBjb21wb25lbnRzWzBdLFxuICAgICAgICAgIGJpbmRpbmc6IGNvbXBvbmVudHMuYXQoLTEpLFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4geyBzcGVjaWZpZXI6IG5hbWVkSW1wb3J0LCBiaW5kaW5nOiBuYW1lZEltcG9ydCB9XG4gICAgfSlcbiAgICAuZmlsdGVyKCh7IHNwZWNpZmllciB9KSA9PiBzcGVjaWZpZXIubGVuZ3RoID4gMClcblxuICByZXR1cm4geyBuYW1lZEltcG9ydHMsIGkgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBwYXJzZU5hbWVkSW1wb3J0c1xuIiwiaW1wb3J0IHsgc2tpcE5vblNlcGFyYXRvcnMsIHNraXBTZXBhcmF0b3JzIH0gZnJvbSAnLi9za2lwLmpzJ1xuXG5jb25zdCBwYXJzZU5hbWVzcGFjZUltcG9ydCA9IChpbXBvcnRDbGF1c2VTdHJpbmcsIGkpID0+IHtcbiAgaSsrXG4gIGkgPSBza2lwU2VwYXJhdG9ycyhpbXBvcnRDbGF1c2VTdHJpbmcsIGkpXG4gIGkgKz0gYGFzYC5sZW5ndGhcbiAgaSA9IHNraXBTZXBhcmF0b3JzKGltcG9ydENsYXVzZVN0cmluZywgaSlcblxuICBjb25zdCBzdGFydEluZGV4ID0gaVxuICBpID0gc2tpcE5vblNlcGFyYXRvcnMoaW1wb3J0Q2xhdXNlU3RyaW5nLCBpKVxuXG4gIHJldHVybiB7XG4gICAgbmFtZXNwYWNlSW1wb3J0OiBpbXBvcnRDbGF1c2VTdHJpbmcuc2xpY2Uoc3RhcnRJbmRleCwgaSksXG4gICAgaSxcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBwYXJzZU5hbWVzcGFjZUltcG9ydFxuIiwiaW1wb3J0IHBhcnNlRGVmYXVsdEltcG9ydCBmcm9tICcuL3BhcnNlLWRlZmF1bHQtaW1wb3J0LmpzJ1xuaW1wb3J0IHBhcnNlTmFtZWRJbXBvcnRzIGZyb20gJy4vcGFyc2UtbmFtZWQtaW1wb3J0cy5qcydcbmltcG9ydCBwYXJzZU5hbWVzcGFjZUltcG9ydCBmcm9tICcuL3BhcnNlLW5hbWVzcGFjZS1pbXBvcnQuanMnXG5pbXBvcnQgeyBzZXBhcmF0b3JSZWdleCB9IGZyb20gJy4vc2tpcC5qcydcblxuLy8gQXNzdW1lcyBpbXBvcnQgY2xhdXNlIGlzIHN5bnRhY3RpY2FsbHkgdmFsaWRcbmNvbnN0IHBhcnNlSW1wb3J0Q2xhdXNlID0gaW1wb3J0Q2xhdXNlU3RyaW5nID0+IHtcbiAgbGV0IGRlZmF1bHRJbXBvcnRcbiAgbGV0IG5hbWVzcGFjZUltcG9ydFxuICBjb25zdCBuYW1lZEltcG9ydHMgPSBbXVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaW1wb3J0Q2xhdXNlU3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKHNlcGFyYXRvclJlZ2V4LnRlc3QoaW1wb3J0Q2xhdXNlU3RyaW5nW2ldKSkge1xuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICBpZiAoaW1wb3J0Q2xhdXNlU3RyaW5nW2ldID09PSBge2ApIHtcbiAgICAgIGxldCBuZXdOYW1lZEltcG9ydHNcbiAgICAgIDsoeyBuYW1lZEltcG9ydHM6IG5ld05hbWVkSW1wb3J0cywgaSB9ID0gcGFyc2VOYW1lZEltcG9ydHMoXG4gICAgICAgIGltcG9ydENsYXVzZVN0cmluZyxcbiAgICAgICAgaSxcbiAgICAgICkpXG4gICAgICBuYW1lZEltcG9ydHMucHVzaCguLi5uZXdOYW1lZEltcG9ydHMpXG4gICAgfSBlbHNlIGlmIChpbXBvcnRDbGF1c2VTdHJpbmdbaV0gPT09IGAqYCkge1xuICAgICAgOyh7IG5hbWVzcGFjZUltcG9ydCwgaSB9ID0gcGFyc2VOYW1lc3BhY2VJbXBvcnQoaW1wb3J0Q2xhdXNlU3RyaW5nLCBpKSlcbiAgICB9IGVsc2Uge1xuICAgICAgOyh7IGRlZmF1bHRJbXBvcnQsIGkgfSA9IHBhcnNlRGVmYXVsdEltcG9ydChpbXBvcnRDbGF1c2VTdHJpbmcsIGkpKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZGVmYXVsdDogZGVmYXVsdEltcG9ydCxcbiAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZUltcG9ydCxcbiAgICBuYW1lZDogbmFtZWRJbXBvcnRzLFxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IHBhcnNlSW1wb3J0Q2xhdXNlXG4iLCIvLyBBc3N1bWVzIHRoZSBzdHJpbmcgaXMgc3ludGFjdGljYWxseSB2YWxpZFxuY29uc3QgaXNDb25zdGFudFN0cmluZ0xpdGVyYWwgPSBzdHJpbmdMaXRlcmFsID0+IHtcbiAgY29uc3QgcXVvdGUgPSBbYCdgLCBgXCJgLCBgXFxgYF0uZmluZChcbiAgICBxdW90ZUNhbmRpZGF0ZSA9PlxuICAgICAgc3RyaW5nTGl0ZXJhbC5zdGFydHNXaXRoKHF1b3RlQ2FuZGlkYXRlKSAmJlxuICAgICAgc3RyaW5nTGl0ZXJhbC5lbmRzV2l0aChxdW90ZUNhbmRpZGF0ZSksXG4gIClcblxuICBpZiAocXVvdGUgPT0gbnVsbCkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDE7IGkgPCBzdHJpbmdMaXRlcmFsLmxlbmd0aCAtIDE7IGkrKykge1xuICAgIC8vIENoZWNrIGZvciBlbmQgb2Ygc3RyaW5nIGxpdGVyYWwgYmVmb3JlIGVuZCBvZiBzdHJpbmdMaXRlcmFsXG4gICAgaWYgKHN0cmluZ0xpdGVyYWxbaV0gPT09IHF1b3RlICYmIHN0cmluZ0xpdGVyYWxbaSAtIDFdICE9PSBgXFxcXGApIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cblxuICAgIC8vIENoZWNrIGZvciBpbnRlcnBvbGF0ZWQgdmFsdWUgaW4gdGVtcGxhdGUgbGl0ZXJhbFxuICAgIGlmIChcbiAgICAgIHF1b3RlID09PSBgXFxgYCAmJlxuICAgICAgc3RyaW5nTGl0ZXJhbC5zbGljZShpLCBpICsgMikgPT09IGBcXCR7YCAmJlxuICAgICAgc3RyaW5nTGl0ZXJhbFtpIC0gMV0gIT09IGBcXFxcYFxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWVcbn1cblxuZXhwb3J0IGRlZmF1bHQgaXNDb25zdGFudFN0cmluZ0xpdGVyYWxcbiIsImltcG9ydCBtb2R1bGUgZnJvbSAnbm9kZTptb2R1bGUnXG5cbmNvbnN0IGJ1aWx0aW5Nb2R1bGVzID0gbmV3IFNldChtb2R1bGUuYnVpbHRpbk1vZHVsZXMpXG5cbmNvbnN0IHBhcnNlVHlwZSA9IG1vZHVsZVNwZWNpZmllciA9PiB7XG4gIGlmIChtb2R1bGVTcGVjaWZpZXIubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGBpbnZhbGlkYFxuICB9XG5cbiAgaWYgKG1vZHVsZVNwZWNpZmllci5zdGFydHNXaXRoKGAvYCkpIHtcbiAgICByZXR1cm4gYGFic29sdXRlYFxuICB9XG5cbiAgaWYgKG1vZHVsZVNwZWNpZmllci5zdGFydHNXaXRoKGAuYCkpIHtcbiAgICByZXR1cm4gYHJlbGF0aXZlYFxuICB9XG5cbiAgaWYgKGJ1aWx0aW5Nb2R1bGVzLmhhcyhtb2R1bGVTcGVjaWZpZXIpKSB7XG4gICAgcmV0dXJuIGBidWlsdGluYFxuICB9XG5cbiAgcmV0dXJuIGBwYWNrYWdlYFxufVxuXG5leHBvcnQgZGVmYXVsdCBwYXJzZVR5cGVcbiIsImltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tICdub2RlOm1vZHVsZSdcbmltcG9ydCB7IGRpcm5hbWUgfSBmcm9tICdub2RlOnBhdGgnXG5cbmNvbnN0IHJlcXVpcmUgPSBjcmVhdGVSZXF1aXJlKGltcG9ydC5tZXRhLnVybClcblxuY29uc3QgcmVzb2x2ZSA9IChmcm9tLCB0bykgPT4ge1xuICB0cnkge1xuICAgIHJldHVybiByZXF1aXJlLnJlc29sdmUodG8sIHsgcGF0aHM6IFtkaXJuYW1lKGZyb20pXSB9KVxuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgcmVzb2x2ZVxuIiwiaW1wb3J0IGFzc2VydCBmcm9tICdub2RlOmFzc2VydCdcbmltcG9ydCB7IHJlbW92ZVNsYXNoZXMgfSBmcm9tICdzbGFzaGVzJ1xuaW1wb3J0IGlzQ29uc3RhbnRTdHJpbmdMaXRlcmFsIGZyb20gJy4vaXMtY29uc3RhbnQtc3RyaW5nLWxpdGVyYWwuanMnXG5pbXBvcnQgcGFyc2VUeXBlIGZyb20gJy4vcGFyc2UtdHlwZS5qcydcbmltcG9ydCByZXNvbHZlIGZyb20gJy4vcmVzb2x2ZS5qcydcblxuY29uc3QgcGFyc2VNb2R1bGVTcGVjaWZpZXIgPSAoXG4gIG1vZHVsZVNwZWNpZmllclN0cmluZyxcbiAgeyBpc0R5bmFtaWNJbXBvcnQsIHJlc29sdmVGcm9tIH0sXG4pID0+IHtcbiAgYXNzZXJ0KGlzRHluYW1pY0ltcG9ydCB8fCBpc0NvbnN0YW50U3RyaW5nTGl0ZXJhbChtb2R1bGVTcGVjaWZpZXJTdHJpbmcpKVxuXG4gIGNvbnN0IHsgaXNDb25zdGFudCwgdmFsdWUgfSA9XG4gICAgIWlzRHluYW1pY0ltcG9ydCB8fCBpc0NvbnN0YW50U3RyaW5nTGl0ZXJhbChtb2R1bGVTcGVjaWZpZXJTdHJpbmcpXG4gICAgICA/IHtcbiAgICAgICAgICBpc0NvbnN0YW50OiB0cnVlLFxuICAgICAgICAgIHZhbHVlOiByZW1vdmVTbGFzaGVzKG1vZHVsZVNwZWNpZmllclN0cmluZy5zbGljZSgxLCAtMSkpLFxuICAgICAgICB9XG4gICAgICA6IHsgaXNDb25zdGFudDogZmFsc2UsIHZhbHVlOiB1bmRlZmluZWQgfVxuXG4gIHJldHVybiB7XG4gICAgdHlwZTogaXNDb25zdGFudCA/IHBhcnNlVHlwZSh2YWx1ZSkgOiBgdW5rbm93bmAsXG4gICAgaXNDb25zdGFudCxcbiAgICBjb2RlOiBtb2R1bGVTcGVjaWZpZXJTdHJpbmcsXG4gICAgdmFsdWUsXG4gICAgcmVzb2x2ZWQ6XG4gICAgICB0eXBlb2YgcmVzb2x2ZUZyb20gPT09IGBzdHJpbmdgICYmIGlzQ29uc3RhbnRcbiAgICAgICAgPyByZXNvbHZlKHJlc29sdmVGcm9tLCB2YWx1ZSlcbiAgICAgICAgOiB1bmRlZmluZWQsXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgcGFyc2VNb2R1bGVTcGVjaWZpZXJcbiIsImltcG9ydCB7IGluaXQsIHBhcnNlIH0gZnJvbSAnZXMtbW9kdWxlLWxleGVyJ1xuaW1wb3J0IHBhcnNlSW1wb3J0Q2xhdXNlIGZyb20gJy4vcGFyc2UtaW1wb3J0LWNsYXVzZS9pbmRleC5qcydcbmltcG9ydCBwYXJzZU1vZHVsZVNwZWNpZmllciBmcm9tICcuL3BhcnNlLW1vZHVsZS1zcGVjaWZpZXIvaW5kZXguanMnXG5cbmV4cG9ydCBjb25zdCB3YXNtTG9hZFByb21pc2UgPSBpbml0XG5cbmV4cG9ydCBjb25zdCBwYXJzZUltcG9ydHMgPSBhc3luYyAoY29kZSwgb3B0aW9ucykgPT4ge1xuICBhd2FpdCB3YXNtTG9hZFByb21pc2VcbiAgcmV0dXJuIHBhcnNlSW1wb3J0c1N5bmMoY29kZSwgb3B0aW9ucylcbn1cblxuZXhwb3J0IGNvbnN0IHBhcnNlSW1wb3J0c1N5bmMgPSAoY29kZSwgeyByZXNvbHZlRnJvbSB9ID0ge30pID0+IHtcbiAgY29uc3QgcmVzdWx0ID0gcGFyc2UoY29kZSwgcmVzb2x2ZUZyb20gPT0gbnVsbCA/IHVuZGVmaW5lZCA6IHJlc29sdmVGcm9tKVxuICBpZiAoIUFycmF5LmlzQXJyYXkocmVzdWx0KSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICBgRXhwZWN0ZWQgV0FTTSB0byBiZSBsb2FkZWQgYmVmb3JlIGNhbGxpbmcgcGFyc2VJbXBvcnRzU3luY2AsXG4gICAgKVxuICB9XG4gIGNvbnN0IFtpbXBvcnRzXSA9IHJlc3VsdFxuXG4gIHJldHVybiB7XG4gICAgKltTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgICAgZm9yIChsZXQge1xuICAgICAgICBkOiBkeW5hbWljSW1wb3J0U3RhcnRJbmRleCxcbiAgICAgICAgc3M6IHN0YXRlbWVudFN0YXJ0SW5kZXgsXG4gICAgICAgIHM6IG1vZHVsZVNwZWNpZmllclN0YXJ0SW5kZXgsXG4gICAgICAgIGU6IG1vZHVsZVNwZWNpZmllckVuZEluZGV4RXhjbHVzaXZlLFxuICAgICAgfSBvZiBpbXBvcnRzKSB7XG4gICAgICAgIGNvbnN0IGlzSW1wb3J0TWV0YSA9IGR5bmFtaWNJbXBvcnRTdGFydEluZGV4ID09PSAtMlxuICAgICAgICBpZiAoaXNJbXBvcnRNZXRhKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGlzRHluYW1pY0ltcG9ydCA9IGR5bmFtaWNJbXBvcnRTdGFydEluZGV4ID4gLTFcblxuICAgICAgICAvLyBJbmNsdWRlIHN0cmluZyBsaXRlcmFsIHF1b3RlcyBpbiBjaGFyYWN0ZXIgcmFuZ2VcbiAgICAgICAgaWYgKCFpc0R5bmFtaWNJbXBvcnQpIHtcbiAgICAgICAgICBtb2R1bGVTcGVjaWZpZXJTdGFydEluZGV4LS1cbiAgICAgICAgICBtb2R1bGVTcGVjaWZpZXJFbmRJbmRleEV4Y2x1c2l2ZSsrXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBtb2R1bGVTcGVjaWZpZXJTdHJpbmcgPSBjb2RlLnNsaWNlKFxuICAgICAgICAgIG1vZHVsZVNwZWNpZmllclN0YXJ0SW5kZXgsXG4gICAgICAgICAgbW9kdWxlU3BlY2lmaWVyRW5kSW5kZXhFeGNsdXNpdmUsXG4gICAgICAgIClcbiAgICAgICAgY29uc3QgbW9kdWxlU3BlY2lmaWVyID0ge1xuICAgICAgICAgIHN0YXJ0SW5kZXg6IG1vZHVsZVNwZWNpZmllclN0YXJ0SW5kZXgsXG4gICAgICAgICAgZW5kSW5kZXg6IG1vZHVsZVNwZWNpZmllckVuZEluZGV4RXhjbHVzaXZlLFxuICAgICAgICAgIC4uLnBhcnNlTW9kdWxlU3BlY2lmaWVyKG1vZHVsZVNwZWNpZmllclN0cmluZywge1xuICAgICAgICAgICAgaXNEeW5hbWljSW1wb3J0LFxuICAgICAgICAgICAgcmVzb2x2ZUZyb20sXG4gICAgICAgICAgfSksXG4gICAgICAgIH1cblxuICAgICAgICBsZXQgaW1wb3J0Q2xhdXNlXG4gICAgICAgIGlmICghaXNEeW5hbWljSW1wb3J0KSB7XG4gICAgICAgICAgbGV0IGltcG9ydENsYXVzZVN0cmluZyA9IGNvZGVcbiAgICAgICAgICAgIC5zbGljZShcbiAgICAgICAgICAgICAgc3RhdGVtZW50U3RhcnRJbmRleCArIGBpbXBvcnRgLmxlbmd0aCxcbiAgICAgICAgICAgICAgbW9kdWxlU3BlY2lmaWVyU3RhcnRJbmRleCxcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC50cmltKClcbiAgICAgICAgICBpZiAoaW1wb3J0Q2xhdXNlU3RyaW5nLmVuZHNXaXRoKGBmcm9tYCkpIHtcbiAgICAgICAgICAgIGltcG9ydENsYXVzZVN0cmluZyA9IGltcG9ydENsYXVzZVN0cmluZy5zbGljZShcbiAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgTWF0aC5tYXgoMCwgaW1wb3J0Q2xhdXNlU3RyaW5nLmxlbmd0aCAtIGBmcm9tYC5sZW5ndGgpLFxuICAgICAgICAgICAgKVxuICAgICAgICAgIH1cbiAgICAgICAgICBpbXBvcnRDbGF1c2UgPSBwYXJzZUltcG9ydENsYXVzZShpbXBvcnRDbGF1c2VTdHJpbmcpXG4gICAgICAgIH1cblxuICAgICAgICB5aWVsZCB7XG4gICAgICAgICAgc3RhcnRJbmRleDogc3RhdGVtZW50U3RhcnRJbmRleCxcbiAgICAgICAgICAvLyBJbmNsdWRlIHRoZSBjbG9zaW5nIHBhcmVudGhlc2lzIGZvciBkeW5hbWljIGltcG9ydFxuICAgICAgICAgIGVuZEluZGV4OiBpc0R5bmFtaWNJbXBvcnRcbiAgICAgICAgICAgID8gbW9kdWxlU3BlY2lmaWVyRW5kSW5kZXhFeGNsdXNpdmUgKyAxXG4gICAgICAgICAgICA6IG1vZHVsZVNwZWNpZmllckVuZEluZGV4RXhjbHVzaXZlLFxuICAgICAgICAgIGlzRHluYW1pY0ltcG9ydCxcbiAgICAgICAgICBtb2R1bGVTcGVjaWZpZXIsXG4gICAgICAgICAgaW1wb3J0Q2xhdXNlLFxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUEsTUFBYSxpQkFBaUI7QUFFOUIsTUFBYSxrQkFBa0IsVUFBVSxNQUFNO0FBQzdDLFFBQU8sSUFBSSxT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