@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
203 lines • 25.4 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.addCustomSynthesis = exports.synthesize = void 0;
const cxapi = require("@aws-cdk/cx-api");
const constructs = require("constructs");
const annotations_1 = require("../annotations");
const aspect_1 = require("../aspect");
const stack_1 = require("../stack");
const stage_1 = require("../stage");
const metadata_resource_1 = require("./metadata-resource");
const prepare_app_1 = require("./prepare-app");
const tree_metadata_1 = require("./tree-metadata");
function synthesize(root, options = {}) {
// we start by calling "synth" on all nested assemblies (which will take care of all their children)
synthNestedAssemblies(root, options);
invokeAspects(root);
injectMetadataResources(root);
// This is mostly here for legacy purposes as the framework itself does not use prepare anymore.
prepareTree(root);
// resolve references
prepare_app_1.prepareApp(root);
// give all children an opportunity to validate now that we've finished prepare
if (!options.skipValidation) {
validateTree(root);
}
// in unit tests, we support creating free-standing stacks, so we create the
// assembly builder here.
const builder = stage_1.Stage.isStage(root)
? root._assemblyBuilder
: new cxapi.CloudAssemblyBuilder(options.outdir);
// next, we invoke "onSynthesize" on all of our children. this will allow
// stacks to add themselves to the synthesized cloud assembly.
synthesizeTree(root, builder, options.validateOnSynthesis);
return builder.buildAssembly();
}
exports.synthesize = synthesize;
const CUSTOM_SYNTHESIS_SYM = Symbol.for('@aws-cdk/core:customSynthesis');
function addCustomSynthesis(construct, synthesis) {
Object.defineProperty(construct, CUSTOM_SYNTHESIS_SYM, {
value: synthesis,
enumerable: false,
});
}
exports.addCustomSynthesis = addCustomSynthesis;
function getCustomSynthesis(construct) {
return construct[CUSTOM_SYNTHESIS_SYM];
}
/**
* Find Assemblies inside the construct and call 'synth' on them
*
* (They will in turn recurse again)
*/
function synthNestedAssemblies(root, options) {
for (const child of root.node.children) {
if (stage_1.Stage.isStage(child)) {
child.synth(options);
}
else {
synthNestedAssemblies(child, options);
}
}
}
/**
* Invoke aspects on the given construct tree.
*
* Aspects are not propagated across Assembly boundaries. The same Aspect will not be invoked
* twice for the same construct.
*/
function invokeAspects(root) {
const invokedByPath = {};
let nestedAspectWarning = false;
recurse(root, []);
function recurse(construct, inheritedAspects) {
const node = construct.node;
const aspects = aspect_1.Aspects.of(construct);
const allAspectsHere = [...inheritedAspects ?? [], ...aspects.aspects];
const nodeAspectsCount = aspects.aspects.length;
for (const aspect of allAspectsHere) {
let invoked = invokedByPath[node.path];
if (!invoked) {
invoked = invokedByPath[node.path] = [];
}
if (invoked.includes(aspect)) {
continue;
}
aspect.visit(construct);
// if an aspect was added to the node while invoking another aspect it will not be invoked, emit a warning
// the `nestedAspectWarning` flag is used to prevent the warning from being emitted for every child
if (!nestedAspectWarning && nodeAspectsCount !== aspects.aspects.length) {
annotations_1.Annotations.of(construct).addWarning('We detected an Aspect was added via another Aspect, and will not be applied');
nestedAspectWarning = true;
}
// mark as invoked for this node
invoked.push(aspect);
}
for (const child of construct.node.children) {
if (!stage_1.Stage.isStage(child)) {
recurse(child, allAspectsHere);
}
}
}
}
/**
* Prepare all constructs in the given construct tree in post-order.
*
* Stop at Assembly boundaries.
*/
function prepareTree(root) {
visit(root, 'post', construct => construct.onPrepare());
}
/**
* Find all stacks and add Metadata Resources to all of them
*
* There is no good generic place to do this. Can't do it in the constructor
* (because adding a child construct makes it impossible to set context on the
* node), and the generic prepare phase is deprecated.
*
* Only do this on [parent] stacks (not nested stacks), don't do this when
* disabled by the user.
*
* Also, only when running via the CLI. If we do it unconditionally,
* all unit tests everywhere are going to break massively. I've spent a day
* fixing our own, but downstream users would be affected just as badly.
*
* Stop at Assembly boundaries.
*/
function injectMetadataResources(root) {
visit(root, 'post', construct => {
if (!stack_1.Stack.isStack(construct) || !construct._versionReportingEnabled) {
return;
}
// Because of https://github.com/aws/aws-cdk/blob/master/packages/assert-internal/lib/synth-utils.ts#L74
// synthesize() may be called more than once on a stack in unit tests, and the below would break
// if we execute it a second time. Guard against the constructs already existing.
const CDKMetadata = 'CDKMetadata';
if (construct.node.tryFindChild(CDKMetadata)) {
return;
}
new metadata_resource_1.MetadataResource(construct, CDKMetadata);
});
}
/**
* Synthesize children in post-order into the given builder
*
* Stop at Assembly boundaries.
*/
function synthesizeTree(root, builder, validateOnSynth = false) {
visit(root, 'post', construct => {
const session = {
outdir: builder.outdir,
assembly: builder,
validateOnSynth,
};
if (stack_1.Stack.isStack(construct)) {
construct.synthesizer.synthesize(session);
}
else if (construct instanceof tree_metadata_1.TreeMetadata) {
construct._synthesizeTree(session);
}
else {
const custom = getCustomSynthesis(construct);
custom?.onSynthesize(session);
}
// this will soon be deprecated and removed in 2.x
// see https://github.com/aws/aws-cdk-rfcs/issues/192
construct.onSynthesize(session);
});
}
/**
* Validate all constructs in the given construct tree
*/
function validateTree(root) {
const errors = new Array();
// Validations added through `node.addValidation()`
// This automatically also includes Ye Olde Method of validating, using
// the `protected validate()` methods.
errors.push(...constructs.Node.of(root).validate().map(e => ({
message: e.message,
source: e.source,
})));
if (errors.length > 0) {
const errorList = errors.map(e => `[${e.source.node.path}] ${e.message}`).join('\n ');
throw new Error(`Validation failed with the following errors:\n ${errorList}`);
}
}
/**
* Visit the given construct tree in either pre or post order, stopping at Assemblies
*/
function visit(root, order, cb) {
if (order === 'pre') {
cb(root);
}
for (const child of root.node.children) {
if (stage_1.Stage.isStage(child)) {
continue;
}
visit(child, order, cb);
}
if (order === 'post') {
cb(root);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ludGhlc2lzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3ludGhlc2lzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlDQUF5QztBQUN6Qyx5Q0FBeUM7QUFDekMsZ0RBQTZDO0FBQzdDLHNDQUE2QztBQUU3QyxvQ0FBaUM7QUFDakMsb0NBQXdEO0FBQ3hELDJEQUF1RDtBQUN2RCwrQ0FBMkM7QUFDM0MsbURBQStDO0FBRS9DLFNBQWdCLFVBQVUsQ0FBQyxJQUFnQixFQUFFLFVBQTRCLEVBQUc7SUFDMUUsb0dBQW9HO0lBQ3BHLHFCQUFxQixDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztJQUVyQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFcEIsdUJBQXVCLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFOUIsZ0dBQWdHO0lBQ2hHLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVsQixxQkFBcUI7SUFDckIsd0JBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVqQiwrRUFBK0U7SUFDL0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUU7UUFDM0IsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ3BCO0lBRUQsNEVBQTRFO0lBQzVFLHlCQUF5QjtJQUN6QixNQUFNLE9BQU8sR0FBRyxhQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztRQUNqQyxDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQjtRQUN2QixDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsb0JBQW9CLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRW5ELHlFQUF5RTtJQUN6RSw4REFBOEQ7SUFDOUQsY0FBYyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFFM0QsT0FBTyxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUM7QUFDakMsQ0FBQztBQTlCRCxnQ0E4QkM7QUFFRCxNQUFNLG9CQUFv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QUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRTtRQUN0QyxJQUFJLGFBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFBRSxTQUFTO1NBQUU7UUFDdkMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7S0FDekI7SUFFRCxJQUFJLEtBQUssS0FBSyxNQUFNLEVBQUU7UUFDcEIsRUFBRSxDQUFDLElBQWtDLENBQUMsQ0FBQztLQUN4QztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0ICogYXMgY29uc3RydWN0cyBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEFubm90YXRpb25zIH0gZnJvbSAnLi4vYW5ub3RhdGlvbnMnO1xuaW1wb3J0IHsgQXNwZWN0cywgSUFzcGVjdCB9IGZyb20gJy4uL2FzcGVjdCc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QsIElDb25zdHJ1Y3QsIElTeW50aGVzaXNTZXNzaW9uLCBTeW50aGVzaXNPcHRpb25zLCBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tICcuLi9jb25zdHJ1Y3QtY29tcGF0JztcbmltcG9ydCB7IFN0YWNrIH0gZnJvbSAnLi4vc3RhY2snO1xuaW1wb3J0IHsgU3RhZ2UsIFN0YWdlU3ludGhlc2lzT3B0aW9ucyB9IGZyb20gJy4uL3N0YWdlJztcbmltcG9ydCB7IE1ldGFkYXRhUmVzb3VyY2UgfSBmcm9tICcuL21ldGFkYXRhLXJlc291cmNlJztcbmltcG9ydCB7IHByZXBhcmVBcHAgfSBmcm9tICcuL3ByZXBhcmUtYXBwJztcbmltcG9ydCB7IFRyZWVNZXRhZGF0YSB9IGZyb20gJy4vdHJlZS1tZXRhZGF0YSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBzeW50aGVzaXplKHJvb3Q6IElDb25zdHJ1Y3QsIG9wdGlvbnM6IFN5bnRoZXNpc09wdGlvbnMgPSB7IH0pOiBjeGFwaS5DbG91ZEFzc2VtYmx5IHtcbiAgLy8gd2Ugc3RhcnQgYnkgY2FsbGluZyBcInN5bnRoXCIgb24gYWxsIG5lc3RlZCBhc3NlbWJsaWVzICh3aGljaCB3aWxsIHRha2UgY2FyZSBvZiBhbGwgdGhlaXIgY2hpbGRyZW4pXG4gIHN5bnRoTmVzdGVkQXNzZW1ibGllcyhyb290LCBvcHRpb25zKTtcblxuICBpbnZva2VBc3BlY3RzKHJvb3QpO1xuXG4gIGluamVjdE1ldGFkYXRhUmVzb3VyY2VzKHJvb3QpO1xuXG4gIC8vIFRoaXMgaXMgbW9zdGx5IGhlcmUgZm9yIGxlZ2FjeSBwdXJwb3NlcyBhcyB0aGUgZnJhbWV3b3JrIGl0c2VsZiBkb2VzIG5vdCB1c2UgcHJlcGFyZSBhbnltb3JlLlxuICBwcmVwYXJlVHJlZShyb290KTtcblxuICAvLyByZXNvbHZlIHJlZmVyZW5jZXNcbiAgcHJlcGFyZUFwcChyb290KTtcblxuICAvLyBnaXZlIGFsbCBjaGlsZHJlbiBhbiBvcHBvcnR1bml0eSB0byB2YWxpZGF0ZSBub3cgdGhhdCB3ZSd2ZSBmaW5pc2hlZCBwcmVwYXJlXG4gIGlmICghb3B0aW9ucy5za2lwVmFsaWRhdGlvbikge1xuICAgIHZhbGlkYXRlVHJlZShyb290KTtcbiAgfVxuXG4gIC8vIGluIHVuaXQgdGVzdHMsIHdlIHN1cHBvcnQgY3JlYXRpbmcgZnJlZS1zdGFuZGluZyBzdGFja3MsIHNvIHdlIGNyZWF0ZSB0aGVcbiAgLy8gYXNzZW1ibHkgYnVpbGRlciBoZXJlLlxuICBjb25zdCBidWlsZGVyID0gU3RhZ2UuaXNTdGFnZShyb290KVxuICAgID8gcm9vdC5fYXNzZW1ibHlCdWlsZGVyXG4gICAgOiBuZXcgY3hhcGkuQ2xvdWRBc3NlbWJseUJ1aWxkZXIob3B0aW9ucy5vdXRkaXIpO1xuXG4gIC8vIG5leHQsIHdlIGludm9rZSBcIm9uU3ludGhlc2l6ZVwiIG9uIGFsbCBvZiBvdXIgY2hpbGRyZW4uIHRoaXMgd2lsbCBhbGxvd1xuICAvLyBzdGFja3MgdG8gYWRkIHRoZW1zZWx2ZXMgdG8gdGhlIHN5bnRoZXNpemVkIGNsb3VkIGFzc2VtYmx5LlxuICBzeW50aGVzaXplVHJlZShyb290LCBidWlsZGVyLCBvcHRpb25zLnZhbGlkYXRlT25TeW50aGVzaXMpO1xuXG4gIHJldHVybiBidWlsZGVyLmJ1aWxkQXNzZW1ibHkoKTtcbn1cblxuY29uc3QgQ1VTVE9NX1NZTlRIRVNJU19TWU0gPSBTeW1ib2wuZm9yKCdAYXdzLWNkay9jb3JlOmN1c3RvbVN5bnRoZXNpcycpO1xuXG4vKipcbiAqIEludGVyZmFjZSBmb3IgY29uc3RydWN0cyB0aGF0IHdhbnQgdG8gZG8gc29tZXRoaW5nIGN1c3RvbSBkdXJpbmcgc3ludGhlc2lzXG4gKlxuICogVGhpcyBmZWF0dXJlIGlzIGludGVuZGVkIGZvciB1c2UgYnkgb2ZmaWNpYWwgQVdTIENESyBsaWJyYXJpZXMgb25seTsgM3JkIHBhcnR5XG4gKiBsaWJyYXJ5IGF1dGhvcnMgYW5kIENESyB1c2VycyBzaG91bGQgbm90IHVzZSB0aGlzIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIElDdXN0b21TeW50aGVzaXMge1xuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gdGhlIGNvbnN0cnVjdCBpcyBzeW50aGVzaXplZFxuICAgKi9cbiAgb25TeW50aGVzaXplKHNlc3Npb246IElTeW50aGVzaXNTZXNzaW9uKTogdm9pZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZEN1c3RvbVN5bnRoZXNpcyhjb25zdHJ1Y3Q6IGNvbnN0cnVjdHMuSUNvbnN0cnVjdCwgc3ludGhlc2lzOiBJQ3VzdG9tU3ludGhlc2lzKTogdm9pZCB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb25zdHJ1Y3QsIENVU1RPTV9TWU5USEVTSVNfU1lNLCB7XG4gICAgdmFsdWU6IHN5bnRoZXNpcyxcbiAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldEN1c3RvbVN5bnRoZXNpcyhjb25zdHJ1Y3Q6IGNvbnN0cnVjdHMuSUNvbnN0cnVjdCk6IElDdXN0b21TeW50aGVzaXMgfCB1bmRlZmluZWQge1xuICByZXR1cm4gKGNvbnN0cnVjdCBhcyBhbnkpW0NVU1RPTV9TWU5USEVTSVNfU1lNXTtcbn1cblxuLyoqXG4gKiBGaW5kIEFzc2VtYmxpZXMgaW5zaWRlIHRoZSBjb25zdHJ1Y3QgYW5kIGNhbGwgJ3N5bnRoJyBvbiB0aGVtXG4gKlxuICogKFRoZXkgd2lsbCBpbiB0dXJuIHJlY3Vyc2UgYWdhaW4pXG4gKi9cbmZ1bmN0aW9uIHN5bnRoTmVzdGVkQXNzZW1ibGllcyhyb290OiBJQ29uc3RydWN0LCBvcHRpb25zOiBTdGFnZVN5bnRoZXNpc09wdGlvbnMpIHtcbiAgZm9yIChjb25zdCBjaGlsZCBvZiByb290Lm5vZGUuY2hpbGRyZW4pIHtcbiAgICBpZiAoU3RhZ2UuaXNTdGFnZShjaGlsZCkpIHtcbiAgICAgIGNoaWxkLnN5bnRoKG9wdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzeW50aE5lc3RlZEFzc2VtYmxpZXMoY2hpbGQsIG9wdGlvbnMpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEludm9rZSBhc3BlY3RzIG9uIHRoZSBnaXZlbiBjb25zdHJ1Y3QgdHJlZS5cbiAqXG4gKiBBc3BlY3RzIGFyZSBub3QgcHJvcGFnYXRlZCBhY3Jvc3MgQXNzZW1ibHkgYm91bmRhcmllcy4gVGhlIHNhbWUgQXNwZWN0IHdpbGwgbm90IGJlIGludm9rZWRcbiAqIHR3aWNlIGZvciB0aGUgc2FtZSBjb25zdHJ1Y3QuXG4gKi9cbmZ1bmN0aW9uIGludm9rZUFzcGVjdHMocm9vdDogSUNvbnN0cnVjdCkge1xuICBjb25zdCBpbnZva2VkQnlQYXRoOiB7IFtub2RlUGF0aDogc3RyaW5nXTogSUFzcGVjdFtdIH0gPSB7IH07XG5cbiAgbGV0IG5lc3RlZEFzcGVjdFdhcm5pbmcgPSBmYWxzZTtcbiAgcmVjdXJzZShyb290LCBbXSk7XG5cbiAgZnVuY3Rpb24gcmVjdXJzZShjb25zdHJ1Y3Q6IElDb25zdHJ1Y3QsIGluaGVyaXRlZEFzcGVjdHM6IGNvbnN0cnVjdHMuSUFzcGVjdFtdKSB7XG4gICAgY29uc3Qgbm9kZSA9IGNvbnN0cnVjdC5ub2RlO1xuICAgIGNvbnN0IGFzcGVjdHMgPSBBc3BlY3RzLm9mKGNvbnN0cnVjdCk7XG4gICAgY29uc3QgYWxsQXNwZWN0c0hlcmUgPSBbLi4uaW5oZXJpdGVkQXNwZWN0cyA/PyBbXSwgLi4uYXNwZWN0cy5hc3BlY3RzXTtcbiAgICBjb25zdCBub2RlQXNwZWN0c0NvdW50ID0gYXNwZWN0cy5hc3BlY3RzLmxlbmd0aDtcbiAgICBmb3IgKGNvbnN0IGFzcGVjdCBvZiBhbGxBc3BlY3RzSGVyZSkge1xuICAgICAgbGV0IGludm9rZWQgPSBpbnZva2VkQnlQYXRoW25vZGUucGF0aF07XG4gICAgICBpZiAoIWludm9rZWQpIHtcbiAgICAgICAgaW52b2tlZCA9IGludm9rZWRCeVBhdGhbbm9kZS5wYXRoXSA9IFtdO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW52b2tlZC5pbmNsdWRlcyhhc3BlY3QpKSB7IGNvbnRpbnVlOyB9XG5cbiAgICAgIGFzcGVjdC52aXNpdChjb25zdHJ1Y3QpO1xuXG4gICAgICAvLyBpZiBhbiBhc3BlY3Qgd2FzIGFkZGVkIHRvIHRoZSBub2RlIHdoaWxlIGludm9raW5nIGFub3RoZXIgYXNwZWN0IGl0IHdpbGwgbm90IGJlIGludm9rZWQsIGVtaXQgYSB3YXJuaW5nXG4gICAgICAvLyB0aGUgYG5lc3RlZEFzcGVjdFdhcm5pbmdgIGZsYWcgaXMgdXNlZCB0byBwcmV2ZW50IHRoZSB3YXJuaW5nIGZyb20gYmVpbmcgZW1pdHRlZCBmb3IgZXZlcnkgY2hpbGRcbiAgICAgIGlmICghbmVzdGVkQXNwZWN0V2FybmluZyAmJiBub2RlQXNwZWN0c0NvdW50ICE9PSBhc3BlY3RzLmFzcGVjdHMubGVuZ3RoKSB7XG4gICAgICAgIEFubm90YXRpb25zLm9mKGNvbnN0cnVjdCkuYWRkV2FybmluZygnV2UgZGV0ZWN0ZWQgYW4gQXNwZWN0IHdhcyBhZGRlZCB2aWEgYW5vdGhlciBBc3BlY3QsIGFuZCB3aWxsIG5vdCBiZSBhcHBsaWVkJyk7XG4gICAgICAgIG5lc3RlZEFzcGVjdFdhcm5pbmcgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBtYXJrIGFzIGludm9rZWQgZm9yIHRoaXMgbm9kZVxuICAgICAgaW52b2tlZC5wdXNoKGFzcGVjdCk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBjb25zdHJ1Y3Qubm9kZS5jaGlsZHJlbikge1xuICAgICAgaWYgKCFTdGFnZS5pc1N0YWdlKGNoaWxkKSkge1xuICAgICAgICByZWN1cnNlKGNoaWxkLCBhbGxBc3BlY3RzSGVyZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogUHJlcGFyZSBhbGwgY29uc3RydWN0cyBpbiB0aGUgZ2l2ZW4gY29uc3RydWN0IHRyZWUgaW4gcG9zdC1vcmRlci5cbiAqXG4gKiBTdG9wIGF0IEFzc2VtYmx5IGJvdW5kYXJpZXMuXG4gKi9cbmZ1bmN0aW9uIHByZXBhcmVUcmVlKHJvb3Q6IElDb25zdHJ1Y3QpIHtcbiAgdmlzaXQocm9vdCwgJ3Bvc3QnLCBjb25zdHJ1Y3QgPT4gY29uc3RydWN0Lm9uUHJlcGFyZSgpKTtcbn1cblxuLyoqXG4gKiBGaW5kIGFsbCBzdGFja3MgYW5kIGFkZCBNZXRhZGF0YSBSZXNvdXJjZXMgdG8gYWxsIG9mIHRoZW1cbiAqXG4gKiBUaGVyZSBpcyBubyBnb29kIGdlbmVyaWMgcGxhY2UgdG8gZG8gdGhpcy4gQ2FuJ3QgZG8gaXQgaW4gdGhlIGNvbnN0cnVjdG9yXG4gKiAoYmVjYXVzZSBhZGRpbmcgYSBjaGlsZCBjb25zdHJ1Y3QgbWFrZXMgaXQgaW1wb3NzaWJsZSB0byBzZXQgY29udGV4dCBvbiB0aGVcbiAqIG5vZGUpLCBhbmQgdGhlIGdlbmVyaWMgcHJlcGFyZSBwaGFzZSBpcyBkZXByZWNhdGVkLlxuICpcbiAqIE9ubHkgZG8gdGhpcyBvbiBbcGFyZW50XSBzdGFja3MgKG5vdCBuZXN0ZWQgc3RhY2tzKSwgZG9uJ3QgZG8gdGhpcyB3aGVuXG4gKiBkaXNhYmxlZCBieSB0aGUgdXNlci5cbiAqXG4gKiBBbHNvLCBvbmx5IHdoZW4gcnVubmluZyB2aWEgdGhlIENMSS4gSWYgd2UgZG8gaXQgdW5jb25kaXRpb25hbGx5LFxuICogYWxsIHVuaXQgdGVzdHMgZXZlcnl3aGVyZSBhcmUgZ29pbmcgdG8gYnJlYWsgbWFzc2l2ZWx5LiBJJ3ZlIHNwZW50IGEgZGF5XG4gKiBmaXhpbmcgb3VyIG93biwgYnV0IGRvd25zdHJlYW0gdXNlcnMgd291bGQgYmUgYWZmZWN0ZWQganVzdCBhcyBiYWRseS5cbiAqXG4gKiBTdG9wIGF0IEFzc2VtYmx5IGJvdW5kYXJpZXMuXG4gKi9cbmZ1bmN0aW9uIGluamVjdE1ldGFkYXRhUmVzb3VyY2VzKHJvb3Q6IElDb25zdHJ1Y3QpIHtcbiAgdmlzaXQocm9vdCwgJ3Bvc3QnLCBjb25zdHJ1Y3QgPT4ge1xuICAgIGlmICghU3RhY2suaXNTdGFjayhjb25zdHJ1Y3QpIHx8ICFjb25zdHJ1Y3QuX3ZlcnNpb25SZXBvcnRpbmdFbmFibGVkKSB7IHJldHVybjsgfVxuXG4gICAgLy8gQmVjYXVzZSBvZiBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvYmxvYi9tYXN0ZXIvcGFja2FnZXMvYXNzZXJ0LWludGVybmFsL2xpYi9zeW50aC11dGlscy50cyNMNzRcbiAgICAvLyBzeW50aGVzaXplKCkgbWF5IGJlIGNhbGxlZCBtb3JlIHRoYW4gb25jZSBvbiBhIHN0YWNrIGluIHVuaXQgdGVzdHMsIGFuZCB0aGUgYmVsb3cgd291bGQgYnJlYWtcbiAgICAvLyBpZiB3ZSBleGVjdXRlIGl0IGEgc2Vjb25kIHRpbWUuIEd1YXJkIGFnYWluc3QgdGhlIGNvbnN0cnVjdHMgYWxyZWFkeSBleGlzdGluZy5cbiAgICBjb25zdCBDREtNZXRhZGF0YSA9ICdDREtNZXRhZGF0YSc7XG4gICAgaWYgKGNvbnN0cnVjdC5ub2RlLnRyeUZpbmRDaGlsZChDREtNZXRhZGF0YSkpIHsgcmV0dXJuOyB9XG5cbiAgICBuZXcgTWV0YWRhdGFSZXNvdXJjZShjb25zdHJ1Y3QsIENES01ldGFkYXRhKTtcbiAgfSk7XG59XG5cbi8qKlxuICogU3ludGhlc2l6ZSBjaGlsZHJlbiBpbiBwb3N0LW9yZGVyIGludG8gdGhlIGdpdmVuIGJ1aWxkZXJcbiAqXG4gKiBTdG9wIGF0IEFzc2VtYmx5IGJvdW5kYXJpZXMuXG4gKi9cbmZ1bmN0aW9uIHN5bnRoZXNpemVUcmVlKHJvb3Q6IElDb25zdHJ1Y3QsIGJ1aWxkZXI6IGN4YXBpLkNsb3VkQXNzZW1ibHlCdWlsZGVyLCB2YWxpZGF0ZU9uU3ludGg6IGJvb2xlYW4gPSBmYWxzZSkge1xuICB2aXNpdChyb290LCAncG9zdCcsIGNvbnN0cnVjdCA9PiB7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IHtcbiAgICAgIG91dGRpcjogYnVpbGRlci5vdXRkaXIsXG4gICAgICBhc3NlbWJseTogYnVpbGRlcixcbiAgICAgIHZhbGlkYXRlT25TeW50aCxcbiAgICB9O1xuXG4gICAgaWYgKFN0YWNrLmlzU3RhY2soY29uc3RydWN0KSkge1xuICAgICAgY29uc3RydWN0LnN5bnRoZXNpemVyLnN5bnRoZXNpemUoc2Vzc2lvbik7XG4gICAgfSBlbHNlIGlmIChjb25zdHJ1Y3QgaW5zdGFuY2VvZiBUcmVlTWV0YWRhdGEpIHtcbiAgICAgIGNvbnN0cnVjdC5fc3ludGhlc2l6ZVRyZWUoc2Vzc2lvbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGN1c3RvbSA9IGdldEN1c3RvbVN5bnRoZXNpcyhjb25zdHJ1Y3QpO1xuICAgICAgY3VzdG9tPy5vblN5bnRoZXNpemUoc2Vzc2lvbik7XG4gICAgfVxuXG4gICAgLy8gdGhpcyB3aWxsIHNvb24gYmUgZGVwcmVjYXRlZCBhbmQgcmVtb3ZlZCBpbiAyLnhcbiAgICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrLXJmY3MvaXNzdWVzLzE5MlxuICAgIGNvbnN0cnVjdC5vblN5bnRoZXNpemUoc2Vzc2lvbik7XG4gIH0pO1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIGFsbCBjb25zdHJ1Y3RzIGluIHRoZSBnaXZlbiBjb25zdHJ1Y3QgdHJlZVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZVRyZWUocm9vdDogSUNvbnN0cnVjdCkge1xuICBjb25zdCBlcnJvcnMgPSBuZXcgQXJyYXk8VmFsaWRhdGlvbkVycm9yPigpO1xuXG4gIC8vIFZhbGlkYXRpb25zIGFkZGVkIHRocm91Z2ggYG5vZGUuYWRkVmFsaWRhdGlvbigpYFxuICAvLyBUaGlzIGF1dG9tYXRpY2FsbHkgYWxzbyBpbmNsdWRlcyBZZSBPbGRlIE1ldGhvZCBvZiB2YWxpZGF0aW5nLCB1c2luZ1xuICAvLyB0aGUgYHByb3RlY3RlZCB2YWxpZGF0ZSgpYCBtZXRob2RzLlxuICBlcnJvcnMucHVzaCguLi5jb25zdHJ1Y3RzLk5vZGUub2Yocm9vdCkudmFsaWRhdGUoKS5tYXAoZSA9PiAoe1xuICAgIG1lc3NhZ2U6IGUubWVzc2FnZSwgc291cmNlOiBlLnNvdXJjZSBhcyB1bmtub3duIGFzIENvbnN0cnVjdCxcbiAgfSkpKTtcblxuICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBlcnJvckxpc3QgPSBlcnJvcnMubWFwKGUgPT4gYFske2Uuc291cmNlLm5vZGUucGF0aH1dICR7ZS5tZXNzYWdlfWApLmpvaW4oJ1xcbiAgJyk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBWYWxpZGF0aW9uIGZhaWxlZCB3aXRoIHRoZSBmb2xsb3dpbmcgZXJyb3JzOlxcbiAgJHtlcnJvckxpc3R9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBWaXNpdCB0aGUgZ2l2ZW4gY29uc3RydWN0IHRyZWUgaW4gZWl0aGVyIHByZSBvciBwb3N0IG9yZGVyLCBzdG9wcGluZyBhdCBBc3NlbWJsaWVzXG4gKi9cbmZ1bmN0aW9uIHZpc2l0KHJvb3Q6IElDb25zdHJ1Y3QsIG9yZGVyOiAncHJlJyB8ICdwb3N0JywgY2I6ICh4OiBJUHJvdGVjdGVkQ29uc3RydWN0TWV0aG9kcykgPT4gdm9pZCkge1xuICBpZiAob3JkZXIgPT09ICdwcmUnKSB7XG4gICAgY2Iocm9vdCBhcyBJUHJvdGVjdGVkQ29uc3RydWN0TWV0aG9kcyk7XG4gIH1cblxuICBmb3IgKGNvbnN0IGNoaWxkIG9mIHJvb3Qubm9kZS5jaGlsZHJlbikge1xuICAgIGlmIChTdGFnZS5pc1N0YWdlKGNoaWxkKSkgeyBjb250aW51ZTsgfVxuICAgIHZpc2l0KGNoaWxkLCBvcmRlciwgY2IpO1xuICB9XG5cbiAgaWYgKG9yZGVyID09PSAncG9zdCcpIHtcbiAgICBjYihyb290IGFzIElQcm90ZWN0ZWRDb25zdHJ1Y3RNZXRob2RzKTtcbiAgfVxufVxuXG4vKipcbiAqIEludGVyZmFjZSB3aGljaCBwcm92aWRlcyBhY2Nlc3MgdG8gc3BlY2lhbCBtZXRob2RzIG9mIENvbnN0cnVjdFxuICpcbiAqL1xuaW50ZXJmYWNlIElQcm90ZWN0ZWRDb25zdHJ1Y3RNZXRob2RzIGV4dGVuZHMgSUNvbnN0cnVjdCB7XG4gIC8qKlxuICAgKiBNZXRob2QgdGhhdCBnZXRzIGNhbGxlZCB3aGVuIGEgY29uc3RydWN0IHNob3VsZCBzeW50aGVzaXplIGl0c2VsZiB0byBhbiBhc3NlbWJseVxuICAgKi9cbiAgb25TeW50aGVzaXplKHNlc3Npb246IGNvbnN0cnVjdHMuSVN5bnRoZXNpc1Nlc3Npb24pOiB2b2lkO1xuXG4gIC8qKlxuICAgKiBNZXRob2QgdGhhdCBnZXRzIGNhbGxlZCB0byB2YWxpZGF0ZSBhIGNvbnN0cnVjdFxuICAgKi9cbiAgb25WYWxpZGF0ZSgpOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTWV0aG9kIHRoYXQgZ2V0cyBjYWxsZWQgdG8gcHJlcGFyZSBhIGNvbnN0cnVjdFxuICAgKi9cbiAgb25QcmVwYXJlKCk6IHZvaWQ7XG59XG4iXX0=
;