UNPKG

@aws-cdk/core

Version:

AWS Cloud Development Kit Core Library

203 lines 25.4 kB
"use strict"; 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=