@angular/core 9.0.0-rc.9 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/core-testing.umd.js +10 -9
- package/bundles/core-testing.umd.js.map +1 -1
- package/bundles/core-testing.umd.min.js +6 -6
- package/bundles/core-testing.umd.min.js.map +1 -1
- package/bundles/core.umd.js +3619 -3914
- package/bundles/core.umd.js.map +1 -1
- package/bundles/core.umd.min.js +182 -175
- package/bundles/core.umd.min.js.map +1 -1
- package/core.d.ts +483 -651
- package/core.metadata.json +1 -1
- package/esm2015/core.js +17 -17
- package/esm2015/index.js +2 -2
- package/esm2015/public_api.js +2 -2
- package/esm2015/src/application_ref.js +7 -7
- package/esm2015/src/core.js +3 -3
- package/esm2015/src/core_private_export.js +7 -7
- package/esm2015/src/core_render3_private_export.js +2 -2
- package/esm2015/src/debug/debug_node.js +44 -12
- package/esm2015/src/i18n/locale_data_api.js +1 -2
- package/esm2015/src/interface/type.js +1 -1
- package/esm2015/src/metadata/ng_module.js +1 -1
- package/esm2015/src/render/api.js +4 -1
- package/esm2015/src/render3/assert.js +9 -1
- package/esm2015/src/render3/bindings.js +16 -5
- package/esm2015/src/render3/component.js +54 -25
- package/esm2015/src/render3/component_ref.js +11 -15
- package/esm2015/src/render3/definition.js +3 -1
- package/esm2015/src/render3/di.js +3 -4
- package/esm2015/src/render3/di_setup.js +5 -7
- package/esm2015/src/render3/errors.js +3 -1
- package/esm2015/src/render3/features/inherit_definition_feature.js +41 -13
- package/esm2015/src/render3/features/ng_onchanges_feature.js +2 -2
- package/esm2015/src/render3/global_utils_api.js +3 -3
- package/esm2015/src/render3/i18n.js +60 -56
- package/esm2015/src/render3/index.js +2 -2
- package/esm2015/src/render3/instructions/advance.js +10 -11
- package/esm2015/src/render3/instructions/all.js +4 -5
- package/esm2015/src/render3/instructions/attribute.js +6 -6
- package/esm2015/src/render3/instructions/attribute_interpolation.js +40 -21
- package/esm2015/src/render3/instructions/change_detection.js +8 -23
- package/esm2015/src/render3/instructions/class_map_interpolation.js +13 -12
- package/esm2015/src/render3/instructions/container.js +15 -12
- package/esm2015/src/render3/instructions/element.js +40 -127
- package/esm2015/src/render3/instructions/element_container.js +8 -10
- package/esm2015/src/render3/instructions/embedded_view.js +7 -7
- package/esm2015/src/render3/instructions/host_property.js +10 -7
- package/esm2015/src/render3/instructions/listener.js +18 -16
- package/esm2015/src/render3/instructions/lview_debug.js +160 -23
- package/esm2015/src/render3/instructions/projection.js +7 -5
- package/esm2015/src/render3/instructions/property.js +27 -6
- package/esm2015/src/render3/instructions/property_interpolation.js +40 -22
- package/esm2015/src/render3/instructions/shared.js +267 -240
- package/esm2015/src/render3/instructions/storage.js +6 -8
- package/esm2015/src/render3/instructions/style_prop_interpolation.js +12 -12
- package/esm2015/src/render3/instructions/styling.js +731 -475
- package/esm2015/src/render3/instructions/text.js +5 -5
- package/esm2015/src/render3/interfaces/definition.js +41 -1
- package/esm2015/src/render3/interfaces/node.js +160 -115
- package/esm2015/src/render3/interfaces/styling.js +183 -375
- package/esm2015/src/render3/interfaces/view.js +10 -2
- package/esm2015/src/render3/jit/environment.js +1 -3
- package/esm2015/src/render3/node_manipulation.js +177 -57
- package/esm2015/src/render3/node_selector_matcher.js +39 -24
- package/esm2015/src/render3/node_util.js +12 -7
- package/esm2015/src/render3/pipe.js +4 -6
- package/esm2015/src/render3/query.js +32 -26
- package/esm2015/src/render3/state.js +54 -183
- package/esm2015/src/render3/styling/class_differ.js +47 -0
- package/esm2015/src/render3/styling/static_styling.js +54 -0
- package/esm2015/src/render3/styling/style_binding_list.js +437 -0
- package/esm2015/src/render3/styling/styling_parser.js +336 -0
- package/esm2015/src/render3/tokens.js +2 -2
- package/esm2015/src/render3/util/attrs_utils.js +125 -2
- package/esm2015/src/render3/util/change_detection_utils.js +33 -0
- package/esm2015/src/render3/util/discovery_utils.js +146 -119
- package/esm2015/src/render3/util/global_utils.js +5 -5
- package/esm2015/src/render3/util/view_utils.js +6 -6
- package/esm2015/src/render3/view_engine_compatibility.js +16 -17
- package/esm2015/src/render3/view_ref.js +16 -13
- package/esm2015/src/sanitization/bypass.js +1 -1
- package/esm2015/src/sanitization/sanitization.js +20 -5
- package/esm2015/src/util/array_utils.js +240 -1
- package/esm2015/src/util/assert.js +37 -21
- package/esm2015/src/util/char_code.js +8 -0
- package/esm2015/src/util/iterable.js +4 -1
- package/esm2015/src/util/ng_dev_mode.js +1 -12
- package/esm2015/src/util/stringify.js +14 -1
- package/esm2015/src/version.js +1 -1
- package/esm2015/testing/src/r3_test_bed.js +5 -1
- package/esm2015/testing/src/r3_test_bed_compiler.js +2 -12
- package/esm2015/testing/src/styling.js +103 -0
- package/esm5/core.js +17 -17
- package/esm5/src/application_ref.js +6 -6
- package/esm5/src/core_private_export.js +7 -7
- package/esm5/src/core_render3_private_export.js +2 -2
- package/esm5/src/debug/debug_node.js +29 -11
- package/esm5/src/i18n/locale_data_api.js +1 -2
- package/esm5/src/interface/type.js +1 -1
- package/esm5/src/metadata/ng_module.js +1 -1
- package/esm5/src/render/api.js +4 -1
- package/esm5/src/render3/assert.js +4 -1
- package/esm5/src/render3/bindings.js +19 -2
- package/esm5/src/render3/component.js +47 -22
- package/esm5/src/render3/component_ref.js +9 -14
- package/esm5/src/render3/definition.js +3 -1
- package/esm5/src/render3/di.js +3 -4
- package/esm5/src/render3/di_setup.js +4 -5
- package/esm5/src/render3/errors.js +3 -1
- package/esm5/src/render3/features/inherit_definition_feature.js +36 -12
- package/esm5/src/render3/features/ng_onchanges_feature.js +1 -1
- package/esm5/src/render3/global_utils_api.js +3 -3
- package/esm5/src/render3/i18n.js +51 -51
- package/esm5/src/render3/index.js +2 -2
- package/esm5/src/render3/instructions/advance.js +9 -11
- package/esm5/src/render3/instructions/all.js +1 -2
- package/esm5/src/render3/instructions/attribute.js +5 -6
- package/esm5/src/render3/instructions/attribute_interpolation.js +31 -21
- package/esm5/src/render3/instructions/change_detection.js +8 -21
- package/esm5/src/render3/instructions/class_map_interpolation.js +13 -12
- package/esm5/src/render3/instructions/container.js +13 -12
- package/esm5/src/render3/instructions/element.js +36 -108
- package/esm5/src/render3/instructions/element_container.js +8 -9
- package/esm5/src/render3/instructions/embedded_view.js +7 -7
- package/esm5/src/render3/instructions/host_property.js +8 -7
- package/esm5/src/render3/instructions/listener.js +13 -13
- package/esm5/src/render3/instructions/lview_debug.js +56 -15
- package/esm5/src/render3/instructions/projection.js +6 -5
- package/esm5/src/render3/instructions/property.js +17 -6
- package/esm5/src/render3/instructions/property_interpolation.js +31 -23
- package/esm5/src/render3/instructions/shared.js +247 -207
- package/esm5/src/render3/instructions/storage.js +4 -6
- package/esm5/src/render3/instructions/style_prop_interpolation.js +12 -12
- package/esm5/src/render3/instructions/styling.js +685 -367
- package/esm5/src/render3/instructions/text.js +5 -5
- package/esm5/src/render3/interfaces/definition.js +1 -1
- package/esm5/src/render3/interfaces/node.js +49 -1
- package/esm5/src/render3/interfaces/styling.js +57 -1
- package/esm5/src/render3/interfaces/view.js +1 -1
- package/esm5/src/render3/jit/environment.js +1 -3
- package/esm5/src/render3/node_manipulation.js +167 -54
- package/esm5/src/render3/node_selector_matcher.js +40 -20
- package/esm5/src/render3/node_util.js +12 -7
- package/esm5/src/render3/pipe.js +4 -6
- package/esm5/src/render3/query.js +25 -24
- package/esm5/src/render3/state.js +34 -131
- package/esm5/src/render3/styling/class_differ.js +39 -0
- package/esm5/src/render3/styling/static_styling.js +42 -0
- package/esm5/src/render3/styling/style_binding_list.js +411 -0
- package/esm5/src/render3/styling/styling_parser.js +265 -0
- package/esm5/src/render3/tokens.js +2 -2
- package/esm5/src/render3/util/attrs_utils.js +117 -2
- package/esm5/src/render3/util/change_detection_utils.js +23 -0
- package/esm5/src/render3/util/discovery_utils.js +115 -99
- package/esm5/src/render3/util/global_utils.js +5 -5
- package/esm5/src/render3/util/view_utils.js +5 -5
- package/esm5/src/render3/view_engine_compatibility.js +37 -39
- package/esm5/src/render3/view_ref.js +14 -13
- package/esm5/src/sanitization/bypass.js +1 -1
- package/esm5/src/sanitization/sanitization.js +16 -5
- package/esm5/src/util/array_utils.js +240 -1
- package/esm5/src/util/assert.js +37 -21
- package/esm5/src/util/char_code.js +8 -0
- package/esm5/src/util/iterable.js +4 -1
- package/esm5/src/util/ng_dev_mode.js +1 -12
- package/esm5/src/util/stringify.js +14 -1
- package/esm5/src/version.js +1 -1
- package/esm5/testing/src/r3_test_bed.js +9 -1
- package/esm5/testing/src/r3_test_bed_compiler.js +2 -9
- package/esm5/testing/src/styling.js +82 -0
- package/fesm2015/core.js +5917 -6880
- package/fesm2015/core.js.map +1 -1
- package/fesm2015/testing.js +6 -12
- package/fesm2015/testing.js.map +1 -1
- package/fesm5/core.js +3588 -3884
- package/fesm5/core.js.map +1 -1
- package/fesm5/testing.js +10 -9
- package/fesm5/testing.js.map +1 -1
- package/package.json +1 -1
- package/src/r3_symbols.d.ts +1 -1
- package/testing/testing.d.ts +1 -3
- package/testing/testing.metadata.json +1 -1
- package/testing.d.ts +1 -1
- package/esm2015/global.js +0 -7
- package/esm2015/src/render3/instructions/alloc_host_vars.js +0 -80
- package/esm2015/src/render3/styling/bindings.js +0 -1248
- package/esm2015/src/render3/styling/map_based_bindings.js +0 -384
- package/esm2015/src/render3/styling/state.js +0 -135
- package/esm2015/src/render3/styling/styling_debug.js +0 -655
- package/esm2015/src/render3/util/styling_utils.js +0 -625
- package/esm5/global.js +0 -9
- package/esm5/src/render3/instructions/alloc_host_vars.js +0 -62
- package/esm5/src/render3/styling/bindings.js +0 -949
- package/esm5/src/render3/styling/map_based_bindings.js +0 -310
- package/esm5/src/render3/styling/state.js +0 -56
- package/esm5/src/render3/styling/styling_debug.js +0 -315
- package/esm5/src/render3/util/styling_utils.js +0 -378
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google Inc. All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import { keyValueArrayIndexOf } from '../../util/array_utils';
|
|
9
|
+
import { assertDataInRange, assertEqual, assertNotEqual } from '../../util/assert';
|
|
10
|
+
import { assertFirstUpdatePass } from '../assert';
|
|
11
|
+
import { getTStylingRangeNext, getTStylingRangePrev, setTStylingRangeNext, setTStylingRangeNextDuplicate, setTStylingRangePrev, setTStylingRangePrevDuplicate, toTStylingRange } from '../interfaces/styling';
|
|
12
|
+
import { getTView } from '../state';
|
|
13
|
+
/**
|
|
14
|
+
* NOTE: The word `styling` is used interchangeably as style or class styling.
|
|
15
|
+
*
|
|
16
|
+
* This file contains code to link styling instructions together so that they can be replayed in
|
|
17
|
+
* priority order. The file exists because Ivy styling instruction execution order does not match
|
|
18
|
+
* that of the priority order. The purpose of this code is to create a linked list so that the
|
|
19
|
+
* instructions can be traversed in priority order when computing the styles.
|
|
20
|
+
*
|
|
21
|
+
* Assume we are dealing with the following code:
|
|
22
|
+
* ```
|
|
23
|
+
* @Component({
|
|
24
|
+
* template: `
|
|
25
|
+
* <my-cmp [style]=" {color: '#001'} "
|
|
26
|
+
* [style.color]=" #002 "
|
|
27
|
+
* dir-style-color-1
|
|
28
|
+
* dir-style-color-2> `
|
|
29
|
+
* })
|
|
30
|
+
* class ExampleComponent {
|
|
31
|
+
* static ngComp = ... {
|
|
32
|
+
* ...
|
|
33
|
+
* // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
|
|
34
|
+
* ɵɵstyleMap({color: '#001'});
|
|
35
|
+
* ɵɵstyleProp('color', '#002');
|
|
36
|
+
* ...
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
*
|
|
40
|
+
* @Directive({
|
|
41
|
+
* selector: `[dir-style-color-1]',
|
|
42
|
+
* })
|
|
43
|
+
* class Style1Directive {
|
|
44
|
+
* @HostBinding('style') style = {color: '#005'};
|
|
45
|
+
* @HostBinding('style.color') color = '#006';
|
|
46
|
+
*
|
|
47
|
+
* static ngDir = ... {
|
|
48
|
+
* ...
|
|
49
|
+
* // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
|
|
50
|
+
* ɵɵstyleMap({color: '#005'});
|
|
51
|
+
* ɵɵstyleProp('color', '#006');
|
|
52
|
+
* ...
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
*
|
|
56
|
+
* @Directive({
|
|
57
|
+
* selector: `[dir-style-color-2]',
|
|
58
|
+
* })
|
|
59
|
+
* class Style2Directive {
|
|
60
|
+
* @HostBinding('style') style = {color: '#007'};
|
|
61
|
+
* @HostBinding('style.color') color = '#008';
|
|
62
|
+
*
|
|
63
|
+
* static ngDir = ... {
|
|
64
|
+
* ...
|
|
65
|
+
* // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
|
|
66
|
+
* ɵɵstyleMap({color: '#007'});
|
|
67
|
+
* ɵɵstyleProp('color', '#008');
|
|
68
|
+
* ...
|
|
69
|
+
* }
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* @Directive({
|
|
73
|
+
* selector: `my-cmp',
|
|
74
|
+
* })
|
|
75
|
+
* class MyComponent {
|
|
76
|
+
* @HostBinding('style') style = {color: '#003'};
|
|
77
|
+
* @HostBinding('style.color') color = '#004';
|
|
78
|
+
*
|
|
79
|
+
* static ngComp = ... {
|
|
80
|
+
* ...
|
|
81
|
+
* // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
|
|
82
|
+
* ɵɵstyleMap({color: '#003'});
|
|
83
|
+
* ɵɵstyleProp('color', '#004');
|
|
84
|
+
* ...
|
|
85
|
+
* }
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* The Order of instruction execution is:
|
|
90
|
+
*
|
|
91
|
+
* NOTE: the comment binding location is for illustrative purposes only.
|
|
92
|
+
*
|
|
93
|
+
* ```
|
|
94
|
+
* // Template: (ExampleComponent)
|
|
95
|
+
* ɵɵstyleMap({color: '#001'}); // Binding index: 10
|
|
96
|
+
* ɵɵstyleProp('color', '#002'); // Binding index: 12
|
|
97
|
+
* // MyComponent
|
|
98
|
+
* ɵɵstyleMap({color: '#003'}); // Binding index: 20
|
|
99
|
+
* ɵɵstyleProp('color', '#004'); // Binding index: 22
|
|
100
|
+
* // Style1Directive
|
|
101
|
+
* ɵɵstyleMap({color: '#005'}); // Binding index: 24
|
|
102
|
+
* ɵɵstyleProp('color', '#006'); // Binding index: 26
|
|
103
|
+
* // Style2Directive
|
|
104
|
+
* ɵɵstyleMap({color: '#007'}); // Binding index: 28
|
|
105
|
+
* ɵɵstyleProp('color', '#008'); // Binding index: 30
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* The correct priority order of concatenation is:
|
|
109
|
+
*
|
|
110
|
+
* ```
|
|
111
|
+
* // MyComponent
|
|
112
|
+
* ɵɵstyleMap({color: '#003'}); // Binding index: 20
|
|
113
|
+
* ɵɵstyleProp('color', '#004'); // Binding index: 22
|
|
114
|
+
* // Style1Directive
|
|
115
|
+
* ɵɵstyleMap({color: '#005'}); // Binding index: 24
|
|
116
|
+
* ɵɵstyleProp('color', '#006'); // Binding index: 26
|
|
117
|
+
* // Style2Directive
|
|
118
|
+
* ɵɵstyleMap({color: '#007'}); // Binding index: 28
|
|
119
|
+
* ɵɵstyleProp('color', '#008'); // Binding index: 30
|
|
120
|
+
* // Template: (ExampleComponent)
|
|
121
|
+
* ɵɵstyleMap({color: '#001'}); // Binding index: 10
|
|
122
|
+
* ɵɵstyleProp('color', '#002'); // Binding index: 12
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* What color should be rendered?
|
|
126
|
+
*
|
|
127
|
+
* Once the items are correctly sorted in the list, the answer is simply the last item in the
|
|
128
|
+
* concatenation list which is `#002`.
|
|
129
|
+
*
|
|
130
|
+
* To do so we keep a linked list of all of the bindings which pertain to this element.
|
|
131
|
+
* Notice that the bindings are inserted in the order of execution, but the `TView.data` allows
|
|
132
|
+
* us to traverse them in the order of priority.
|
|
133
|
+
*
|
|
134
|
+
* |Idx|`TView.data`|`LView` | Notes
|
|
135
|
+
* |---|------------|-----------------|--------------
|
|
136
|
+
* |...| | |
|
|
137
|
+
* |10 |`null` |`{color: '#001'}`| `ɵɵstyleMap('color', {color: '#001'})`
|
|
138
|
+
* |11 |`30 | 12` | ... |
|
|
139
|
+
* |12 |`color` |`'#002'` | `ɵɵstyleProp('color', '#002')`
|
|
140
|
+
* |13 |`10 | 0` | ... |
|
|
141
|
+
* |...| | |
|
|
142
|
+
* |20 |`null` |`{color: '#003'}`| `ɵɵstyleMap('color', {color: '#003'})`
|
|
143
|
+
* |21 |`0 | 22` | ... |
|
|
144
|
+
* |22 |`color` |`'#004'` | `ɵɵstyleProp('color', '#004')`
|
|
145
|
+
* |23 |`20 | 24` | ... |
|
|
146
|
+
* |24 |`null` |`{color: '#005'}`| `ɵɵstyleMap('color', {color: '#005'})`
|
|
147
|
+
* |25 |`22 | 26` | ... |
|
|
148
|
+
* |26 |`color` |`'#006'` | `ɵɵstyleProp('color', '#006')`
|
|
149
|
+
* |27 |`24 | 28` | ... |
|
|
150
|
+
* |28 |`null` |`{color: '#007'}`| `ɵɵstyleMap('color', {color: '#007'})`
|
|
151
|
+
* |29 |`26 | 30` | ... |
|
|
152
|
+
* |30 |`color` |`'#008'` | `ɵɵstyleProp('color', '#008')`
|
|
153
|
+
* |31 |`28 | 10` | ... |
|
|
154
|
+
*
|
|
155
|
+
* The above data structure allows us to re-concatenate the styling no matter which data binding
|
|
156
|
+
* changes.
|
|
157
|
+
*
|
|
158
|
+
* NOTE: in addition to keeping track of next/previous index the `TView.data` also stores prev/next
|
|
159
|
+
* duplicate bit. The duplicate bit if true says there either is a binding with the same name or
|
|
160
|
+
* there is a map (which may contain the name). This information is useful in knowing if other
|
|
161
|
+
* styles with higher priority need to be searched for overwrites.
|
|
162
|
+
*
|
|
163
|
+
* NOTE: See `should support example in 'tnode_linked_list.ts' documentation` in
|
|
164
|
+
* `tnode_linked_list_spec.ts` for working example.
|
|
165
|
+
*/
|
|
166
|
+
var __unused_const_as_closure_does_not_like_standalone_comment_blocks__;
|
|
167
|
+
/**
|
|
168
|
+
* Insert new `tStyleValue` at `TData` and link existing style bindings such that we maintain linked
|
|
169
|
+
* list of styles and compute the duplicate flag.
|
|
170
|
+
*
|
|
171
|
+
* Note: this function is executed during `firstUpdatePass` only to populate the `TView.data`.
|
|
172
|
+
*
|
|
173
|
+
* The function works by keeping track of `tStylingRange` which contains two pointers pointing to
|
|
174
|
+
* the head/tail of the template portion of the styles.
|
|
175
|
+
* - if `isHost === false` (we are template) then insertion is at tail of `TStylingRange`
|
|
176
|
+
* - if `isHost === true` (we are host binding) then insertion is at head of `TStylingRange`
|
|
177
|
+
*
|
|
178
|
+
* @param tData The `TData` to insert into.
|
|
179
|
+
* @param tNode `TNode` associated with the styling element.
|
|
180
|
+
* @param tStylingKey See `TStylingKey`.
|
|
181
|
+
* @param index location of where `tStyleValue` should be stored (and linked into list.)
|
|
182
|
+
* @param isHostBinding `true` if the insertion is for a `hostBinding`. (insertion is in front of
|
|
183
|
+
* template.)
|
|
184
|
+
* @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
|
|
185
|
+
* `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
|
|
186
|
+
*/
|
|
187
|
+
export function insertTStylingBinding(tData, tNode, tStylingKeyWithStatic, index, isHostBinding, isClassBinding) {
|
|
188
|
+
ngDevMode && assertFirstUpdatePass(getTView());
|
|
189
|
+
var tBindings = isClassBinding ? tNode.classBindings : tNode.styleBindings;
|
|
190
|
+
var tmplHead = getTStylingRangePrev(tBindings);
|
|
191
|
+
var tmplTail = getTStylingRangeNext(tBindings);
|
|
192
|
+
tData[index] = tStylingKeyWithStatic;
|
|
193
|
+
var isKeyDuplicateOfStatic = false;
|
|
194
|
+
var tStylingKey;
|
|
195
|
+
if (Array.isArray(tStylingKeyWithStatic)) {
|
|
196
|
+
// We are case when the `TStylingKey` contains static fields as well.
|
|
197
|
+
var staticKeyValueArray = tStylingKeyWithStatic;
|
|
198
|
+
tStylingKey = staticKeyValueArray[1]; // unwrap.
|
|
199
|
+
// We need to check if our key is present in the static so that we can mark it as duplicate.
|
|
200
|
+
if (tStylingKey === null ||
|
|
201
|
+
keyValueArrayIndexOf(staticKeyValueArray, tStylingKey) > 0) {
|
|
202
|
+
// tStylingKey is present in the statics, need to mark it as duplicate.
|
|
203
|
+
isKeyDuplicateOfStatic = true;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
tStylingKey = tStylingKeyWithStatic;
|
|
208
|
+
}
|
|
209
|
+
if (isHostBinding) {
|
|
210
|
+
// We are inserting host bindings
|
|
211
|
+
// If we don't have template bindings then `tail` is 0.
|
|
212
|
+
var hasTemplateBindings = tmplTail !== 0;
|
|
213
|
+
// This is important to know because that means that the `head` can't point to the first
|
|
214
|
+
// template bindings (there are none.) Instead the head points to the tail of the template.
|
|
215
|
+
if (hasTemplateBindings) {
|
|
216
|
+
// template head's "prev" will point to last host binding or to 0 if no host bindings yet
|
|
217
|
+
var previousNode = getTStylingRangePrev(tData[tmplHead + 1]);
|
|
218
|
+
tData[index + 1] = toTStylingRange(previousNode, tmplHead);
|
|
219
|
+
// if a host binding has already been registered, we need to update the next of that host
|
|
220
|
+
// binding to point to this one
|
|
221
|
+
if (previousNode !== 0) {
|
|
222
|
+
// We need to update the template-tail value to point to us.
|
|
223
|
+
tData[previousNode + 1] =
|
|
224
|
+
setTStylingRangeNext(tData[previousNode + 1], index);
|
|
225
|
+
}
|
|
226
|
+
// The "previous" of the template binding head should point to this host binding
|
|
227
|
+
tData[tmplHead + 1] = setTStylingRangePrev(tData[tmplHead + 1], index);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
tData[index + 1] = toTStylingRange(tmplHead, 0);
|
|
231
|
+
// if a host binding has already been registered, we need to update the next of that host
|
|
232
|
+
// binding to point to this one
|
|
233
|
+
if (tmplHead !== 0) {
|
|
234
|
+
// We need to update the template-tail value to point to us.
|
|
235
|
+
tData[tmplHead + 1] = setTStylingRangeNext(tData[tmplHead + 1], index);
|
|
236
|
+
}
|
|
237
|
+
// if we don't have template, the head points to template-tail, and needs to be advanced.
|
|
238
|
+
tmplHead = index;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
// We are inserting in template section.
|
|
243
|
+
// We need to set this binding's "previous" to the current template tail
|
|
244
|
+
tData[index + 1] = toTStylingRange(tmplTail, 0);
|
|
245
|
+
ngDevMode && assertEqual(tmplHead !== 0 && tmplTail === 0, false, 'Adding template bindings after hostBindings is not allowed.');
|
|
246
|
+
if (tmplHead === 0) {
|
|
247
|
+
tmplHead = index;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
// We need to update the previous value "next" to point to this binding
|
|
251
|
+
tData[tmplTail + 1] = setTStylingRangeNext(tData[tmplTail + 1], index);
|
|
252
|
+
}
|
|
253
|
+
tmplTail = index;
|
|
254
|
+
}
|
|
255
|
+
// Now we need to update / compute the duplicates.
|
|
256
|
+
// Starting with our location search towards head (least priority)
|
|
257
|
+
if (isKeyDuplicateOfStatic) {
|
|
258
|
+
tData[index + 1] = setTStylingRangePrevDuplicate(tData[index + 1]);
|
|
259
|
+
}
|
|
260
|
+
markDuplicates(tData, tStylingKey, index, true, isClassBinding);
|
|
261
|
+
markDuplicates(tData, tStylingKey, index, false, isClassBinding);
|
|
262
|
+
markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding);
|
|
263
|
+
tBindings = toTStylingRange(tmplHead, tmplTail);
|
|
264
|
+
if (isClassBinding) {
|
|
265
|
+
tNode.classBindings = tBindings;
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
tNode.styleBindings = tBindings;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Look into the residual styling to see if the current `tStylingKey` is duplicate of residual.
|
|
273
|
+
*
|
|
274
|
+
* @param tNode `TNode` where the residual is stored.
|
|
275
|
+
* @param tStylingKey `TStylingKey` to store.
|
|
276
|
+
* @param tData `TData` associated with the current `LView`.
|
|
277
|
+
* @param index location of where `tStyleValue` should be stored (and linked into list.)
|
|
278
|
+
* @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
|
|
279
|
+
* `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
|
|
280
|
+
*/
|
|
281
|
+
function markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding) {
|
|
282
|
+
var residual = isClassBinding ? tNode.residualClasses : tNode.residualStyles;
|
|
283
|
+
if (residual != null /* or undefined */ && typeof tStylingKey == 'string' &&
|
|
284
|
+
keyValueArrayIndexOf(residual, tStylingKey) >= 0) {
|
|
285
|
+
// We have duplicate in the residual so mark ourselves as duplicate.
|
|
286
|
+
tData[index + 1] = setTStylingRangeNextDuplicate(tData[index + 1]);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Marks `TStyleValue`s as duplicates if another style binding in the list has the same
|
|
291
|
+
* `TStyleValue`.
|
|
292
|
+
*
|
|
293
|
+
* NOTE: this function is intended to be called twice once with `isPrevDir` set to `true` and once
|
|
294
|
+
* with it set to `false` to search both the previous as well as next items in the list.
|
|
295
|
+
*
|
|
296
|
+
* No duplicate case
|
|
297
|
+
* ```
|
|
298
|
+
* [style.color]
|
|
299
|
+
* [style.width.px] <<- index
|
|
300
|
+
* [style.height.px]
|
|
301
|
+
* ```
|
|
302
|
+
*
|
|
303
|
+
* In the above case adding `[style.width.px]` to the existing `[style.color]` produces no
|
|
304
|
+
* duplicates because `width` is not found in any other part of the linked list.
|
|
305
|
+
*
|
|
306
|
+
* Duplicate case
|
|
307
|
+
* ```
|
|
308
|
+
* [style.color]
|
|
309
|
+
* [style.width.em]
|
|
310
|
+
* [style.width.px] <<- index
|
|
311
|
+
* ```
|
|
312
|
+
* In the above case adding `[style.width.px]` will produce a duplicate with `[style.width.em]`
|
|
313
|
+
* because `width` is found in the chain.
|
|
314
|
+
*
|
|
315
|
+
* Map case 1
|
|
316
|
+
* ```
|
|
317
|
+
* [style.width.px]
|
|
318
|
+
* [style.color]
|
|
319
|
+
* [style] <<- index
|
|
320
|
+
* ```
|
|
321
|
+
* In the above case adding `[style]` will produce a duplicate with any other bindings because
|
|
322
|
+
* `[style]` is a Map and as such is fully dynamic and could produce `color` or `width`.
|
|
323
|
+
*
|
|
324
|
+
* Map case 2
|
|
325
|
+
* ```
|
|
326
|
+
* [style]
|
|
327
|
+
* [style.width.px]
|
|
328
|
+
* [style.color] <<- index
|
|
329
|
+
* ```
|
|
330
|
+
* In the above case adding `[style.color]` will produce a duplicate because there is already a
|
|
331
|
+
* `[style]` binding which is a Map and as such is fully dynamic and could produce `color` or
|
|
332
|
+
* `width`.
|
|
333
|
+
*
|
|
334
|
+
* NOTE: Once `[style]` (Map) is added into the system all things are mapped as duplicates.
|
|
335
|
+
* NOTE: We use `style` as example, but same logic is applied to `class`es as well.
|
|
336
|
+
*
|
|
337
|
+
* @param tData `TData` where the linked list is stored.
|
|
338
|
+
* @param tStylingKey `TStylingKeyPrimitive` which contains the value to compare to other keys in
|
|
339
|
+
* the linked list.
|
|
340
|
+
* @param index Starting location in the linked list to search from
|
|
341
|
+
* @param isPrevDir Direction.
|
|
342
|
+
* - `true` for previous (lower priority);
|
|
343
|
+
* - `false` for next (higher priority).
|
|
344
|
+
*/
|
|
345
|
+
function markDuplicates(tData, tStylingKey, index, isPrevDir, isClassBinding) {
|
|
346
|
+
var tStylingAtIndex = tData[index + 1];
|
|
347
|
+
var isMap = tStylingKey === null;
|
|
348
|
+
var cursor = isPrevDir ? getTStylingRangePrev(tStylingAtIndex) : getTStylingRangeNext(tStylingAtIndex);
|
|
349
|
+
var foundDuplicate = false;
|
|
350
|
+
// We keep iterating as long as we have a cursor
|
|
351
|
+
// AND either:
|
|
352
|
+
// - we found what we are looking for, OR
|
|
353
|
+
// - we are a map in which case we have to continue searching even after we find what we were
|
|
354
|
+
// looking for since we are a wild card and everything needs to be flipped to duplicate.
|
|
355
|
+
while (cursor !== 0 && (foundDuplicate === false || isMap)) {
|
|
356
|
+
ngDevMode && assertDataInRange(tData, cursor);
|
|
357
|
+
var tStylingValueAtCursor = tData[cursor];
|
|
358
|
+
var tStyleRangeAtCursor = tData[cursor + 1];
|
|
359
|
+
if (isStylingMatch(tStylingValueAtCursor, tStylingKey)) {
|
|
360
|
+
foundDuplicate = true;
|
|
361
|
+
tData[cursor + 1] = isPrevDir ? setTStylingRangeNextDuplicate(tStyleRangeAtCursor) :
|
|
362
|
+
setTStylingRangePrevDuplicate(tStyleRangeAtCursor);
|
|
363
|
+
}
|
|
364
|
+
cursor = isPrevDir ? getTStylingRangePrev(tStyleRangeAtCursor) :
|
|
365
|
+
getTStylingRangeNext(tStyleRangeAtCursor);
|
|
366
|
+
}
|
|
367
|
+
if (foundDuplicate) {
|
|
368
|
+
// if we found a duplicate, than mark ourselves.
|
|
369
|
+
tData[index + 1] = isPrevDir ? setTStylingRangePrevDuplicate(tStylingAtIndex) :
|
|
370
|
+
setTStylingRangeNextDuplicate(tStylingAtIndex);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Determines if two `TStylingKey`s are a match.
|
|
375
|
+
*
|
|
376
|
+
* When computing weather a binding contains a duplicate, we need to compare if the instruction
|
|
377
|
+
* `TStylingKey` has a match.
|
|
378
|
+
*
|
|
379
|
+
* Here are examples of `TStylingKey`s which match given `tStylingKeyCursor` is:
|
|
380
|
+
* - `color`
|
|
381
|
+
* - `color` // Match another color
|
|
382
|
+
* - `null` // That means that `tStylingKey` is a `classMap`/`styleMap` instruction
|
|
383
|
+
* - `['', 'color', 'other', true]` // wrapped `color` so match
|
|
384
|
+
* - `['', null, 'other', true]` // wrapped `null` so match
|
|
385
|
+
* - `['', 'width', 'color', 'value']` // wrapped static value contains a match on `'color'`
|
|
386
|
+
* - `null` // `tStylingKeyCursor` always match as it is `classMap`/`styleMap` instruction
|
|
387
|
+
*
|
|
388
|
+
* @param tStylingKeyCursor
|
|
389
|
+
* @param tStylingKey
|
|
390
|
+
*/
|
|
391
|
+
function isStylingMatch(tStylingKeyCursor, tStylingKey) {
|
|
392
|
+
ngDevMode &&
|
|
393
|
+
assertNotEqual(Array.isArray(tStylingKey), true, 'Expected that \'tStylingKey\' has been unwrapped');
|
|
394
|
+
if (tStylingKeyCursor === null || // If the cursor is `null` it means that we have map at that
|
|
395
|
+
// location so we must assume that we have a match.
|
|
396
|
+
tStylingKey == null || // If `tStylingKey` is `null` then it is a map therefor assume that it
|
|
397
|
+
// contains a match.
|
|
398
|
+
(Array.isArray(tStylingKeyCursor) ? tStylingKeyCursor[1] : tStylingKeyCursor) ===
|
|
399
|
+
tStylingKey // If the keys match explicitly than we are a match.
|
|
400
|
+
) {
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
else if (Array.isArray(tStylingKeyCursor) && typeof tStylingKey === 'string') {
|
|
404
|
+
// if we did not find a match, but `tStylingKeyCursor` is `KeyValueArray` that means cursor has
|
|
405
|
+
// statics and we need to check those as well.
|
|
406
|
+
return keyValueArrayIndexOf(tStylingKeyCursor, tStylingKey) >=
|
|
407
|
+
0; // see if we are matching the key
|
|
408
|
+
}
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3R5bGVfYmluZGluZ19saXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29yZS9zcmMvcmVuZGVyMy9zdHlsaW5nL3N0eWxlX2JpbmRpbmdfbGlzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0VBTUU7QUFFRixPQUFPLEVBQWdCLG9CQUFvQixFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFDM0UsT0FBTyxFQUFDLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxjQUFjLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUNqRixPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFFaEQsT0FBTyxFQUFtRCxvQkFBb0IsRUFBRSxvQkFBb0IsRUFBRSxvQkFBb0IsRUFBRSw2QkFBNkIsRUFBRSxvQkFBb0IsRUFBRSw2QkFBNkIsRUFBRSxlQUFlLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUU5UCxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sVUFBVSxDQUFDO0FBR2xDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXdKRztBQUNILElBQUksbUVBQThFLENBQUM7QUFFbkY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQ2pDLEtBQVksRUFBRSxLQUFZLEVBQUUscUJBQWtDLEVBQUUsS0FBYSxFQUM3RSxhQUFzQixFQUFFLGNBQXVCO0lBQ2pELFNBQVMsSUFBSSxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQy9DLElBQUksU0FBUyxHQUFHLGNBQWMsQ0FBQyxDQUFDLENB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QUFLLFFBQVEsRUFBRTtRQUM5RSwrRkFBK0Y7UUFDL0YsOENBQThDO1FBQzlDLE9BQU8sb0JBQW9CLENBQUMsaUJBQWlCLEVBQUUsV0FBVyxDQUFDO1lBQ3ZELENBQUMsQ0FBQyxDQUFFLGlDQUFpQztLQUMxQztJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuKiBAbGljZW5zZVxuKiBDb3B5cmlnaHQgR29vZ2xlIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbipcbiogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuKi9cblxuaW1wb3J0IHtLZXlWYWx1ZUFycmF5LCBrZXlWYWx1ZUFycmF5SW5kZXhPZn0gZnJvbSAnLi4vLi4vdXRpbC9hcnJheV91dGlscyc7XG5pbXBvcnQge2Fzc2VydERhdGFJblJhbmdlLCBhc3NlcnRFcXVhbCwgYXNzZXJ0Tm90RXF1YWx9IGZyb20gJy4uLy4uL3V0aWwvYXNzZXJ0JztcbmltcG9ydCB7YXNzZXJ0Rmlyc3RVcGRhdGVQYXNzfSBmcm9tICcuLi9hc3NlcnQnO1xuaW1wb3J0IHtUTm9kZX0gZnJvbSAnLi4vaW50ZXJmYWNlcy9ub2RlJztcbmltcG9ydCB7VFN0eWxpbmdLZXksIFRTdHlsaW5nS2V5UHJpbWl0aXZlLCBUU3R5bGluZ1JhbmdlLCBnZXRUU3R5bGluZ1JhbmdlTmV4dCwgZ2V0VFN0eWxpbmdSYW5nZVByZXYsIHNldFRTdHlsaW5nUmFuZ2VOZXh0LCBzZXRUU3R5bGluZ1JhbmdlTmV4dER1cGxpY2F0ZSwgc2V0VFN0eWxpbmdSYW5nZVByZXYsIHNldFRTdHlsaW5nUmFuZ2VQcmV2RHVwbGljYXRlLCB0b1RTdHlsaW5nUmFuZ2V9IGZyb20gJy4uL2ludGVyZmFjZXMvc3R5bGluZyc7XG5pbXBvcnQge1REYXRhfSBmcm9tICcuLi9pbnRlcmZhY2VzL3ZpZXcnO1xuaW1wb3J0IHtnZXRUVmlld30gZnJvbSAnLi4vc3RhdGUnO1xuXG5cbi8qKlxuICogTk9URTogVGhlIHdvcmQgYHN0eWxpbmdgIGlzIHVzZWQgaW50ZXJjaGFuZ2VhYmx5IGFzIHN0eWxlIG9yIGNsYXNzIHN0eWxpbmcuXG4gKlxuICogVGhpcyBmaWxlIGNvbnRhaW5zIGNvZGUgdG8gbGluayBzdHlsaW5nIGluc3RydWN0aW9ucyB0b2dldGhlciBzbyB0aGF0IHRoZXkgY2FuIGJlIHJlcGxheWVkIGluXG4gKiBwcmlvcml0eSBvcmRlci4gVGhlIGZpbGUgZXhpc3RzIGJlY2F1c2UgSXZ5IHN0eWxpbmcgaW5zdHJ1Y3Rpb24gZXhlY3V0aW9uIG9yZGVyIGRvZXMgbm90IG1hdGNoXG4gKiB0aGF0IG9mIHRoZSBwcmlvcml0eSBvcmRlci4gVGhlIHB1cnBvc2Ugb2YgdGhpcyBjb2RlIGlzIHRvIGNyZWF0ZSBhIGxpbmtlZCBsaXN0IHNvIHRoYXQgdGhlXG4gKiBpbnN0cnVjdGlvbnMgY2FuIGJlIHRyYXZlcnNlZCBpbiBwcmlvcml0eSBvcmRlciB3aGVuIGNvbXB1dGluZyB0aGUgc3R5bGVzLlxuICpcbiAqIEFzc3VtZSB3ZSBhcmUgZGVhbGluZyB3aXRoIHRoZSBmb2xsb3dpbmcgY29kZTpcbiAqIGBgYFxuICogQENvbXBvbmVudCh7XG4gKiAgIHRlbXBsYXRlOiBgXG4gKiAgICAgPG15LWNtcCBbc3R5bGVdPVwiIHtjb2xvcjogJyMwMDEnfSBcIlxuICogICAgICAgICAgICAgW3N0eWxlLmNvbG9yXT1cIiAjMDAyIFwiXG4gKiAgICAgICAgICAgICBkaXItc3R5bGUtY29sb3ItMVxuICogICAgICAgICAgICAgZGlyLXN0eWxlLWNvbG9yLTI+IGBcbiAqIH0pXG4gKiBjbGFzcyBFeGFtcGxlQ29tcG9uZW50IHtcbiAqICAgc3RhdGljIG5nQ29tcCA9IC4uLiB7XG4gKiAgICAgLi4uXG4gKiAgICAgLy8gQ29tcGlsZXIgZW5zdXJlcyB0aGF0IGDJtcm1c3R5bGVQcm9wYCBpcyBhZnRlciBgybXJtXN0eWxlTWFwYFxuICogICAgIMm1ybVzdHlsZU1hcCh7Y29sb3I6ICcjMDAxJ30pO1xuICogICAgIMm1ybVzdHlsZVByb3AoJ2NvbG9yJywgJyMwMDInKTtcbiAqICAgICAuLi5cbiAqICAgfVxuICogfVxuICpcbiAqIEBEaXJlY3RpdmUoe1xuICogICBzZWxlY3RvcjogYFtkaXItc3R5bGUtY29sb3ItMV0nLFxuICogfSlcbiAqIGNsYXNzIFN0eWxlMURpcmVjdGl2ZSB7XG4gKiAgIEBIb3N0QmluZGluZygnc3R5bGUnKSBzdHlsZSA9IHtjb2xvcjogJyMwMDUnfTtcbiAqICAgQEhvc3RCaW5kaW5nKCdzdHlsZS5jb2xvcicpIGNvbG9yID0gJyMwMDYnO1xuICpcbiAqICAgc3RhdGljIG5nRGlyID0gLi4uIHtcbiAqICAgICAuLi5cbiAqICAgICAvLyBDb21waWxlciBlbnN1cmVzIHRoYXQgYMm1ybVzdHlsZVByb3BgIGlzIGFmdGVyIGDJtcm1c3R5bGVNYXBgXG4gKiAgICAgybXJtXN0eWxlTWFwKHtjb2xvcjogJyMwMDUnfSk7XG4gKiAgICAgybXJtXN0eWxlUHJvcCgnY29sb3InLCAnIzAwNicpO1xuICogICAgIC4uLlxuICogICB9XG4gKiB9XG4gKlxuICogQERpcmVjdGl2ZSh7XG4gKiAgIHNlbGVjdG9yOiBgW2Rpci1zdHlsZS1jb2xvci0yXScsXG4gKiB9KVxuICogY2xhc3MgU3R5bGUyRGlyZWN0aXZlIHtcbiAqICAgQEhvc3RCaW5kaW5nKCdzdHlsZScpIHN0eWxlID0ge2NvbG9yOiAnIzAwNyd9O1xuICogICBASG9zdEJpbmRpbmcoJ3N0eWxlLmNvbG9yJykgY29sb3IgPSAnIzAwOCc7XG4gKlxuICogICBzdGF0aWMgbmdEaXIgPSAuLi4ge1xuICogICAgIC4uLlxuICogICAgIC8vIENvbXBpbGVyIGVuc3VyZXMgdGhhdCBgybXJtXN0eWxlUHJvcGAgaXMgYWZ0ZXIgYMm1ybVzdHlsZU1hcGBcbiAqICAgICDJtcm1c3R5bGVNYXAoe2NvbG9yOiAnIzAwNyd9KTtcbiAqICAgICDJtcm1c3R5bGVQcm9wKCdjb2xvcicsICcjMDA4Jyk7XG4gKiAgICAgLi4uXG4gKiAgIH1cbiAqIH1cbiAqXG4gKiBARGlyZWN0aXZlKHtcbiAqICAgc2VsZWN0b3I6IGBteS1jbXAnLFxuICogfSlcbiAqIGNsYXNzIE15Q29tcG9uZW50IHtcbiAqICAgQEhvc3RCaW5kaW5nKCdzdHlsZScpIHN0eWxlID0ge2NvbG9yOiAnIzAwMyd9O1xuICogICBASG9zdEJpbmRpbmcoJ3N0eWxlLmNvbG9yJykgY29sb3IgPSAnIzAwNCc7XG4gKlxuICogICBzdGF0aWMgbmdDb21wID0gLi4uIHtcbiAqICAgICAuLi5cbiAqICAgICAvLyBDb21waWxlciBlbnN1cmVzIHRoYXQgYMm1ybVzdHlsZVByb3BgIGlzIGFmdGVyIGDJtcm1c3R5bGVNYXBgXG4gKiAgICAgybXJtXN0eWxlTWFwKHtjb2xvcjogJyMwMDMnfSk7XG4gKiAgICAgybXJtXN0eWxlUHJvcCgnY29sb3InLCAnIzAwNCcpO1xuICogICAgIC4uLlxuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBUaGUgT3JkZXIgb2YgaW5zdHJ1Y3Rpb24gZXhlY3V0aW9uIGlzOlxuICpcbiAqIE5PVEU6IHRoZSBjb21tZW50IGJpbmRpbmcgbG9jYXRpb24gaXMgZm9yIGlsbHVzdHJhdGl2ZSBwdXJwb3NlcyBvbmx5LlxuICpcbiAqIGBgYFxuICogLy8gVGVtcGxhdGU6IChFeGFtcGxlQ29tcG9uZW50KVxuICogICAgIMm1ybVzdHlsZU1hcCh7Y29sb3I6ICcjMDAxJ30pOyAgIC8vIEJpbmRpbmcgaW5kZXg6IDEwXG4gKiAgICAgybXJtXN0eWxlUHJvcCgnY29sb3InLCAnIzAwMicpOyAgLy8gQmluZGluZyBpbmRleDogMTJcbiAqIC8vIE15Q29tcG9uZW50XG4gKiAgICAgybXJtXN0eWxlTWFwKHtjb2xvcjogJyMwMDMnfSk7ICAgLy8gQmluZGluZyBpbmRleDogMjBcbiAqICAgICDJtcm1c3R5bGVQcm9wKCdjb2xvcicsICcjMDA0Jyk7ICAvLyBCaW5kaW5nIGluZGV4OiAyMlxuICogLy8gU3R5bGUxRGlyZWN0aXZlXG4gKiAgICAgybXJtXN0eWxlTWFwKHtjb2xvcjogJyMwMDUnfSk7ICAgLy8gQmluZGluZyBpbmRleDogMjRcbiAqICAgICDJtcm1c3R5bGVQcm9wKCdjb2xvcicsICcjMDA2Jyk7ICAvLyBCaW5kaW5nIGluZGV4OiAyNlxuICogLy8gU3R5bGUyRGlyZWN0aXZlXG4gKiAgICAgybXJtXN0eWxlTWFwKHtjb2xvcjogJyMwMDcnfSk7ICAgLy8gQmluZGluZyBpbmRleDogMjhcbiAqICAgICDJtcm1c3R5bGVQcm9wKCdjb2xvcicsICcjMDA4Jyk7ICAvLyBCaW5kaW5nIGluZGV4OiAzMFxuICogYGBgXG4gKlxuICogVGhlIGNvcnJlY3QgcHJpb3JpdHkgb3JkZXIgb2YgY29uY2F0ZW5hdGlvbiBpczpcbiAqXG4gKiBgYGBcbiAqIC8vIE15Q29tcG9uZW50XG4gKiAgICAgybXJtXN0eWxlTWFwKHtjb2xvcjogJyMwMDMnfSk7ICAgLy8gQmluZGluZyBpbmRleDogMjBcbiAqICAgICDJtcm1c3R5bGVQcm9wKCdjb2xvcicsICcjMDA0Jyk7ICAvLyBCaW5kaW5nIGluZGV4OiAyMlxuICogLy8gU3R5bGUxRGlyZWN0aXZlXG4gKiAgICAgybXJtXN0eWxlTWFwKHtjb2xvcjogJyMwMDUnfSk7ICAgLy8gQmluZGluZyBpbmRleDogMjRcbiAqICAgICDJtcm1c3R5bGVQcm9wKCdjb2xvcicsICcjMDA2Jyk7ICAvLyBCaW5kaW5nIGluZGV4OiAyNlxuICogLy8gU3R5bGUyRGlyZWN0aXZlXG4gKiAgICAgybXJtXN0eWxlTWFwKHtjb2xvcjogJyMwMDcnfSk7ICAgLy8gQmluZGluZyBpbmRleDogMjhcbiAqICAgICDJtcm1c3R5bGVQcm9wKCdjb2xvcicsICcjMDA4Jyk7ICAvLyBCaW5kaW5nIGluZGV4OiAzMFxuICogLy8gVGVtcGxhdGU6IChFeGFtcGxlQ29tcG9uZW50KVxuICogICAgIMm1ybVzdHlsZU1hcCh7Y29sb3I6ICcjMDAxJ30pOyAgIC8vIEJpbmRpbmcgaW5kZXg6IDEwXG4gKiAgICAgybXJtXN0eWxlUHJvcCgnY29sb3InLCAnIzAwMicpOyAgLy8gQmluZGluZyBpbmRleDogMTJcbiAqIGBgYFxuICpcbiAqIFdoYXQgY29sb3Igc2hvdWxkIGJlIHJlbmRlcmVkP1xuICpcbiAqIE9uY2UgdGhlIGl0ZW1zIGFyZSBjb3JyZWN0bHkgc29ydGVkIGluIHRoZSBsaXN0LCB0aGUgYW5zd2VyIGlzIHNpbXBseSB0aGUgbGFzdCBpdGVtIGluIHRoZVxuICogY29uY2F0ZW5hdGlvbiBsaXN0IHdoaWNoIGlzIGAjMDAyYC5cbiAqXG4gKiBUbyBkbyBzbyB3ZSBrZWVwIGEgbGlua2VkIGxpc3Qgb2YgYWxsIG9mIHRoZSBiaW5kaW5ncyB3aGljaCBwZXJ0YWluIHRvIHRoaXMgZWxlbWVudC5cbiAqIE5vdGljZSB0aGF0IHRoZSBiaW5kaW5ncyBhcmUgaW5zZXJ0ZWQgaW4gdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiwgYnV0IHRoZSBgVFZpZXcuZGF0YWAgYWxsb3dzXG4gKiB1cyB0byB0cmF2ZXJzZSB0aGVtIGluIHRoZSBvcmRlciBvZiBwcmlvcml0eS5cbiAqXG4gKiB8SWR4fGBUVmlldy5kYXRhYHxgTFZpZXdgICAgICAgICAgIHwgTm90ZXNcbiAqIHwtLS18LS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tXG4gKiB8Li4ufCAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgIHxcbiAqIHwxMCB8YG51bGxgICAgICAgfGB7Y29sb3I6ICcjMDAxJ31gfCBgybXJtXN0eWxlTWFwKCdjb2xvcicsIHtjb2xvcjogJyMwMDEnfSlgXG4gKiB8MTEgfGAzMCB8IDEyYCAgIHwgLi4uICAgICAgICAgICAgIHxcbiAqIHwxMiB8YGNvbG9yYCAgICAgfGAnIzAwMidgICAgICAgICAgfCBgybXJtXN0eWxlUHJvcCgnY29sb3InLCAnIzAwMicpYFxuICogfDEzIHxgMTAgfCAwYCAgICB8IC4uLiAgICAgICAgICAgICB8XG4gKiB8Li4ufCAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgIHxcbiAqIHwyMCB8YG51bGxgICAgICAgfGB7Y29sb3I6ICcjMDAzJ31gfCBgybXJtXN0eWxlTWFwKCdjb2xvcicsIHtjb2xvcjogJyMwMDMnfSlgXG4gKiB8MjEgfGAwIHwgMjJgICAgIHwgLi4uICAgICAgICAgICAgIHxcbiAqIHwyMiB8YGNvbG9yYCAgICAgfGAnIzAwNCdgICAgICAgICAgfCBgybXJtXN0eWxlUHJvcCgnY29sb3InLCAnIzAwNCcpYFxuICogfDIzIHxgMjAgfCAyNGAgICB8IC4uLiAgICAgICAgICAgICB8XG4gKiB8MjQgfGBudWxsYCAgICAgIHxge2NvbG9yOiAnIzAwNSd9YHwgYMm1ybVzdHlsZU1hcCgnY29sb3InLCB7Y29sb3I6ICcjMDA1J30pYFxuICogfDI1IHxgMjIgfCAyNmAgICB8IC4uLiAgICAgICAgICAgICB8XG4gKiB8MjYgfGBjb2xvcmAgICAgIHxgJyMwMDYnYCAgICAgICAgIHwgYMm1ybVzdHlsZVByb3AoJ2NvbG9yJywgJyMwMDYnKWBcbiAqIHwyNyB8YDI0IHwgMjhgICAgfCAuLi4gICAgICAgICAgICAgfFxuICogfDI4IHxgbnVsbGAgICAgICB8YHtjb2xvcjogJyMwMDcnfWB8IGDJtcm1c3R5bGVNYXAoJ2NvbG9yJywge2NvbG9yOiAnIzAwNyd9KWBcbiAqIHwyOSB8YDI2IHwgMzBgICAgfCAuLi4gICAgICAgICAgICAgfFxuICogfDMwIHxgY29sb3JgICAgICB8YCcjMDA4J2AgICAgICAgICB8IGDJtcm1c3R5bGVQcm9wKCdjb2xvcicsICcjMDA4JylgXG4gKiB8MzEgfGAyOCB8IDEwYCAgIHwgLi4uICAgICAgICAgICAgIHxcbiAqXG4gKiBUaGUgYWJvdmUgZGF0YSBzdHJ1Y3R1cmUgYWxsb3dzIHVzIHRvIHJlLWNvbmNhdGVuYXRlIHRoZSBzdHlsaW5nIG5vIG1hdHRlciB3aGljaCBkYXRhIGJpbmRpbmdcbiAqIGNoYW5nZXMuXG4gKlxuICogTk9URTogaW4gYWRkaXRpb24gdG8ga2VlcGluZyB0cmFjayBvZiBuZXh0L3ByZXZpb3VzIGluZGV4IHRoZSBgVFZpZXcuZGF0YWAgYWxzbyBzdG9yZXMgcHJldi9uZXh0XG4gKiBkdXBsaWNhdGUgYml0LiBUaGUgZHVwbGljYXRlIGJpdCBpZiB0cnVlIHNheXMgdGhlcmUgZWl0aGVyIGlzIGEgYmluZGluZyB3aXRoIHRoZSBzYW1lIG5hbWUgb3JcbiAqIHRoZXJlIGlzIGEgbWFwICh3aGljaCBtYXkgY29udGFpbiB0aGUgbmFtZSkuIFRoaXMgaW5mb3JtYXRpb24gaXMgdXNlZnVsIGluIGtub3dpbmcgaWYgb3RoZXJcbiAqIHN0eWxlcyB3aXRoIGhpZ2hlciBwcmlvcml0eSBuZWVkIHRvIGJlIHNlYXJjaGVkIGZvciBvdmVyd3JpdGVzLlxuICpcbiAqIE5PVEU6IFNlZSBgc2hvdWxkIHN1cHBvcnQgZXhhbXBsZSBpbiAndG5vZGVfbGlua2VkX2xpc3QudHMnIGRvY3VtZW50YXRpb25gIGluXG4gKiBgdG5vZGVfbGlua2VkX2xpc3Rfc3BlYy50c2AgZm9yIHdvcmtpbmcgZXhhbXBsZS5cbiAqL1xubGV0IF9fdW51c2VkX2NvbnN0X2FzX2Nsb3N1cmVfZG9lc19ub3RfbGlrZV9zdGFuZGFsb25lX2NvbW1lbnRfYmxvY2tzX186IHVuZGVmaW5lZDtcblxuLyoqXG4gKiBJbnNlcnQgbmV3IGB0U3R5bGVWYWx1ZWAgYXQgYFREYXRhYCBhbmQgbGluayBleGlzdGluZyBzdHlsZSBiaW5kaW5ncyBzdWNoIHRoYXQgd2UgbWFpbnRhaW4gbGlua2VkXG4gKiBsaXN0IG9mIHN0eWxlcyBhbmQgY29tcHV0ZSB0aGUgZHVwbGljYXRlIGZsYWcuXG4gKlxuICogTm90ZTogdGhpcyBmdW5jdGlvbiBpcyBleGVjdXRlZCBkdXJpbmcgYGZpcnN0VXBkYXRlUGFzc2Agb25seSB0byBwb3B1bGF0ZSB0aGUgYFRWaWV3LmRhdGFgLlxuICpcbiAqIFRoZSBmdW5jdGlvbiB3b3JrcyBieSBrZWVwaW5nIHRyYWNrIG9mIGB0U3R5bGluZ1JhbmdlYCB3aGljaCBjb250YWlucyB0d28gcG9pbnRlcnMgcG9pbnRpbmcgdG9cbiAqIHRoZSBoZWFkL3RhaWwgb2YgdGhlIHRlbXBsYXRlIHBvcnRpb24gb2YgdGhlIHN0eWxlcy5cbiAqICAtIGlmIGBpc0hvc3QgPT09IGZhbHNlYCAod2UgYXJlIHRlbXBsYXRlKSB0aGVuIGluc2VydGlvbiBpcyBhdCB0YWlsIG9mIGBUU3R5bGluZ1JhbmdlYFxuICogIC0gaWYgYGlzSG9zdCA9PT0gdHJ1ZWAgKHdlIGFyZSBob3N0IGJpbmRpbmcpIHRoZW4gaW5zZXJ0aW9uIGlzIGF0IGhlYWQgb2YgYFRTdHlsaW5nUmFuZ2VgXG4gKlxuICogQHBhcmFtIHREYXRhIFRoZSBgVERhdGFgIHRvIGluc2VydCBpbnRvLlxuICogQHBhcmFtIHROb2RlIGBUTm9kZWAgYXNzb2NpYXRlZCB3aXRoIHRoZSBzdHlsaW5nIGVsZW1lbnQuXG4gKiBAcGFyYW0gdFN0eWxpbmdLZXkgU2VlIGBUU3R5bGluZ0tleWAuXG4gKiBAcGFyYW0gaW5kZXggbG9jYXRpb24gb2Ygd2hlcmUgYHRTdHlsZVZhbHVlYCBzaG91bGQgYmUgc3RvcmVkIChhbmQgbGlua2VkIGludG8gbGlzdC4pXG4gKiBAcGFyYW0gaXNIb3N0QmluZGluZyBgdHJ1ZWAgaWYgdGhlIGluc2VydGlvbiBpcyBmb3IgYSBgaG9zdEJpbmRpbmdgLiAoaW5zZXJ0aW9uIGlzIGluIGZyb250IG9mXG4gKiAgICAgICAgICAgICAgIHRlbXBsYXRlLilcbiAqIEBwYXJhbSBpc0NsYXNzQmluZGluZyBUcnVlIGlmIHRoZSBhc3NvY2lhdGVkIGB0U3R5bGluZ0tleWAgYXMgYSBgY2xhc3NgIHN0eWxpbmcuXG4gKiAgICAgICAgICAgICAgICAgICAgICAgYHROb2RlLmNsYXNzQmluZGluZ3NgIHNob3VsZCBiZSB1c2VkIChvciBgdE5vZGUuc3R5bGVCaW5kaW5nc2Agb3RoZXJ3aXNlLilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluc2VydFRTdHlsaW5nQmluZGluZyhcbiAgICB0RGF0YTogVERhdGEsIHROb2RlOiBUTm9kZSwgdFN0eWxpbmdLZXlXaXRoU3RhdGljOiBUU3R5bGluZ0tleSwgaW5kZXg6IG51bWJlcixcbiAgICBpc0hvc3RCaW5kaW5nOiBib29sZWFuLCBpc0NsYXNzQmluZGluZzogYm9vbGVhbik6IHZvaWQge1xuICBuZ0Rldk1vZGUgJiYgYXNzZXJ0Rmlyc3RVcGRhdGVQYXNzKGdldFRWaWV3KCkpO1xuICBsZXQgdEJpbmRpbmdzID0gaXNDbGFzc0JpbmRpbmcgPyB0Tm9kZS5jbGFzc0JpbmRpbmdzIDogdE5vZGUuc3R5bGVCaW5kaW5ncztcbiAgbGV0IHRtcGxIZWFkID0gZ2V0VFN0eWxpbmdSYW5nZVByZXYodEJpbmRpbmdzKTtcbiAgbGV0IHRtcGxUYWlsID0gZ2V0VFN0eWxpbmdSYW5nZU5leHQodEJpbmRpbmdzKTtcblxuICB0RGF0YVtpbmRleF0gPSB0U3R5bGluZ0tleVdpdGhTdGF0aWM7XG4gIGxldCBpc0tleUR1cGxpY2F0ZU9mU3RhdGljID0gZmFsc2U7XG4gIGxldCB0U3R5bGluZ0tleTogVFN0eWxpbmdLZXlQcmltaXRpdmU7XG4gIGlmIChBcnJheS5pc0FycmF5KHRTdHlsaW5nS2V5V2l0aFN0YXRpYykpIHtcbiAgICAvLyBXZSBhcmUgY2FzZSB3aGVuIHRoZSBgVFN0eWxpbmdLZXlgIGNvbnRhaW5zIHN0YXRpYyBmaWVsZHMgYXMgd2VsbC5cbiAgICBjb25zdCBzdGF0aWNLZXlWYWx1ZUFycmF5ID0gdFN0eWxpbmdLZXlXaXRoU3RhdGljIGFzIEtleVZhbHVlQXJyYXk8YW55PjtcbiAgICB0U3R5bGluZ0tleSA9IHN0YXRpY0tleVZhbHVlQXJyYXlbMV07ICAvLyB1bndyYXAuXG4gICAgLy8gV2UgbmVlZCB0byBjaGVjayBpZiBvdXIga2V5IGlzIHByZXNlbnQgaW4gdGhlIHN0YXRpYyBzbyB0aGF0IHdlIGNhbiBtYXJrIGl0IGFzIGR1cGxpY2F0ZS5cbiAgICBpZiAodFN0eWxpbmdLZXkgPT09IG51bGwgfHxcbiAgICAgICAga2V5VmFsdWVBcnJheUluZGV4T2Yoc3RhdGljS2V5VmFsdWVBcnJheSwgdFN0eWxpbmdLZXkgYXMgc3RyaW5nKSA+IDApIHtcbiAgICAgIC8vIHRTdHlsaW5nS2V5IGlzIHByZXNlbnQgaW4gdGhlIHN0YXRpY3MsIG5lZWQgdG8gbWFyayBpdCBhcyBkdXBsaWNhdGUuXG4gICAgICBpc0tleUR1cGxpY2F0ZU9mU3RhdGljID0gdHJ1ZTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdFN0eWxpbmdLZXkgPSB0U3R5bGluZ0tleVdpdGhTdGF0aWM7XG4gIH1cbiAgaWYgKGlzSG9zdEJpbmRpbmcpIHtcbiAgICAvLyBXZSBhcmUgaW5zZXJ0aW5nIGhvc3QgYmluZGluZ3NcblxuICAgIC8vIElmIHdlIGRvbid0IGhhdmUgdGVtcGxhdGUgYmluZGluZ3MgdGhlbiBgdGFpbGAgaXMgMC5cbiAgICBjb25zdCBoYXNUZW1wbGF0ZUJpbmRpbmdzID0gdG1wbFRhaWwgIT09IDA7XG4gICAgLy8gVGhpcyBpcyBpbXBvcnRhbnQgdG8ga25vdyBiZWNhdXNlIHRoYXQgbWVhbnMgdGhhdCB0aGUgYGhlYWRgIGNhbid0IHBvaW50IHRvIHRoZSBmaXJzdFxuICAgIC8vIHRlbXBsYXRlIGJpbmRpbmdzICh0aGVyZSBhcmUgbm9uZS4pIEluc3RlYWQgdGhlIGhlYWQgcG9pbnRzIHRvIHRoZSB0YWlsIG9mIHRoZSB0ZW1wbGF0ZS5cbiAgICBpZiAoaGFzVGVtcGxhdGVCaW5kaW5ncykge1xuICAgICAgLy8gdGVtcGxhdGUgaGVhZCdzIFwicHJldlwiIHdpbGwgcG9pbnQgdG8gbGFzdCBob3N0IGJpbmRpbmcgb3IgdG8gMCBpZiBubyBob3N0IGJpbmRpbmdzIHlldFxuICAgICAgY29uc3QgcHJldmlvdXNOb2RlID0gZ2V0VFN0eWxpbmdSYW5nZVByZXYodERhdGFbdG1wbEhlYWQgKyAxXSBhcyBUU3R5bGluZ1JhbmdlKTtcbiAgICAgIHREYXRhW2luZGV4ICsgMV0gPSB0b1RTdHlsaW5nUmFuZ2UocHJldmlvdXNOb2RlLCB0bXBsSGVhZCk7XG4gICAgICAvLyBpZiBhIGhvc3QgYmluZGluZyBoYXMgYWxyZWFkeSBiZWVuIHJlZ2lzdGVyZWQsIHdlIG5lZWQgdG8gdXBkYXRlIHRoZSBuZXh0IG9mIHRoYXQgaG9zdFxuICAgICAgLy8gYmluZGluZyB0byBwb2ludCB0byB0aGlzIG9uZVxuICAgICAgaWYgKHByZXZpb3VzTm9kZSAhPT0gMCkge1xuICAgICAgICAvLyBXZSBuZWVkIHRvIHVwZGF0ZSB0aGUgdGVtcGxhdGUtdGFpbCB2YWx1ZSB0byBwb2ludCB0byB1cy5cbiAgICAgICAgdERhdGFbcHJldmlvdXNOb2RlICsgMV0gPVxuICAgICAgICAgICAgc2V0VFN0eWxpbmdSYW5nZU5leHQodERhdGFbcHJldmlvdXNOb2RlICsgMV0gYXMgVFN0eWxpbmdSYW5nZSwgaW5kZXgpO1xuICAgICAgfVxuICAgICAgLy8gVGhlIFwicHJldmlvdXNcIiBvZiB0aGUgdGVtcGxhdGUgYmluZGluZyBoZWFkIHNob3VsZCBwb2ludCB0byB0aGlzIGhvc3QgYmluZGluZ1xuICAgICAgdERhdGFbdG1wbEhlYWQgKyAxXSA9IHNldFRTdHlsaW5nUmFuZ2VQcmV2KHREYXRhW3RtcGxIZWFkICsgMV0gYXMgVFN0eWxpbmdSYW5nZSwgaW5kZXgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0RGF0YVtpbmRleCArIDFdID0gdG9UU3R5bGluZ1JhbmdlKHRtcGxIZWFkLCAwKTtcbiAgICAgIC8vIGlmIGEgaG9zdCBiaW5kaW5nIGhhcyBhbHJlYWR5IGJlZW4gcmVnaXN0ZXJlZCwgd2UgbmVlZCB0byB1cGRhdGUgdGhlIG5leHQgb2YgdGhhdCBob3N0XG4gICAgICAvLyBiaW5kaW5nIHRvIHBvaW50IHRvIHRoaXMgb25lXG4gICAgICBpZiAodG1wbEhlYWQgIT09IDApIHtcbiAgICAgICAgLy8gV2UgbmVlZCB0byB1cGRhdGUgdGhlIHRlbXBsYXRlLXRhaWwgdmFsdWUgdG8gcG9pbnQgdG8gdXMuXG4gICAgICAgIHREYXRhW3RtcGxIZWFkICsgMV0gPSBzZXRUU3R5bGluZ1JhbmdlTmV4dCh0RGF0YVt0bXBsSGVhZCArIDFdIGFzIFRTdHlsaW5nUmFuZ2UsIGluZGV4KTtcbiAgICAgIH1cbiAgICAgIC8vIGlmIHdlIGRvbid0IGhhdmUgdGVtcGxhdGUsIHRoZSBoZWFkIHBvaW50cyB0byB0ZW1wbGF0ZS10YWlsLCBhbmQgbmVlZHMgdG8gYmUgYWR2YW5jZWQuXG4gICAgICB0bXBsSGVhZCA9IGluZGV4O1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBXZSBhcmUgaW5zZXJ0aW5nIGluIHRlbXBsYXRlIHNlY3Rpb24uXG4gICAgLy8gV2UgbmVlZCB0byBzZXQgdGhpcyBiaW5kaW5nJ3MgXCJwcmV2aW91c1wiIHRvIHRoZSBjdXJyZW50IHRlbXBsYXRlIHRhaWxcbiAgICB0RGF0YVtpbmRleCArIDFdID0gdG9UU3R5bGluZ1JhbmdlKHRtcGxUYWlsLCAwKTtcbiAgICBuZ0Rldk1vZGUgJiYgYXNzZXJ0RXF1YWwoXG4gICAgICAgICAgICAgICAgICAgICB0bXBsSGVhZCAhPT0gMCAmJiB0bXBsVGFpbCA9PT0gMCwgZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAnQWRkaW5nIHRlbXBsYXRlIGJpbmRpbmdzIGFmdGVyIGhvc3RCaW5kaW5ncyBpcyBub3QgYWxsb3dlZC4nKTtcbiAgICBpZiAodG1wbEhlYWQgPT09IDApIHtcbiAgICAgIHRtcGxIZWFkID0gaW5kZXg7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFdlIG5lZWQgdG8gdXBkYXRlIHRoZSBwcmV2aW91cyB2YWx1ZSBcIm5leHRcIiB0byBwb2ludCB0byB0aGlzIGJpbmRpbmdcbiAgICAgIHREYXRhW3RtcGxUYWlsICsgMV0gPSBzZXRUU3R5bGluZ1JhbmdlTmV4dCh0RGF0YVt0bXBsVGFpbCArIDFdIGFzIFRTdHlsaW5nUmFuZ2UsIGluZGV4KTtcbiAgICB9XG4gICAgdG1wbFRhaWwgPSBpbmRleDtcbiAgfVxuXG4gIC8vIE5vdyB3ZSBuZWVkIHRvIHVwZGF0ZSAvIGNvbXB1dGUgdGhlIGR1cGxpY2F0ZXMuXG4gIC8vIFN0YXJ0aW5nIHdpdGggb3VyIGxvY2F0aW9uIHNlYXJjaCB0b3dhcmRzIGhlYWQgKGxlYXN0IHByaW9yaXR5KVxuICBpZiAoaXNLZXlEdXBsaWNhdGVPZlN0YXRpYykge1xuICAgIHREYXRhW2luZGV4ICsgMV0gPSBzZXRUU3R5bGluZ1JhbmdlUHJldkR1cGxpY2F0ZSh0RGF0YVtpbmRleCArIDFdIGFzIFRTdHlsaW5nUmFuZ2UpO1xuICB9XG4gIG1hcmtEdXBsaWNhdGVzKHREYXRhLCB0U3R5bGluZ0tleSwgaW5kZXgsIHRydWUsIGlzQ2xhc3NCaW5kaW5nKTtcbiAgbWFya0R1cGxpY2F0ZXModERhdGEsIHRTdHlsaW5nS2V5LCBpbmRleCwgZmFsc2UsIGlzQ2xhc3NCaW5kaW5nKTtcbiAgbWFya0R1cGxpY2F0ZU9mUmVzaWR1YWxTdHlsaW5nKHROb2RlLCB0U3R5bGluZ0tleSwgdERhdGEsIGluZGV4LCBpc0NsYXNzQmluZGluZyk7XG5cbiAgdEJpbmRpbmdzID0gdG9UU3R5bGluZ1JhbmdlKHRtcGxIZWFkLCB0bXBsVGFpbCk7XG4gIGlmIChpc0NsYXNzQmluZGluZykge1xuICAgIHROb2RlLmNsYXNzQmluZGluZ3MgPSB0QmluZGluZ3M7XG4gIH0gZWxzZSB7XG4gICAgdE5vZGUuc3R5bGVCaW5kaW5ncyA9IHRCaW5kaW5ncztcbiAgfVxufVxuXG4vKipcbiAqIExvb2sgaW50byB0aGUgcmVzaWR1YWwgc3R5bGluZyB0byBzZWUgaWYgdGhlIGN1cnJlbnQgYHRTdHlsaW5nS2V5YCBpcyBkdXBsaWNhdGUgb2YgcmVzaWR1YWwuXG4gKlxuICogQHBhcmFtIHROb2RlIGBUTm9kZWAgd2hlcmUgdGhlIHJlc2lkdWFsIGlzIHN0b3JlZC5cbiAqIEBwYXJhbSB0U3R5bGluZ0tleSBgVFN0eWxpbmdLZXlgIHRvIHN0b3JlLlxuICogQHBhcmFtIHREYXRhIGBURGF0YWAgYXNzb2NpYXRlZCB3aXRoIHRoZSBjdXJyZW50IGBMVmlld2AuXG4gKiBAcGFyYW0gaW5kZXggbG9jYXRpb24gb2Ygd2hlcmUgYHRTdHlsZVZhbHVlYCBzaG91bGQgYmUgc3RvcmVkIChhbmQgbGlua2VkIGludG8gbGlzdC4pXG4gKiBAcGFyYW0gaXNDbGFzc0JpbmRpbmcgVHJ1ZSBpZiB0aGUgYXNzb2NpYXRlZCBgdFN0eWxpbmdLZXlgIGFzIGEgYGNsYXNzYCBzdHlsaW5nLlxuICogICAgICAgICAgICAgICAgICAgICAgIGB0Tm9kZS5jbGFzc0JpbmRpbmdzYCBzaG91bGQgYmUgdXNlZCAob3IgYHROb2RlLnN0eWxlQmluZGluZ3NgIG90aGVyd2lzZS4pXG4gKi9cbmZ1bmN0aW9uIG1hcmtEdXBsaWNhdGVPZlJlc2lkdWFsU3R5bGluZyhcbiAgICB0Tm9kZTogVE5vZGUsIHRTdHlsaW5nS2V5OiBUU3R5bGluZ0tleSwgdERhdGE6IFREYXRhLCBpbmRleDogbnVtYmVyLCBpc0NsYXNzQmluZGluZzogYm9vbGVhbikge1xuICBjb25zdCByZXNpZHVhbCA9IGlzQ2xhc3NCaW5kaW5nID8gdE5vZGUucmVzaWR1YWxDbGFzc2VzIDogdE5vZGUucmVzaWR1YWxTdHlsZXM7XG4gIGlmIChyZXNpZHVhbCAhPSBudWxsIC8qIG9yIHVuZGVmaW5lZCAqLyAmJiB0eXBlb2YgdFN0eWxpbmdLZXkgPT0gJ3N0cmluZycgJiZcbiAgICAgIGtleVZhbHVlQXJyYXlJbmRleE9mKHJlc2lkdWFsLCB0U3R5bGluZ0tleSkgPj0gMCkge1xuICAgIC8vIFdlIGhhdmUgZHVwbGljYXRlIGluIHRoZSByZXNpZHVhbCBzbyBtYXJrIG91cnNlbHZlcyBhcyBkdXBsaWNhdGUuXG4gICAgdERhdGFbaW5kZXggKyAxXSA9IHNldFRTdHlsaW5nUmFuZ2VOZXh0RHVwbGljYXRlKHREYXRhW2luZGV4ICsgMV0gYXMgVFN0eWxpbmdSYW5nZSk7XG4gIH1cbn1cblxuXG4vKipcbiAqIE1hcmtzIGBUU3R5bGVWYWx1ZWBzIGFzIGR1cGxpY2F0ZXMgaWYgYW5vdGhlciBzdHlsZSBiaW5kaW5nIGluIHRoZSBsaXN0IGhhcyB0aGUgc2FtZVxuICogYFRTdHlsZVZhbHVlYC5cbiAqXG4gKiBOT1RFOiB0aGlzIGZ1bmN0aW9uIGlzIGludGVuZGVkIHRvIGJlIGNhbGxlZCB0d2ljZSBvbmNlIHdpdGggYGlzUHJldkRpcmAgc2V0IHRvIGB0cnVlYCBhbmQgb25jZVxuICogd2l0aCBpdCBzZXQgdG8gYGZhbHNlYCB0byBzZWFyY2ggYm90aCB0aGUgcHJldmlvdXMgYXMgd2VsbCBhcyBuZXh0IGl0ZW1zIGluIHRoZSBsaXN0LlxuICpcbiAqIE5vIGR1cGxpY2F0ZSBjYXNlXG4gKiBgYGBcbiAqICAgW3N0eWxlLmNvbG9yXVxuICogICBbc3R5bGUud2lkdGgucHhdIDw8LSBpbmRleFxuICogICBbc3R5bGUuaGVpZ2h0LnB4XVxuICogYGBgXG4gKlxuICogSW4gdGhlIGFib3ZlIGNhc2UgYWRkaW5nIGBbc3R5bGUud2lkdGgucHhdYCB0byB0aGUgZXhpc3RpbmcgYFtzdHlsZS5jb2xvcl1gIHByb2R1Y2VzIG5vXG4gKiBkdXBsaWNhdGVzIGJlY2F1c2UgYHdpZHRoYCBpcyBub3QgZm91bmQgaW4gYW55IG90aGVyIHBhcnQgb2YgdGhlIGxpbmtlZCBsaXN0LlxuICpcbiAqIER1cGxpY2F0ZSBjYXNlXG4gKiBgYGBcbiAqICAgW3N0eWxlLmNvbG9yXVxuICogICBbc3R5bGUud2lkdGguZW1dXG4gKiAgIFtzdHlsZS53aWR0aC5weF0gPDwtIGluZGV4XG4gKiBgYGBcbiAqIEluIHRoZSBhYm92ZSBjYXNlIGFkZGluZyBgW3N0eWxlLndpZHRoLnB4XWAgd2lsbCBwcm9kdWNlIGEgZHVwbGljYXRlIHdpdGggYFtzdHlsZS53aWR0aC5lbV1gXG4gKiBiZWNhdXNlIGB3aWR0aGAgaXMgZm91bmQgaW4gdGhlIGNoYWluLlxuICpcbiAqIE1hcCBjYXNlIDFcbiAqIGBgYFxuICogICBbc3R5bGUud2lkdGgucHhdXG4gKiAgIFtzdHlsZS5jb2xvcl1cbiAqICAgW3N0eWxlXSAgPDwtIGluZGV4XG4gKiBgYGBcbiAqIEluIHRoZSBhYm92ZSBjYXNlIGFkZGluZyBgW3N0eWxlXWAgd2lsbCBwcm9kdWNlIGEgZHVwbGljYXRlIHdpdGggYW55IG90aGVyIGJpbmRpbmdzIGJlY2F1c2VcbiAqIGBbc3R5bGVdYCBpcyBhIE1hcCBhbmQgYXMgc3VjaCBpcyBmdWxseSBkeW5hbWljIGFuZCBjb3VsZCBwcm9kdWNlIGBjb2xvcmAgb3IgYHdpZHRoYC5cbiAqXG4gKiBNYXAgY2FzZSAyXG4gKiBgYGBcbiAqICAgW3N0eWxlXVxuICogICBbc3R5bGUud2lkdGgucHhdXG4gKiAgIFtzdHlsZS5jb2xvcl0gIDw8LSBpbmRleFxuICogYGBgXG4gKiBJbiB0aGUgYWJvdmUgY2FzZSBhZGRpbmcgYFtzdHlsZS5jb2xvcl1gIHdpbGwgcHJvZHVjZSBhIGR1cGxpY2F0ZSBiZWNhdXNlIHRoZXJlIGlzIGFscmVhZHkgYVxuICogYFtzdHlsZV1gIGJpbmRpbmcgd2hpY2ggaXMgYSBNYXAgYW5kIGFzIHN1Y2ggaXMgZnVsbHkgZHluYW1pYyBhbmQgY291bGQgcHJvZHVjZSBgY29sb3JgIG9yXG4gKiBgd2lkdGhgLlxuICpcbiAqIE5PVEU6IE9uY2UgYFtzdHlsZV1gIChNYXApIGlzIGFkZGVkIGludG8gdGhlIHN5c3RlbSBhbGwgdGhpbmdzIGFyZSBtYXBwZWQgYXMgZHVwbGljYXRlcy5cbiAqIE5PVEU6IFdlIHVzZSBgc3R5bGVgIGFzIGV4YW1wbGUsIGJ1dCBzYW1lIGxvZ2ljIGlzIGFwcGxpZWQgdG8gYGNsYXNzYGVzIGFzIHdlbGwuXG4gKlxuICogQHBhcmFtIHREYXRhIGBURGF0YWAgd2hlcmUgdGhlIGxpbmtlZCBsaXN0IGlzIHN0b3JlZC5cbiAqIEBwYXJhbSB0U3R5bGluZ0tleSBgVFN0eWxpbmdLZXlQcmltaXRpdmVgIHdoaWNoIGNvbnRhaW5zIHRoZSB2YWx1ZSB0byBjb21wYXJlIHRvIG90aGVyIGtleXMgaW5cbiAqICAgICAgICB0aGUgbGlua2VkIGxpc3QuXG4gKiBAcGFyYW0gaW5kZXggU3RhcnRpbmcgbG9jYXRpb24gaW4gdGhlIGxpbmtlZCBsaXN0IHRvIHNlYXJjaCBmcm9tXG4gKiBAcGFyYW0gaXNQcmV2RGlyIERpcmVjdGlvbi5cbiAqICAgICAgICAtIGB0cnVlYCBmb3IgcHJldmlvdXMgKGxvd2VyIHByaW9yaXR5KTtcbiAqICAgICAgICAtIGBmYWxzZWAgZm9yIG5leHQgKGhpZ2hlciBwcmlvcml0eSkuXG4gKi9cbmZ1bmN0aW9uIG1hcmtEdXBsaWNhdGVzKFxuICAgIHREYXRhOiBURGF0YSwgdFN0eWxpbmdLZXk6IFRTdHlsaW5nS2V5UHJpbWl0aXZlLCBpbmRleDogbnVtYmVyLCBpc1ByZXZEaXI6IGJvb2xlYW4sXG4gICAgaXNDbGFzc0JpbmRpbmc6IGJvb2xlYW4pIHtcbiAgY29uc3QgdFN0eWxpbmdBdEluZGV4ID0gdERhdGFbaW5kZXggKyAxXSBhcyBUU3R5bGluZ1JhbmdlO1xuICBjb25zdCBpc01hcCA9IHRTdHlsaW5nS2V5ID09PSBudWxsO1xuICBsZXQgY3Vyc29yID1cbiAgICAgIGlzUHJldkRpciA/IGdldFRTdHlsaW5nUmFuZ2VQcmV2KHRTdHlsaW5nQXRJbmRleCkgOiBnZXRUU3R5bGluZ1JhbmdlTmV4dCh0U3R5bGluZ0F0SW5kZXgpO1xuICBsZXQgZm91bmREdXBsaWNhdGUgPSBmYWxzZTtcbiAgLy8gV2Uga2VlcCBpdGVyYXRpbmcgYXMgbG9uZyBhcyB3ZSBoYXZlIGEgY3Vyc29yXG4gIC8vIEFORCBlaXRoZXI6XG4gIC8vIC0gd2UgZm91bmQgd2hhdCB3ZSBhcmUgbG9va2luZyBmb3IsIE9SXG4gIC8vIC0gd2UgYXJlIGEgbWFwIGluIHdoaWNoIGNhc2Ugd2UgaGF2ZSB0byBjb250aW51ZSBzZWFyY2hpbmcgZXZlbiBhZnRlciB3ZSBmaW5kIHdoYXQgd2Ugd2VyZVxuICAvLyAgIGxvb2tpbmcgZm9yIHNpbmNlIHdlIGFyZSBhIHdpbGQgY2FyZCBhbmQgZXZlcnl0aGluZyBuZWVkcyB0byBiZSBmbGlwcGVkIHRvIGR1cGxpY2F0ZS5cbiAgd2hpbGUgKGN1cnNvciAhPT0gMCAmJiAoZm91bmREdXBsaWNhdGUgPT09IGZhbHNlIHx8IGlzTWFwKSkge1xuICAgIG5nRGV2TW9kZSAmJiBhc3NlcnREYXRhSW5SYW5nZSh0RGF0YSwgY3Vyc29yKTtcbiAgICBjb25zdCB0U3R5bGluZ1ZhbHVlQXRDdXJzb3IgPSB0RGF0YVtjdXJzb3JdIGFzIFRTdHlsaW5nS2V5O1xuICAgIGNvbnN0IHRTdHlsZVJhbmdlQXRDdXJzb3IgPSB0RGF0YVtjdXJzb3IgKyAxXSBhcyBUU3R5bGluZ1JhbmdlO1xuICAgIGlmIChpc1N0eWxpbmdNYXRjaCh0U3R5bGluZ1ZhbHVlQXRDdXJzb3IsIHRTdHlsaW5nS2V5KSkge1xuICAgICAgZm91bmREdXBsaWNhdGUgPSB0cnVlO1xuICAgICAgdERhdGFbY3Vyc29yICsgMV0gPSBpc1ByZXZEaXIgPyBzZXRUU3R5bGluZ1JhbmdlTmV4dER1cGxpY2F0ZSh0U3R5bGVSYW5nZUF0Q3Vyc29yKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRTdHlsaW5nUmFuZ2VQcmV2RHVwbGljYXRlKHRTdHlsZVJhbmdlQXRDdXJzb3IpO1xuICAgIH1cbiAgICBjdXJzb3IgPSBpc1ByZXZEaXIgPyBnZXRUU3R5bGluZ1JhbmdlUHJldih0U3R5bGVSYW5nZUF0Q3Vyc29yKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgZ2V0VFN0eWxpbmdSYW5nZU5leHQodFN0eWxlUmFuZ2VBdEN1cnNvcik7XG4gIH1cbiAgaWYgKGZvdW5kRHVwbGljYXRlKSB7XG4gICAgLy8gaWYgd2UgZm91bmQgYSBkdXBsaWNhdGUsIHRoYW4gbWFyayBvdXJzZWx2ZXMuXG4gICAgdERhdGFbaW5kZXggKyAxXSA9IGlzUHJldkRpciA/IHNldFRTdHlsaW5nUmFuZ2VQcmV2RHVwbGljYXRlKHRTdHlsaW5nQXRJbmRleCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRUU3R5bGluZ1JhbmdlTmV4dER1cGxpY2F0ZSh0U3R5bGluZ0F0SW5kZXgpO1xuICB9XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lcyBpZiB0d28gYFRTdHlsaW5nS2V5YHMgYXJlIGEgbWF0Y2guXG4gKlxuICogV2hlbiBjb21wdXRpbmcgd2VhdGhlciBhIGJpbmRpbmcgY29udGFpbnMgYSBkdXBsaWNhdGUsIHdlIG5lZWQgdG8gY29tcGFyZSBpZiB0aGUgaW5zdHJ1Y3Rpb25cbiAqIGBUU3R5bGluZ0tleWAgaGFzIGEgbWF0Y2guXG4gKlxuICogSGVyZSBhcmUgZXhhbXBsZXMgb2YgYFRTdHlsaW5nS2V5YHMgd2hpY2ggbWF0Y2ggZ2l2ZW4gYHRTdHlsaW5nS2V5Q3Vyc29yYCBpczpcbiAqIC0gYGNvbG9yYFxuICogICAgLSBgY29sb3JgICAgIC8vIE1hdGNoIGFub3RoZXIgY29sb3JcbiAqICAgIC0gYG51bGxgICAgICAvLyBUaGF0IG1lYW5zIHRoYXQgYHRTdHlsaW5nS2V5YCBpcyBhIGBjbGFzc01hcGAvYHN0eWxlTWFwYCBpbnN0cnVjdGlvblxuICogICAgLSBgWycnLCAnY29sb3InLCAnb3RoZXInLCB0cnVlXWAgLy8gd3JhcHBlZCBgY29sb3JgIHNvIG1hdGNoXG4gKiAgICAtIGBbJycsIG51bGwsICdvdGhlcicsIHRydWVdYCAgICAgICAvLyB3cmFwcGVkIGBudWxsYCBzbyBtYXRjaFxuICogICAgLSBgWycnLCAnd2lkdGgnLCAnY29sb3InLCAndmFsdWUnXWAgLy8gd3JhcHBlZCBzdGF0aWMgdmFsdWUgY29udGFpbnMgYSBtYXRjaCBvbiBgJ2NvbG9yJ2BcbiAqIC0gYG51bGxgICAgICAgIC8vIGB0U3R5bGluZ0tleUN1cnNvcmAgYWx3YXlzIG1hdGNoIGFzIGl0IGlzIGBjbGFzc01hcGAvYHN0eWxlTWFwYCBpbnN0cnVjdGlvblxuICpcbiAqIEBwYXJhbSB0U3R5bGluZ0tleUN1cnNvclxuICogQHBhcmFtIHRTdHlsaW5nS2V5XG4gKi9cbmZ1bmN0aW9uIGlzU3R5bGluZ01hdGNoKHRTdHlsaW5nS2V5Q3Vyc29yOiBUU3R5bGluZ0tleSwgdFN0eWxpbmdLZXk6IFRTdHlsaW5nS2V5UHJpbWl0aXZlKSB7XG4gIG5nRGV2TW9kZSAmJlxuICAgICAgYXNzZXJ0Tm90RXF1YWwoXG4gICAgICAgICAgQXJyYXkuaXNBcnJheSh0U3R5bGluZ0tleSksIHRydWUsICdFeHBlY3RlZCB0aGF0IFxcJ3RTdHlsaW5nS2V5XFwnIGhhcyBiZWVuIHVud3JhcHBlZCcpO1xuICBpZiAodFN0eWxpbmdLZXlDdXJzb3IgPT09IG51bGwgfHwgIC8vIElmIHRoZSBjdXJzb3IgaXMgYG51bGxgIGl0IG1lYW5zIHRoYXQgd2UgaGF2ZSBtYXAgYXQgdGhhdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxvY2F0aW9uIHNvIHdlIG11c3QgYXNzdW1lIHRoYXQgd2UgaGF2ZSBhIG1hdGNoLlxuICAgICAgdFN0eWxpbmdLZXkgPT0gbnVsbCB8fCAgLy8gSWYgYHRTdHlsaW5nS2V5YCBpcyBgbnVsbGAgdGhlbiBpdCBpcyBhIG1hcCB0aGVyZWZvciBhc3N1bWUgdGhhdCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29udGFpbnMgYSBtYXRjaC5cbiAgICAgIChBcnJheS5pc0FycmF5KHRTdHlsaW5nS2V5Q3Vyc29yKSA/IHRTdHlsaW5nS2V5Q3Vyc29yWzFdIDogdFN0eWxpbmdLZXlDdXJzb3IpID09PVxuICAgICAgICAgIHRTdHlsaW5nS2V5ICAvLyBJZiB0aGUga2V5cyBtYXRjaCBleHBsaWNpdGx5IHRoYW4gd2UgYXJlIGEgbWF0Y2guXG4gICAgICApIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHRTdHlsaW5nS2V5Q3Vyc29yKSAmJiB0eXBlb2YgdFN0eWxpbmdLZXkgPT09ICdzdHJpbmcnKSB7XG4gICAgLy8gaWYgd2UgZGlkIG5vdCBmaW5kIGEgbWF0Y2gsIGJ1dCBgdFN0eWxpbmdLZXlDdXJzb3JgIGlzIGBLZXlWYWx1ZUFycmF5YCB0aGF0IG1lYW5zIGN1cnNvciBoYXNcbiAgICAvLyBzdGF0aWNzIGFuZCB3ZSBuZWVkIHRvIGNoZWNrIHRob3NlIGFzIHdlbGwuXG4gICAgcmV0dXJuIGtleVZhbHVlQXJyYXlJbmRleE9mKHRTdHlsaW5nS2V5Q3Vyc29yLCB0U3R5bGluZ0tleSkgPj1cbiAgICAgICAgMDsgIC8vIHNlZSBpZiB3ZSBhcmUgbWF0Y2hpbmcgdGhlIGtleVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cbiJdfQ==
|