UNPKG

21.3 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const tslib_1 = require("tslib");
4const lodash_1 = tslib_1.__importDefault(require("lodash"));
5const FETCH_TIMEOUT_MS = 20000;
6const QUEUE_SIZE = 1000;
7const BATCH_SIZE = 10;
8class AsyncBlockIterator {
9 constructor({ client, options: { indexStart, indexStop, monitor }, fetchTimeoutMS = FETCH_TIMEOUT_MS, batchSize = BATCH_SIZE, }) {
10 this.client = client;
11 this.mutableItems = [];
12 this.mutableResolvers = [];
13 this.mutableDone = false;
14 this.mutableCurrentIndex = indexStart;
15 this.mutableFetching = false;
16 this.indexStop = indexStop;
17 this.fetchTimeoutMS = fetchTimeoutMS;
18 this.batchSize = batchSize;
19 this.monitor = monitor === undefined ? undefined : monitor.at('async_block_iterator');
20 }
21 [Symbol.asyncIterator]() {
22 return this;
23 }
24 async next() {
25 if (!this.mutableDone) {
26 this.fetch();
27 }
28 const item = this.mutableItems.shift();
29 if (item !== undefined) {
30 if (item.type === 'error') {
31 return Promise.reject(item.error);
32 }
33 return Promise.resolve({ done: false, value: item.value });
34 }
35 if (this.mutableDone) {
36 // tslint:disable-next-line no-any
37 return Promise.resolve({ done: true });
38 }
39 // tslint:disable-next-line promise-must-complete
40 return new Promise((resolve, reject) => {
41 this.mutableResolvers.push({ resolve, reject });
42 });
43 }
44 write(value) {
45 this.push({ type: 'value', value });
46 }
47 error(error) {
48 this.push({ type: 'error', error });
49 }
50 push(item) {
51 if (this.mutableDone) {
52 /* istanbul ignore next */
53 throw new Error('AsyncBlockIterator already ended');
54 }
55 const resolver = this.mutableResolvers.shift();
56 if (resolver !== undefined) {
57 const { resolve, reject } = resolver;
58 if (item.type === 'error') {
59 reject(item.error);
60 }
61 else {
62 resolve({ done: false, value: item.value });
63 }
64 }
65 else {
66 this.mutableItems.push(item);
67 }
68 }
69 done() {
70 // tslint:disable-next-line no-any
71 this.mutableResolvers.forEach(({ resolve }) => resolve({ done: true }));
72 // tslint:disable-next-line no-any
73 this.mutableResolvers = [];
74 this.mutableDone = true;
75 }
76 fetch() {
77 if (this.mutableFetching) {
78 return;
79 }
80 this.mutableFetching = true;
81 this.asyncFetch()
82 .then(() => {
83 this.mutableFetching = false;
84 })
85 .catch((error) => {
86 this.mutableFetching = false;
87 this.error(error);
88 });
89 }
90 async asyncFetch() {
91 let startHeight = this.mutableStartHeight;
92 let indexIn = this.mutableCurrentIndex;
93 if (startHeight === undefined || indexIn === undefined) {
94 const blockCount = await this.client.getBlockCount(this.monitor);
95 if (startHeight === undefined) {
96 startHeight = blockCount - 1;
97 this.mutableStartHeight = startHeight;
98 }
99 if (indexIn === undefined) {
100 indexIn = blockCount - 1;
101 this.mutableCurrentIndex = indexIn;
102 }
103 }
104 const index = indexIn;
105 const incIndex = (value) => {
106 if (this.mutableCurrentIndex === undefined) {
107 throw new Error('Something went wrong!');
108 }
109 this.mutableCurrentIndex += value;
110 };
111 if (this.indexStop !== undefined && index >= this.indexStop) {
112 this.done();
113 }
114 else if (index >= startHeight) {
115 const [block, newStartHeight] = await Promise.all([
116 this.fetchOne(index),
117 // Refresh the block count in case we got behind somehow
118 this.client.getBlockCount(this.monitor),
119 ]);
120 incIndex(1);
121 this.write(block);
122 this.mutableStartHeight = newStartHeight;
123 }
124 else {
125 let toFetch = Math.min(QUEUE_SIZE - this.mutableItems.length, startHeight - index);
126 if (this.indexStop !== undefined) {
127 toFetch = Math.min(toFetch, this.indexStop - index);
128 }
129 // tslint:disable-next-line no-loop-statement
130 for (const chunk of lodash_1.default.chunk(lodash_1.default.range(0, toFetch), this.batchSize)) {
131 const blocks = await Promise.all(chunk.map(async (offset) => this.fetchOne(index + offset, true)));
132 incIndex(chunk.length);
133 blocks.forEach((block) => this.write(block));
134 }
135 }
136 }
137 async fetchOne(index, isBatch = false) {
138 try {
139 // tslint:disable-next-line no-unnecessary-local-variable prefer-immediate-return
140 const block = await this.client.getBlock(index, isBatch
141 ? {
142 monitor: this.monitor,
143 }
144 : {
145 timeoutMS: this.fetchTimeoutMS,
146 monitor: this.monitor,
147 });
148 // tslint:disable-next-line no-var-before-return
149 return block;
150 }
151 catch (error) {
152 if (error.code === 'UNKNOWN_BLOCK') {
153 return this.fetchOne(index, isBatch);
154 }
155 throw error;
156 }
157 }
158}
159exports.AsyncBlockIterator = AsyncBlockIterator;
160
161//# sourceMappingURL=data:application/json;charset=utf8;base64,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dkIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO2FBQzlDO1NBQ0Y7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFhLEVBQUUsT0FBTyxHQUFHLEtBQUs7UUFDbkQsSUFBSTtZQUNGLGlGQUFpRjtZQUNqRixNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUN0QyxLQUFLLEVBQ0wsT0FBTztnQkFDTCxDQUFDLENBQUM7b0JBQ0UsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO2lCQUN0QjtnQkFDSCxDQUFDLENBQUM7b0JBQ0UsU0FBUyxFQUFFLElBQUksQ0FBQyxjQUFjO29CQUM5QixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87aUJBQ3RCLENBQ04sQ0FBQztZQUVGLGdEQUFnRDtZQUNoRCxPQUFPLEtBQUssQ0FBQztTQUNkO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssZUFBZSxFQUFFO2dCQUNsQyxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2FBQ3RDO1lBRUQsTUFBTSxLQUFjLENBQUM7U0FDdEI7SUFDSCxDQUFDO0NBQ0Y7QUEzTEQsZ0RBMkxDIiwiZmlsZSI6Im5lby1vbmUtY2xpZW50LWNvcmUvc3JjL0FzeW5jQmxvY2tJdGVyYXRvci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJsb2NrLCBHZXRPcHRpb25zLCBJdGVyT3B0aW9ucyB9IGZyb20gJ0BuZW8tb25lL2NsaWVudC1jb21tb24nO1xuaW1wb3J0IHsgTW9uaXRvciB9IGZyb20gJ0BuZW8tb25lL21vbml0b3InO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcblxudHlwZSBJdGVtID0geyByZWFkb25seSB0eXBlOiAndmFsdWUnOyByZWFkb25seSB2YWx1ZTogQmxvY2sgfSB8IHsgcmVhZG9ubHkgdHlwZTogJ2Vycm9yJzsgcmVhZG9ubHkgZXJyb3I6IEVycm9yIH07XG5pbnRlcmZhY2UgUmVzb2x2ZXIge1xuICByZWFkb25seSByZXNvbHZlOiAodmFsdWU6IEl0ZXJhdG9yUmVzdWx0PEJsb2NrPikgPT4gdm9pZDtcbiAgcmVhZG9ubHkgcmVqZWN0OiAocmVhc29uOiBFcnJvcikgPT4gdm9pZDtcbn1cblxuaW50ZXJmYWNlIENsaWVudCB7XG4gIHJlYWRvbmx5IGdldEJsb2NrQ291bnQ6IChtb25pdG9yPzogTW9uaXRvcikgPT4gUHJvbWlzZTxudW1iZXI+O1xuICByZWFkb25seSBnZXRCbG9jazogKGluZGV4OiBudW1iZXIsIG9wdGlvbnM/OiBHZXRPcHRpb25zKSA9PiBQcm9taXNlPEJsb2NrPjtcbn1cblxuaW50ZXJmYWNlIEFzeW5jQmxvY2tJdGVyYXRvck9wdGlvbnMge1xuICByZWFkb25seSBjbGllbnQ6IENsaWVudDtcbiAgcmVhZG9ubHkgb3B0aW9uczogSXRlck9wdGlvbnM7XG4gIHJlYWRvbmx5IGZldGNoVGltZW91dE1TPzogbnVtYmVyO1xuICByZWFkb25seSBiYXRjaFNpemU/OiBudW1iZXI7XG59XG5cbmNvbnN0IEZFVENIX1RJTUVPVVRfTVMgPSAyMDAwMDtcbmNvbnN0IFFVRVVFX1NJWkUgPSAxMDAwO1xuY29uc3QgQkFUQ0hfU0laRSA9IDEwO1xuXG5leHBvcnQgY2xhc3MgQXN5bmNCbG9ja0l0ZXJhdG9yIGltcGxlbWVudHMgQXN5bmNJdGVyYXRvcjxCbG9jaz4ge1xuICBwcml2YXRlIHJlYWRvbmx5IGNsaWVudDogQ2xpZW50O1xuICBwcml2YXRlIHJlYWRvbmx5IG11dGFibGVJdGVtczogSXRlbVtdO1xuICBwcml2YXRlIG11dGFibGVSZXNvbHZlcnM6IFJlc29sdmVyW107XG4gIHByaXZhdGUgbXV0YWJsZURvbmU6IGJvb2xlYW47XG4gIHByaXZhdGUgbXV0YWJsZUN1cnJlbnRJbmRleDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIG11dGFibGVGZXRjaGluZzogYm9vbGVhbjtcbiAgcHJpdmF0ZSBtdXRhYmxlU3RhcnRIZWlnaHQ6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmRleFN0b3A6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSBmZXRjaFRpbWVvdXRNUzogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGJhdGNoU2l6ZTogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IG1vbml0b3I6IE1vbml0b3IgfCB1bmRlZmluZWQ7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHtcbiAgICBjbGllbnQsXG4gICAgb3B0aW9uczogeyBpbmRleFN0YXJ0LCBpbmRleFN0b3AsIG1vbml0b3IgfSxcbiAgICBmZXRjaFRpbWVvdXRNUyA9IEZFVENIX1RJTUVPVVRfTVMsXG4gICAgYmF0Y2hTaXplID0gQkFUQ0hfU0laRSxcbiAgfTogQXN5bmNCbG9ja0l0ZXJhdG9yT3B0aW9ucykge1xuICAgIHRoaXMuY2xpZW50ID0gY2xpZW50O1xuICAgIHRoaXMubXV0YWJsZUl0ZW1zID0gW107XG4gICAgdGhpcy5tdXRhYmxlUmVzb2x2ZXJzID0gW107XG4gICAgdGhpcy5tdXRhYmxlRG9uZSA9IGZhbHNlO1xuICAgIHRoaXMubXV0YWJsZUN1cnJlbnRJbmRleCA9IGluZGV4U3RhcnQ7XG4gICAgdGhpcy5tdXRhYmxlRmV0Y2hpbmcgPSBmYWxzZTtcbiAgICB0aGlzLmluZGV4U3RvcCA9IGluZGV4U3RvcDtcbiAgICB0aGlzLmZldGNoVGltZW91dE1TID0gZmV0Y2hUaW1lb3V0TVM7XG4gICAgdGhpcy5iYXRjaFNpemUgPSBiYXRjaFNpemU7XG4gICAgdGhpcy5tb25pdG9yID0gbW9uaXRvciA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogbW9uaXRvci5hdCgnYXN5bmNfYmxvY2tfaXRlcmF0b3InKTtcbiAgfVxuXG4gIHB1YmxpYyBbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIG5leHQoKTogUHJvbWlzZTxJdGVyYXRvclJlc3VsdDxCbG9jaz4+IHtcbiAgICBpZiAoIXRoaXMubXV0YWJsZURvbmUpIHtcbiAgICAgIHRoaXMuZmV0Y2goKTtcbiAgICB9XG5cbiAgICBjb25zdCBpdGVtID0gdGhpcy5tdXRhYmxlSXRlbXMuc2hpZnQoKTtcbiAgICBpZiAoaXRlbSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoaXRlbS50eXBlID09PSAnZXJyb3InKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChpdGVtLmVycm9yKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IGRvbmU6IGZhbHNlLCB2YWx1ZTogaXRlbS52YWx1ZSB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5tdXRhYmxlRG9uZSkge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWFueVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IGRvbmU6IHRydWUgfSBhcyBhbnkpO1xuICAgIH1cblxuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBwcm9taXNlLW11c3QtY29tcGxldGVcbiAgICByZXR1cm4gbmV3IFByb21pc2U8SXRlcmF0b3JSZXN1bHQ8QmxvY2s+PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLm11dGFibGVSZXNvbHZlcnMucHVzaCh7IHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgd3JpdGUodmFsdWU6IEJsb2NrKTogdm9pZCB7XG4gICAgdGhpcy5wdXNoKHsgdHlwZTogJ3ZhbHVlJywgdmFsdWUgfSk7XG4gIH1cblxuICBwcml2YXRlIGVycm9yKGVycm9yOiBFcnJvcik6IHZvaWQge1xuICAgIHRoaXMucHVzaCh7IHR5cGU6ICdlcnJvcicsIGVycm9yIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBwdXNoKGl0ZW06IEl0ZW0pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5tdXRhYmxlRG9uZSkge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHRocm93IG5ldyBFcnJvcignQXN5bmNCbG9ja0l0ZXJhdG9yIGFscmVhZHkgZW5kZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNvbHZlciA9IHRoaXMubXV0YWJsZVJlc29sdmVycy5zaGlmdCgpO1xuICAgIGlmIChyZXNvbHZlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCB7IHJlc29sdmUsIHJlamVjdCB9ID0gcmVzb2x2ZXI7XG4gICAgICBpZiAoaXRlbS50eXBlID09PSAnZXJyb3InKSB7XG4gICAgICAgIHJlamVjdChpdGVtLmVycm9yKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc29sdmUoeyBkb25lOiBmYWxzZSwgdmFsdWU6IGl0ZW0udmFsdWUgfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubXV0YWJsZUl0ZW1zLnB1c2goaXRlbSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBkb25lKCk6IHZvaWQge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1hbnlcbiAgICB0aGlzLm11dGFibGVSZXNvbHZlcnMuZm9yRWFjaCgoeyByZXNvbHZlIH0pID0+IHJlc29sdmUoeyBkb25lOiB0cnVlIH0gYXMgYW55KSk7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWFueVxuICAgIHRoaXMubXV0YWJsZVJlc29sdmVycyA9IFtdO1xuICAgIHRoaXMubXV0YWJsZURvbmUgPSB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBmZXRjaCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5tdXRhYmxlRmV0Y2hpbmcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5tdXRhYmxlRmV0Y2hpbmcgPSB0cnVlO1xuICAgIHRoaXMuYXN5bmNGZXRjaCgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMubXV0YWJsZUZldGNoaW5nID0gZmFsc2U7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICB0aGlzLm11dGFibGVGZXRjaGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVycm9yKGVycm9yKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBhc3luY0ZldGNoKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxldCBzdGFydEhlaWdodCA9IHRoaXMubXV0YWJsZVN0YXJ0SGVpZ2h0O1xuICAgIGxldCBpbmRleEluID0gdGhpcy5tdXRhYmxlQ3VycmVudEluZGV4O1xuICAgIGlmIChzdGFydEhlaWdodCA9PT0gdW5kZWZpbmVkIHx8IGluZGV4SW4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgYmxvY2tDb3VudCA9IGF3YWl0IHRoaXMuY2xpZW50LmdldEJsb2NrQ291bnQodGhpcy5tb25pdG9yKTtcbiAgICAgIGlmIChzdGFydEhlaWdodCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHN0YXJ0SGVpZ2h0ID0gYmxvY2tDb3VudCAtIDE7XG4gICAgICAgIHRoaXMubXV0YWJsZVN0YXJ0SGVpZ2h0ID0gc3RhcnRIZWlnaHQ7XG4gICAgICB9XG4gICAgICBpZiAoaW5kZXhJbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGluZGV4SW4gPSBibG9ja0NvdW50IC0gMTtcbiAgICAgICAgdGhpcy5tdXRhYmxlQ3VycmVudEluZGV4ID0gaW5kZXhJbjtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgaW5kZXggPSBpbmRleEluO1xuXG4gICAgY29uc3QgaW5jSW5kZXggPSAodmFsdWU6IG51bWJlcikgPT4ge1xuICAgICAgaWYgKHRoaXMubXV0YWJsZUN1cnJlbnRJbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignU29tZXRoaW5nIHdlbnQgd3JvbmchJyk7XG4gICAgICB9XG4gICAgICB0aGlzLm11dGFibGVDdXJyZW50SW5kZXggKz0gdmFsdWU7XG4gICAgfTtcblxuICAgIGlmICh0aGlzLmluZGV4U3RvcCAhPT0gdW5kZWZpbmVkICYmIGluZGV4ID49IHRoaXMuaW5kZXhTdG9wKSB7XG4gICAgICB0aGlzLmRvbmUoKTtcbiAgICB9IGVsc2UgaWYgKGluZGV4ID49IHN0YXJ0SGVpZ2h0KSB7XG4gICAgICBjb25zdCBbYmxvY2ssIG5ld1N0YXJ0SGVpZ2h0XSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgdGhpcy5mZXRjaE9uZShpbmRleCksXG4gICAgICAgIC8vIFJlZnJlc2ggdGhlIGJsb2NrIGNvdW50IGluIGNhc2Ugd2UgZ290IGJlaGluZCBzb21laG93XG4gICAgICAgIHRoaXMuY2xpZW50LmdldEJsb2NrQ291bnQodGhpcy5tb25pdG9yKSxcbiAgICAgIF0pO1xuXG4gICAgICBpbmNJbmRleCgxKTtcbiAgICAgIHRoaXMud3JpdGUoYmxvY2spO1xuICAgICAgdGhpcy5tdXRhYmxlU3RhcnRIZWlnaHQgPSBuZXdTdGFydEhlaWdodDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHRvRmV0Y2ggPSBNYXRoLm1pbihRVUVVRV9TSVpFIC0gdGhpcy5tdXRhYmxlSXRlbXMubGVuZ3RoLCBzdGFydEhlaWdodCAtIGluZGV4KTtcblxuICAgICAgaWYgKHRoaXMuaW5kZXhTdG9wICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdG9GZXRjaCA9IE1hdGgubWluKHRvRmV0Y2gsIHRoaXMuaW5kZXhTdG9wIC0gaW5kZXgpO1xuICAgICAgfVxuXG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tbG9vcC1zdGF0ZW1lbnRcbiAgICAgIGZvciAoY29uc3QgY2h1bmsgb2YgXy5jaHVuayhfLnJhbmdlKDAsIHRvRmV0Y2gpLCB0aGlzLmJhdGNoU2l6ZSkpIHtcbiAgICAgICAgY29uc3QgYmxvY2tzID0gYXdhaXQgUHJvbWlzZS5hbGwoY2h1bmsubWFwKGFzeW5jIChvZmZzZXQpID0+IHRoaXMuZmV0Y2hPbmUoaW5kZXggKyBvZmZzZXQsIHRydWUpKSk7XG5cbiAgICAgICAgaW5jSW5kZXgoY2h1bmsubGVuZ3RoKTtcbiAgICAgICAgYmxvY2tzLmZvckVhY2goKGJsb2NrKSA9PiB0aGlzLndyaXRlKGJsb2NrKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmZXRjaE9uZShpbmRleDogbnVtYmVyLCBpc0JhdGNoID0gZmFsc2UpOiBQcm9taXNlPEJsb2NrPiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby11bm5lY2Vzc2FyeS1sb2NhbC12YXJpYWJsZSBwcmVmZXItaW1tZWRpYXRlLXJldHVyblxuICAgICAgY29uc3QgYmxvY2sgPSBhd2FpdCB0aGlzLmNsaWVudC5nZXRCbG9jayhcbiAgICAgICAgaW5kZXgsXG4gICAgICAgIGlzQmF0Y2hcbiAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgbW9uaXRvcjogdGhpcy5tb25pdG9yLFxuICAgICAgICAgICAgfVxuICAgICAgICAgIDoge1xuICAgICAgICAgICAgICB0aW1lb3V0TVM6IHRoaXMuZmV0Y2hUaW1lb3V0TVMsXG4gICAgICAgICAgICAgIG1vbml0b3I6IHRoaXMubW9uaXRvcixcbiAgICAgICAgICAgIH0sXG4gICAgICApO1xuXG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tdmFyLWJlZm9yZS1yZXR1cm5cbiAgICAgIHJldHVybiBibG9jaztcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yLmNvZGUgPT09ICdVTktOT1dOX0JMT0NLJykge1xuICAgICAgICByZXR1cm4gdGhpcy5mZXRjaE9uZShpbmRleCwgaXNCYXRjaCk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGVycm9yIGFzIEVycm9yO1xuICAgIH1cbiAgfVxufVxuIl19