UNPKG

@aws-cdk/core

Version:

AWS Cloud Development Kit Core Library

184 lines 22.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.synthesize = void 0; const cxapi = require("@aws-cdk/cx-api"); 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); return builder.buildAssembly(); } exports.synthesize = synthesize; /** * 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 !== null && inheritedAspects !== void 0 ? 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/@aws-cdk/assert/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) { visit(root, 'post', construct => { const session = { outdir: builder.outdir, assembly: builder, }; if (stack_1.Stack.isStack(construct)) { construct.synthesizer.synthesize(session); } else if (construct instanceof tree_metadata_1.TreeMetadata) { construct._synthesizeTree(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(); visit(root, 'pre', construct => { for (const message of construct.onValidate()) { errors.push({ message, source: construct }); } }); 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ludGhlc2lzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3ludGhlc2lzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlDQUF5QztBQUV6QyxnREFBNkM7QUFDN0Msc0NBQTZDO0FBRTdDLG9DQUFpQztBQUNqQyxvQ0FBd0Q7QUFDeEQsMkRBQXVEO0FBQ3ZELCtDQUEyQztBQUMzQyxtREFBK0M7QUFFL0MsU0FBZ0IsVUFBVSxDQUFDLElBQWdCLEVBQUUsVUFBNEIsRUFBRztJQUMxRSxvR0FBb0c7SUFDcEcscUJBQXFCLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRXJDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVwQix1QkFBdUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU5QixnR0FBZ0c7SUFDaEcsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRWxCLHFCQUFxQjtJQUNyQix3QkFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRWpCLCtFQUErRTtJQUMvRSxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRTtRQUMzQixZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDcEI7SUFFRCw0RUFBNEU7SUFDNUUseUJBQXlCO0lBQ3pCLE1BQU0sT0FBTyxHQUFHLGFBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCO1FBQ3ZCLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFbkQseUVBQXlFO0lBQ3pFLDhEQUE4RDtJQUM5RCxjQUFjLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRTlCLE9BQU8sT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFDO0FBQ2pDLENBQUM7QUE5QkQsZ0NBOEJDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMscUJBQXFCLENBQUMsSUFBZ0IsRUFBRSxPQUE4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QyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQ3JCLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdkYsTUFBTSxJQUFJLEtBQUssQ0FBQyxtREFBbUQsU0FBUyxFQUFFLENBQUMsQ0FBQztLQUNqRjtBQUNILENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsS0FBSyxDQUFDLElBQWdCLEVBQUUsS0FBcUIsRUFBRSxFQUEyQztJQUNqRyxJQUFJLEtBQUssS0FBSyxLQUFLLEVBQUU7UUFDbkIsRUFBRSxDQUFDLElBQWtDLENBQUMsQ0FBQztLQUN4QztJQUVELEtBQUssTUFBTSxLQUFLLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7UUFDdEMsSUFBSSxhQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQUUsU0FBUztTQUFFO1FBQ3ZDLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0tBQ3pCO0lBRUQsSUFBSSxLQUFLLEtBQUssTUFBTSxFQUFFO1FBQ3BCLEVBQUUsQ0FBQyxJQUFrQyxDQUFDLENBQUM7S0FDeEM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY3hhcGkgZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBbm5vdGF0aW9ucyB9IGZyb20gJy4uL2Fubm90YXRpb25zJztcbmltcG9ydCB7IEFzcGVjdHMsIElBc3BlY3QgfSBmcm9tICcuLi9hc3BlY3QnO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBJQ29uc3RydWN0LCBTeW50aGVzaXNPcHRpb25zLCBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tICcuLi9jb25zdHJ1Y3QtY29tcGF0JztcbmltcG9ydCB7IFN0YWNrIH0gZnJvbSAnLi4vc3RhY2snO1xuaW1wb3J0IHsgU3RhZ2UsIFN0YWdlU3ludGhlc2lzT3B0aW9ucyB9IGZyb20gJy4uL3N0YWdlJztcbmltcG9ydCB7IE1ldGFkYXRhUmVzb3VyY2UgfSBmcm9tICcuL21ldGFkYXRhLXJlc291cmNlJztcbmltcG9ydCB7IHByZXBhcmVBcHAgfSBmcm9tICcuL3ByZXBhcmUtYXBwJztcbmltcG9ydCB7IFRyZWVNZXRhZGF0YSB9IGZyb20gJy4vdHJlZS1tZXRhZGF0YSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBzeW50aGVzaXplKHJvb3Q6IElDb25zdHJ1Y3QsIG9wdGlvbnM6IFN5bnRoZXNpc09wdGlvbnMgPSB7IH0pOiBjeGFwaS5DbG91ZEFzc2VtYmx5IHtcbiAgLy8gd2Ugc3RhcnQgYnkgY2FsbGluZyBcInN5bnRoXCIgb24gYWxsIG5lc3RlZCBhc3NlbWJsaWVzICh3aGljaCB3aWxsIHRha2UgY2FyZSBvZiBhbGwgdGhlaXIgY2hpbGRyZW4pXG4gIHN5bnRoTmVzdGVkQXNzZW1ibGllcyhyb290LCBvcHRpb25zKTtcblxuICBpbnZva2VBc3BlY3RzKHJvb3QpO1xuXG4gIGluamVjdE1ldGFkYXRhUmVzb3VyY2VzKHJvb3QpO1xuXG4gIC8vIFRoaXMgaXMgbW9zdGx5IGhlcmUgZm9yIGxlZ2FjeSBwdXJwb3NlcyBhcyB0aGUgZnJhbWV3b3JrIGl0c2VsZiBkb2VzIG5vdCB1c2UgcHJlcGFyZSBhbnltb3JlLlxuICBwcmVwYXJlVHJlZShyb290KTtcblxuICAvLyByZXNvbHZlIHJlZmVyZW5jZXNcbiAgcHJlcGFyZUFwcChyb290KTtcblxuICAvLyBnaXZlIGFsbCBjaGlsZHJlbiBhbiBvcHBvcnR1bml0eSB0byB2YWxpZGF0ZSBub3cgdGhhdCB3ZSd2ZSBmaW5pc2hlZCBwcmVwYXJlXG4gIGlmICghb3B0aW9ucy5za2lwVmFsaWRhdGlvbikge1xuICAgIHZhbGlkYXRlVHJlZShyb290KTtcbiAgfVxuXG4gIC8vIGluIHVuaXQgdGVzdHMsIHdlIHN1cHBvcnQgY3JlYXRpbmcgZnJlZS1zdGFuZGluZyBzdGFja3MsIHNvIHdlIGNyZWF0ZSB0aGVcbiAgLy8gYXNzZW1ibHkgYnVpbGRlciBoZXJlLlxuICBjb25zdCBidWlsZGVyID0gU3RhZ2UuaXNTdGFnZShyb290KVxuICAgID8gcm9vdC5fYXNzZW1ibHlCdWlsZGVyXG4gICAgOiBuZXcgY3hhcGkuQ2xvdWRBc3NlbWJseUJ1aWxkZXIob3B0aW9ucy5vdXRkaXIpO1xuXG4gIC8vIG5leHQsIHdlIGludm9rZSBcIm9uU3ludGhlc2l6ZVwiIG9uIGFsbCBvZiBvdXIgY2hpbGRyZW4uIHRoaXMgd2lsbCBhbGxvd1xuICAvLyBzdGFja3MgdG8gYWRkIHRoZW1zZWx2ZXMgdG8gdGhlIHN5bnRoZXNpemVkIGNsb3VkIGFzc2VtYmx5LlxuICBzeW50aGVzaXplVHJlZShyb290LCBidWlsZGVyKTtcblxuICByZXR1cm4gYnVpbGRlci5idWlsZEFzc2VtYmx5KCk7XG59XG5cbi8qKlxuICogRmluZCBBc3NlbWJsaWVzIGluc2lkZSB0aGUgY29uc3RydWN0IGFuZCBjYWxsICdzeW50aCcgb24gdGhlbVxuICpcbiAqIChUaGV5IHdpbGwgaW4gdHVybiByZWN1cnNlIGFnYWluKVxuICovXG5mdW5jdGlvbiBzeW50aE5lc3RlZEFzc2VtYmxpZXMocm9vdDogSUNvbnN0cnVjdCwgb3B0aW9uczogU3RhZ2VTeW50aGVzaXNPcHRpb25zKSB7XG4gIGZvciAoY29uc3QgY2hpbGQgb2Ygcm9vdC5ub2RlLmNoaWxkcmVuKSB7XG4gICAgaWYgKFN0YWdlLmlzU3RhZ2UoY2hpbGQpKSB7XG4gICAgICBjaGlsZC5zeW50aChvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3ludGhOZXN0ZWRBc3NlbWJsaWVzKGNoaWxkLCBvcHRpb25zKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBJbnZva2UgYXNwZWN0cyBvbiB0aGUgZ2l2ZW4gY29uc3RydWN0IHRyZWUuXG4gKlxuICogQXNwZWN0cyBhcmUgbm90IHByb3BhZ2F0ZWQgYWNyb3NzIEFzc2VtYmx5IGJvdW5kYXJpZXMuIFRoZSBzYW1lIEFzcGVjdCB3aWxsIG5vdCBiZSBpbnZva2VkXG4gKiB0d2ljZSBmb3IgdGhlIHNhbWUgY29uc3RydWN0LlxuICovXG5mdW5jdGlvbiBpbnZva2VBc3BlY3RzKHJvb3Q6IElDb25zdHJ1Y3QpIHtcbiAgY29uc3QgaW52b2tlZEJ5UGF0aDogeyBbbm9kZVBhdGg6IHN0cmluZ106IElBc3BlY3RbXSB9ID0geyB9O1xuXG4gIGxldCBuZXN0ZWRBc3BlY3RXYXJuaW5nID0gZmFsc2U7XG4gIHJlY3Vyc2Uocm9vdCwgW10pO1xuXG4gIGZ1bmN0aW9uIHJlY3Vyc2UoY29uc3RydWN0OiBJQ29uc3RydWN0LCBpbmhlcml0ZWRBc3BlY3RzOiBjb25zdHJ1Y3RzLklBc3BlY3RbXSkge1xuICAgIGNvbnN0IG5vZGUgPSBjb25zdHJ1Y3Qubm9kZTtcbiAgICBjb25zdCBhc3BlY3RzID0gQXNwZWN0cy5vZihjb25zdHJ1Y3QpO1xuICAgIGNvbnN0IGFsbEFzcGVjdHNIZXJlID0gWy4uLmluaGVyaXRlZEFzcGVjdHMgPz8gW10sIC4uLmFzcGVjdHMuYXNwZWN0c107XG4gICAgY29uc3Qgbm9kZUFzcGVjdHNDb3VudCA9IGFzcGVjdHMuYXNwZWN0cy5sZW5ndGg7XG4gICAgZm9yIChjb25zdCBhc3BlY3Qgb2YgYWxsQXNwZWN0c0hlcmUpIHtcbiAgICAgIGxldCBpbnZva2VkID0gaW52b2tlZEJ5UGF0aFtub2RlLnBhdGhdO1xuICAgICAgaWYgKCFpbnZva2VkKSB7XG4gICAgICAgIGludm9rZWQgPSBpbnZva2VkQnlQYXRoW25vZGUucGF0aF0gPSBbXTtcbiAgICAgIH1cblxuICAgICAgaWYgKGludm9rZWQuaW5jbHVkZXMoYXNwZWN0KSkgeyBjb250aW51ZTsgfVxuXG4gICAgICBhc3BlY3QudmlzaXQoY29uc3RydWN0KTtcblxuICAgICAgLy8gaWYgYW4gYXNwZWN0IHdhcyBhZGRlZCB0byB0aGUgbm9kZSB3aGlsZSBpbnZva2luZyBhbm90aGVyIGFzcGVjdCBpdCB3aWxsIG5vdCBiZSBpbnZva2VkLCBlbWl0IGEgd2FybmluZ1xuICAgICAgLy8gdGhlIGBuZXN0ZWRBc3BlY3RXYXJuaW5nYCBmbGFnIGlzIHVzZWQgdG8gcHJldmVudCB0aGUgd2FybmluZyBmcm9tIGJlaW5nIGVtaXR0ZWQgZm9yIGV2ZXJ5IGNoaWxkXG4gICAgICBpZiAoIW5lc3RlZEFzcGVjdFdhcm5pbmcgJiYgbm9kZUFzcGVjdHNDb3VudCAhPT0gYXNwZWN0cy5hc3BlY3RzLmxlbmd0aCkge1xuICAgICAgICBBbm5vdGF0aW9ucy5vZihjb25zdHJ1Y3QpLmFkZFdhcm5pbmcoJ1dlIGRldGVjdGVkIGFuIEFzcGVjdCB3YXMgYWRkZWQgdmlhIGFub3RoZXIgQXNwZWN0LCBhbmQgd2lsbCBub3QgYmUgYXBwbGllZCcpO1xuICAgICAgICBuZXN0ZWRBc3BlY3RXYXJuaW5nID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gbWFyayBhcyBpbnZva2VkIGZvciB0aGlzIG5vZGVcbiAgICAgIGludm9rZWQucHVzaChhc3BlY3QpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgY29uc3RydWN0Lm5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIGlmICghU3RhZ2UuaXNTdGFnZShjaGlsZCkpIHtcbiAgICAgICAgcmVjdXJzZShjaGlsZCwgYWxsQXNwZWN0c0hlcmUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFByZXBhcmUgYWxsIGNvbnN0cnVjdHMgaW4gdGhlIGdpdmVuIGNvbnN0cnVjdCB0cmVlIGluIHBvc3Qtb3JkZXIuXG4gKlxuICogU3RvcCBhdCBBc3NlbWJseSBib3VuZGFyaWVzLlxuICovXG5mdW5jdGlvbiBwcmVwYXJlVHJlZShyb290OiBJQ29uc3RydWN0KSB7XG4gIHZpc2l0KHJvb3QsICdwb3N0JywgY29uc3RydWN0ID0+IGNvbnN0cnVjdC5vblByZXBhcmUoKSk7XG59XG5cbi8qKlxuICogRmluZCBhbGwgc3RhY2tzIGFuZCBhZGQgTWV0YWRhdGEgUmVzb3VyY2VzIHRvIGFsbCBvZiB0aGVtXG4gKlxuICogVGhlcmUgaXMgbm8gZ29vZCBnZW5lcmljIHBsYWNlIHRvIGRvIHRoaXMuIENhbid0IGRvIGl0IGluIHRoZSBjb25zdHJ1Y3RvclxuICogKGJlY2F1c2UgYWRkaW5nIGEgY2hpbGQgY29uc3RydWN0IG1ha2VzIGl0IGltcG9zc2libGUgdG8gc2V0IGNvbnRleHQgb24gdGhlXG4gKiBub2RlKSwgYW5kIHRoZSBnZW5lcmljIHByZXBhcmUgcGhhc2UgaXMgZGVwcmVjYXRlZC5cbiAqXG4gKiBPbmx5IGRvIHRoaXMgb24gW3BhcmVudF0gc3RhY2tzIChub3QgbmVzdGVkIHN0YWNrcyksIGRvbid0IGRvIHRoaXMgd2hlblxuICogZGlzYWJsZWQgYnkgdGhlIHVzZXIuXG4gKlxuICogQWxzbywgb25seSB3aGVuIHJ1bm5pbmcgdmlhIHRoZSBDTEkuIElmIHdlIGRvIGl0IHVuY29uZGl0aW9uYWxseSxcbiAqIGFsbCB1bml0IHRlc3RzIGV2ZXJ5d2hlcmUgYXJlIGdvaW5nIHRvIGJyZWFrIG1hc3NpdmVseS4gSSd2ZSBzcGVudCBhIGRheVxuICogZml4aW5nIG91ciBvd24sIGJ1dCBkb3duc3RyZWFtIHVzZXJzIHdvdWxkIGJlIGFmZmVjdGVkIGp1c3QgYXMgYmFkbHkuXG4gKlxuICogU3RvcCBhdCBBc3NlbWJseSBib3VuZGFyaWVzLlxuICovXG5mdW5jdGlvbiBpbmplY3RNZXRhZGF0YVJlc291cmNlcyhyb290OiBJQ29uc3RydWN0KSB7XG4gIHZpc2l0KHJvb3QsICdwb3N0JywgY29uc3RydWN0ID0+IHtcbiAgICBpZiAoIVN0YWNrLmlzU3RhY2soY29uc3RydWN0KSB8fCAhY29uc3RydWN0Ll92ZXJzaW9uUmVwb3J0aW5nRW5hYmxlZCkgeyByZXR1cm47IH1cblxuICAgIC8vIEJlY2F1c2Ugb2YgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL2Jsb2IvbWFzdGVyL3BhY2thZ2VzL0Bhd3MtY2RrL2Fzc2VydC9saWIvc3ludGgtdXRpbHMudHMjTDc0XG4gICAgLy8gc3ludGhlc2l6ZSgpIG1heSBiZSBjYWxsZWQgbW9yZSB0aGFuIG9uY2Ugb24gYSBzdGFjayBpbiB1bml0IHRlc3RzLCBhbmQgdGhlIGJlbG93IHdvdWxkIGJyZWFrXG4gICAgLy8gaWYgd2UgZXhlY3V0ZSBpdCBhIHNlY29uZCB0aW1lLiBHdWFyZCBhZ2FpbnN0IHRoZSBjb25zdHJ1Y3RzIGFscmVhZHkgZXhpc3RpbmcuXG4gICAgY29uc3QgQ0RLTWV0YWRhdGEgPSAnQ0RLTWV0YWRhdGEnO1xuICAgIGlmIChjb25zdHJ1Y3Qubm9kZS50cnlGaW5kQ2hpbGQoQ0RLTWV0YWRhdGEpKSB7IHJldHVybjsgfVxuXG4gICAgbmV3IE1ldGFkYXRhUmVzb3VyY2UoY29uc3RydWN0LCBDREtNZXRhZGF0YSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFN5bnRoZXNpemUgY2hpbGRyZW4gaW4gcG9zdC1vcmRlciBpbnRvIHRoZSBnaXZlbiBidWlsZGVyXG4gKlxuICogU3RvcCBhdCBBc3NlbWJseSBib3VuZGFyaWVzLlxuICovXG5mdW5jdGlvbiBzeW50aGVzaXplVHJlZShyb290OiBJQ29uc3RydWN0LCBidWlsZGVyOiBjeGFwaS5DbG91ZEFzc2VtYmx5QnVpbGRlcikge1xuICB2aXNpdChyb290LCAncG9zdCcsIGNvbnN0cnVjdCA9PiB7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IHtcbiAgICAgIG91dGRpcjogYnVpbGRlci5vdXRkaXIsXG4gICAgICBhc3NlbWJseTogYnVpbGRlcixcbiAgICB9O1xuXG4gICAgaWYgKFN0YWNrLmlzU3RhY2soY29uc3RydWN0KSkge1xuICAgICAgY29uc3RydWN0LnN5bnRoZXNpemVyLnN5bnRoZXNpemUoc2Vzc2lvbik7XG4gICAgfSBlbHNlIGlmIChjb25zdHJ1Y3QgaW5zdGFuY2VvZiBUcmVlTWV0YWRhdGEpIHtcbiAgICAgIGNvbnN0cnVjdC5fc3ludGhlc2l6ZVRyZWUoc2Vzc2lvbik7XG4gICAgfVxuXG4gICAgLy8gdGhpcyB3aWxsIHNvb24gYmUgZGVwcmVjYXRlZCBhbmQgcmVtb3ZlZCBpbiAyLnhcbiAgICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrLXJmY3MvaXNzdWVzLzE5MlxuICAgIGNvbnN0cnVjdC5vblN5bnRoZXNpemUoc2Vzc2lvbik7XG4gIH0pO1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIGFsbCBjb25zdHJ1Y3RzIGluIHRoZSBnaXZlbiBjb25zdHJ1Y3QgdHJlZVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZVRyZWUocm9vdDogSUNvbnN0cnVjdCkge1xuICBjb25zdCBlcnJvcnMgPSBuZXcgQXJyYXk8VmFsaWRhdGlvbkVycm9yPigpO1xuXG4gIHZpc2l0KHJvb3QsICdwcmUnLCBjb25zdHJ1Y3QgPT4ge1xuICAgIGZvciAoY29uc3QgbWVzc2FnZSBvZiBjb25zdHJ1Y3Qub25WYWxpZGF0ZSgpKSB7XG4gICAgICBlcnJvcnMucHVzaCh7IG1lc3NhZ2UsIHNvdXJjZTogY29uc3RydWN0IGFzIHVua25vd24gYXMgQ29uc3RydWN0IH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgaWYgKGVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgZXJyb3JMaXN0ID0gZXJyb3JzLm1hcChlID0+IGBbJHtlLnNvdXJjZS5ub2RlLnBhdGh9XSAke2UubWVzc2FnZX1gKS5qb2luKCdcXG4gICcpO1xuICAgIHRocm93IG5ldyBFcnJvcihgVmFsaWRhdGlvbiBmYWlsZWQgd2l0aCB0aGUgZm9sbG93aW5nIGVycm9yczpcXG4gICR7ZXJyb3JMaXN0fWApO1xuICB9XG59XG5cbi8qKlxuICogVmlzaXQgdGhlIGdpdmVuIGNvbnN0cnVjdCB0cmVlIGluIGVpdGhlciBwcmUgb3IgcG9zdCBvcmRlciwgc3RvcHBpbmcgYXQgQXNzZW1ibGllc1xuICovXG5mdW5jdGlvbiB2aXNpdChyb290OiBJQ29uc3RydWN0LCBvcmRlcjogJ3ByZScgfCAncG9zdCcsIGNiOiAoeDogSVByb3RlY3RlZENvbnN0cnVjdE1ldGhvZHMpID0+IHZvaWQpIHtcbiAgaWYgKG9yZGVyID09PSAncHJlJykge1xuICAgIGNiKHJvb3QgYXMgSVByb3RlY3RlZENvbnN0cnVjdE1ldGhvZHMpO1xuICB9XG5cbiAgZm9yIChjb25zdCBjaGlsZCBvZiByb290Lm5vZGUuY2hpbGRyZW4pIHtcbiAgICBpZiAoU3RhZ2UuaXNTdGFnZShjaGlsZCkpIHsgY29udGludWU7IH1cbiAgICB2aXNpdChjaGlsZCwgb3JkZXIsIGNiKTtcbiAgfVxuXG4gIGlmIChvcmRlciA9PT0gJ3Bvc3QnKSB7XG4gICAgY2Iocm9vdCBhcyBJUHJvdGVjdGVkQ29uc3RydWN0TWV0aG9kcyk7XG4gIH1cbn1cblxuLyoqXG4gKiBJbnRlcmZhY2Ugd2hpY2ggcHJvdmlkZXMgYWNjZXNzIHRvIHNwZWNpYWwgbWV0aG9kcyBvZiBDb25zdHJ1Y3RcbiAqXG4gKiBAZXhwZXJpbWVudGFsXG4gKi9cbmludGVyZmFjZSBJUHJvdGVjdGVkQ29uc3RydWN0TWV0aG9kcyBleHRlbmRzIElDb25zdHJ1Y3Qge1xuICAvKipcbiAgICogTWV0aG9kIHRoYXQgZ2V0cyBjYWxsZWQgd2hlbiBhIGNvbnN0cnVjdCBzaG91bGQgc3ludGhlc2l6ZSBpdHNlbGYgdG8gYW4gYXNzZW1ibHlcbiAgICovXG4gIG9uU3ludGhlc2l6ZShzZXNzaW9uOiBjb25zdHJ1Y3RzLklTeW50aGVzaXNTZXNzaW9uKTogdm9pZDtcblxuICAvKipcbiAgICogTWV0aG9kIHRoYXQgZ2V0cyBjYWxsZWQgdG8gdmFsaWRhdGUgYSBjb25zdHJ1Y3RcbiAgICovXG4gIG9uVmFsaWRhdGUoKTogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0aGF0IGdldHMgY2FsbGVkIHRvIHByZXBhcmUgYSBjb25zdHJ1Y3RcbiAgICovXG4gIG9uUHJlcGFyZSgpOiB2b2lkO1xufVxuIl19