@angular/core 9.0.0-rc.7 → 9.0.1

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.
Files changed (222) hide show
  1. package/bundles/core-testing.umd.js +18 -16
  2. package/bundles/core-testing.umd.js.map +1 -1
  3. package/bundles/core-testing.umd.min.js +7 -7
  4. package/bundles/core-testing.umd.min.js.map +1 -1
  5. package/bundles/core.umd.js +6386 -6384
  6. package/bundles/core.umd.js.map +1 -1
  7. package/bundles/core.umd.min.js +182 -175
  8. package/bundles/core.umd.min.js.map +1 -1
  9. package/core.d.ts +726 -734
  10. package/core.metadata.json +1 -1
  11. package/esm2015/core.externs.js +5 -5
  12. package/esm2015/core.js +17 -15
  13. package/esm2015/index.js +2 -2
  14. package/esm2015/public_api.js +2 -2
  15. package/esm2015/src/application_init.js +10 -2
  16. package/esm2015/src/application_module.js +6 -3
  17. package/esm2015/src/application_ref.js +7 -7
  18. package/esm2015/src/core.js +4 -4
  19. package/esm2015/src/core_private_export.js +7 -7
  20. package/esm2015/src/core_render3_private_export.js +2 -2
  21. package/esm2015/src/debug/debug_node.js +55 -16
  22. package/esm2015/src/di/injectable.js +1 -13
  23. package/esm2015/src/di/injector.js +12 -10
  24. package/esm2015/src/di/interface/provider.js +1 -1
  25. package/esm2015/src/di/r3_injector.js +5 -4
  26. package/esm2015/src/i18n/locale_data_api.js +22 -6
  27. package/esm2015/src/i18n/locale_en.js +16 -5
  28. package/esm2015/src/i18n/localization.js +7 -1
  29. package/esm2015/src/i18n/tokens.js +41 -1
  30. package/esm2015/src/interface/type.js +1 -1
  31. package/esm2015/src/metadata/ng_module.js +1 -1
  32. package/esm2015/src/render/api.js +4 -1
  33. package/esm2015/src/render3/assert.js +9 -1
  34. package/esm2015/src/render3/bindings.js +16 -5
  35. package/esm2015/src/render3/component.js +54 -25
  36. package/esm2015/src/render3/component_ref.js +28 -18
  37. package/esm2015/src/render3/definition.js +3 -1
  38. package/esm2015/src/render3/di.js +3 -4
  39. package/esm2015/src/render3/di_setup.js +5 -7
  40. package/esm2015/src/render3/errors.js +3 -1
  41. package/esm2015/src/render3/features/inherit_definition_feature.js +89 -52
  42. package/esm2015/src/render3/features/ng_onchanges_feature.js +2 -2
  43. package/esm2015/src/render3/global_utils_api.js +3 -3
  44. package/esm2015/src/render3/i18n.js +60 -56
  45. package/esm2015/src/render3/index.js +2 -2
  46. package/esm2015/src/render3/instructions/advance.js +10 -11
  47. package/esm2015/src/render3/instructions/all.js +4 -5
  48. package/esm2015/src/render3/instructions/attribute.js +12 -5
  49. package/esm2015/src/render3/instructions/attribute_interpolation.js +66 -14
  50. package/esm2015/src/render3/instructions/change_detection.js +8 -23
  51. package/esm2015/src/render3/instructions/class_map_interpolation.js +13 -12
  52. package/esm2015/src/render3/instructions/container.js +15 -12
  53. package/esm2015/src/render3/instructions/element.js +45 -132
  54. package/esm2015/src/render3/instructions/element_container.js +8 -10
  55. package/esm2015/src/render3/instructions/embedded_view.js +7 -7
  56. package/esm2015/src/render3/instructions/host_property.js +10 -7
  57. package/esm2015/src/render3/instructions/listener.js +18 -16
  58. package/esm2015/src/render3/instructions/lview_debug.js +160 -23
  59. package/esm2015/src/render3/instructions/projection.js +7 -5
  60. package/esm2015/src/render3/instructions/property.js +27 -6
  61. package/esm2015/src/render3/instructions/property_interpolation.js +42 -23
  62. package/esm2015/src/render3/instructions/shared.js +279 -244
  63. package/esm2015/src/render3/instructions/storage.js +6 -8
  64. package/esm2015/src/render3/instructions/style_prop_interpolation.js +12 -12
  65. package/esm2015/src/render3/instructions/styling.js +731 -475
  66. package/esm2015/src/render3/instructions/text.js +5 -5
  67. package/esm2015/src/render3/interfaces/definition.js +41 -1
  68. package/esm2015/src/render3/interfaces/node.js +160 -115
  69. package/esm2015/src/render3/interfaces/styling.js +183 -375
  70. package/esm2015/src/render3/interfaces/view.js +10 -2
  71. package/esm2015/src/render3/jit/environment.js +1 -3
  72. package/esm2015/src/render3/namespaces.js +17 -0
  73. package/esm2015/src/render3/node_manipulation.js +177 -57
  74. package/esm2015/src/render3/node_selector_matcher.js +128 -24
  75. package/esm2015/src/render3/node_util.js +12 -7
  76. package/esm2015/src/render3/pipe.js +10 -14
  77. package/esm2015/src/render3/pure_function.js +107 -42
  78. package/esm2015/src/render3/query.js +32 -26
  79. package/esm2015/src/render3/state.js +57 -185
  80. package/esm2015/src/render3/styling/class_differ.js +47 -0
  81. package/esm2015/src/render3/styling/static_styling.js +54 -0
  82. package/esm2015/src/render3/styling/style_binding_list.js +437 -0
  83. package/esm2015/src/render3/styling/styling_parser.js +336 -0
  84. package/esm2015/src/render3/tokens.js +2 -2
  85. package/esm2015/src/render3/util/attrs_utils.js +125 -2
  86. package/esm2015/src/render3/util/change_detection_utils.js +33 -0
  87. package/esm2015/src/render3/util/discovery_utils.js +146 -119
  88. package/esm2015/src/render3/util/global_utils.js +5 -5
  89. package/esm2015/src/render3/util/view_utils.js +6 -6
  90. package/esm2015/src/render3/view_engine_compatibility.js +16 -17
  91. package/esm2015/src/render3/view_ref.js +16 -13
  92. package/esm2015/src/sanitization/bypass.js +1 -1
  93. package/esm2015/src/sanitization/sanitization.js +20 -5
  94. package/esm2015/src/util/array_utils.js +240 -1
  95. package/esm2015/src/util/assert.js +37 -21
  96. package/esm2015/src/util/char_code.js +8 -0
  97. package/esm2015/src/util/iterable.js +4 -1
  98. package/esm2015/src/util/ng_dev_mode.js +1 -12
  99. package/esm2015/src/util/stringify.js +14 -1
  100. package/esm2015/src/version.js +1 -1
  101. package/esm2015/src/view/services.js +1 -1
  102. package/esm2015/testing/src/r3_test_bed.js +5 -1
  103. package/esm2015/testing/src/r3_test_bed_compiler.js +5 -13
  104. package/esm2015/testing/src/styling.js +103 -0
  105. package/esm5/core.js +17 -15
  106. package/esm5/src/application_init.js +10 -2
  107. package/esm5/src/application_module.js +6 -3
  108. package/esm5/src/application_ref.js +6 -6
  109. package/esm5/src/core.js +2 -2
  110. package/esm5/src/core_private_export.js +7 -7
  111. package/esm5/src/core_render3_private_export.js +2 -2
  112. package/esm5/src/debug/debug_node.js +39 -14
  113. package/esm5/src/di/injectable.js +1 -1
  114. package/esm5/src/di/injector.js +12 -12
  115. package/esm5/src/di/interface/provider.js +1 -1
  116. package/esm5/src/di/r3_injector.js +5 -4
  117. package/esm5/src/i18n/locale_data_api.js +20 -6
  118. package/esm5/src/i18n/locale_en.js +16 -5
  119. package/esm5/src/i18n/localization.js +6 -1
  120. package/esm5/src/i18n/tokens.js +40 -1
  121. package/esm5/src/interface/type.js +1 -1
  122. package/esm5/src/metadata/ng_module.js +1 -1
  123. package/esm5/src/render/api.js +4 -1
  124. package/esm5/src/render3/assert.js +4 -1
  125. package/esm5/src/render3/bindings.js +19 -2
  126. package/esm5/src/render3/component.js +47 -22
  127. package/esm5/src/render3/component_ref.js +20 -17
  128. package/esm5/src/render3/definition.js +3 -1
  129. package/esm5/src/render3/di.js +3 -4
  130. package/esm5/src/render3/di_setup.js +4 -5
  131. package/esm5/src/render3/errors.js +3 -1
  132. package/esm5/src/render3/features/inherit_definition_feature.js +74 -42
  133. package/esm5/src/render3/features/ng_onchanges_feature.js +1 -1
  134. package/esm5/src/render3/global_utils_api.js +3 -3
  135. package/esm5/src/render3/i18n.js +51 -51
  136. package/esm5/src/render3/index.js +2 -2
  137. package/esm5/src/render3/instructions/advance.js +9 -11
  138. package/esm5/src/render3/instructions/all.js +1 -2
  139. package/esm5/src/render3/instructions/attribute.js +9 -5
  140. package/esm5/src/render3/instructions/attribute_interpolation.js +49 -13
  141. package/esm5/src/render3/instructions/change_detection.js +8 -21
  142. package/esm5/src/render3/instructions/class_map_interpolation.js +13 -12
  143. package/esm5/src/render3/instructions/container.js +13 -12
  144. package/esm5/src/render3/instructions/element.js +41 -113
  145. package/esm5/src/render3/instructions/element_container.js +8 -9
  146. package/esm5/src/render3/instructions/embedded_view.js +7 -7
  147. package/esm5/src/render3/instructions/host_property.js +8 -7
  148. package/esm5/src/render3/instructions/listener.js +13 -13
  149. package/esm5/src/render3/instructions/lview_debug.js +56 -15
  150. package/esm5/src/render3/instructions/projection.js +6 -5
  151. package/esm5/src/render3/instructions/property.js +17 -6
  152. package/esm5/src/render3/instructions/property_interpolation.js +32 -24
  153. package/esm5/src/render3/instructions/shared.js +258 -210
  154. package/esm5/src/render3/instructions/storage.js +4 -6
  155. package/esm5/src/render3/instructions/style_prop_interpolation.js +12 -12
  156. package/esm5/src/render3/instructions/styling.js +685 -367
  157. package/esm5/src/render3/instructions/text.js +5 -5
  158. package/esm5/src/render3/interfaces/definition.js +1 -1
  159. package/esm5/src/render3/interfaces/node.js +49 -1
  160. package/esm5/src/render3/interfaces/styling.js +57 -1
  161. package/esm5/src/render3/interfaces/view.js +1 -1
  162. package/esm5/src/render3/jit/environment.js +1 -3
  163. package/esm5/src/render3/namespaces.js +10 -0
  164. package/esm5/src/render3/node_manipulation.js +167 -54
  165. package/esm5/src/render3/node_selector_matcher.js +113 -20
  166. package/esm5/src/render3/node_util.js +12 -7
  167. package/esm5/src/render3/pipe.js +10 -14
  168. package/esm5/src/render3/pure_function.js +103 -33
  169. package/esm5/src/render3/query.js +25 -24
  170. package/esm5/src/render3/state.js +37 -133
  171. package/esm5/src/render3/styling/class_differ.js +39 -0
  172. package/esm5/src/render3/styling/static_styling.js +42 -0
  173. package/esm5/src/render3/styling/style_binding_list.js +411 -0
  174. package/esm5/src/render3/styling/styling_parser.js +265 -0
  175. package/esm5/src/render3/tokens.js +2 -2
  176. package/esm5/src/render3/util/attrs_utils.js +117 -2
  177. package/esm5/src/render3/util/change_detection_utils.js +23 -0
  178. package/esm5/src/render3/util/discovery_utils.js +115 -99
  179. package/esm5/src/render3/util/global_utils.js +5 -5
  180. package/esm5/src/render3/util/view_utils.js +5 -5
  181. package/esm5/src/render3/view_engine_compatibility.js +37 -39
  182. package/esm5/src/render3/view_ref.js +14 -13
  183. package/esm5/src/sanitization/bypass.js +1 -1
  184. package/esm5/src/sanitization/sanitization.js +16 -5
  185. package/esm5/src/util/array_utils.js +240 -1
  186. package/esm5/src/util/assert.js +37 -21
  187. package/esm5/src/util/char_code.js +8 -0
  188. package/esm5/src/util/iterable.js +4 -1
  189. package/esm5/src/util/ng_dev_mode.js +1 -12
  190. package/esm5/src/util/stringify.js +14 -1
  191. package/esm5/src/version.js +1 -1
  192. package/esm5/src/view/services.js +1 -1
  193. package/esm5/testing/src/r3_test_bed.js +9 -1
  194. package/esm5/testing/src/r3_test_bed_compiler.js +9 -15
  195. package/esm5/testing/src/styling.js +82 -0
  196. package/fesm2015/core.js +6431 -7075
  197. package/fesm2015/core.js.map +1 -1
  198. package/fesm2015/testing.js +10 -14
  199. package/fesm2015/testing.js.map +1 -1
  200. package/fesm5/core.js +6354 -6361
  201. package/fesm5/core.js.map +1 -1
  202. package/fesm5/testing.js +18 -16
  203. package/fesm5/testing.js.map +1 -1
  204. package/package.json +1 -1
  205. package/src/r3_symbols.d.ts +46 -23
  206. package/testing/testing.d.ts +3 -5
  207. package/testing/testing.metadata.json +1 -1
  208. package/testing.d.ts +2 -2
  209. package/esm2015/global.js +0 -7
  210. package/esm2015/src/render3/instructions/alloc_host_vars.js +0 -80
  211. package/esm2015/src/render3/styling/bindings.js +0 -1248
  212. package/esm2015/src/render3/styling/map_based_bindings.js +0 -384
  213. package/esm2015/src/render3/styling/state.js +0 -135
  214. package/esm2015/src/render3/styling/styling_debug.js +0 -655
  215. package/esm2015/src/render3/util/styling_utils.js +0 -625
  216. package/esm5/global.js +0 -9
  217. package/esm5/src/render3/instructions/alloc_host_vars.js +0 -62
  218. package/esm5/src/render3/styling/bindings.js +0 -949
  219. package/esm5/src/render3/styling/map_based_bindings.js +0 -310
  220. package/esm5/src/render3/styling/state.js +0 -56
  221. package/esm5/src/render3/styling/styling_debug.js +0 -315
  222. package/esm5/src/render3/util/styling_utils.js +0 -378
@@ -1,1248 +0,0 @@
1
- /**
2
- * @fileoverview added by tsickle
3
- * Generated from: packages/core/src/render3/styling/bindings.ts
4
- * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
5
- */
6
- /**
7
- * @license
8
- * Copyright Google Inc. All Rights Reserved.
9
- *
10
- * Use of this source code is governed by an MIT-style license that can be
11
- * found in the LICENSE file at https://angular.io/license
12
- */
13
- import { unwrapSafeValue } from '../../sanitization/bypass';
14
- import { global } from '../../util/global';
15
- import { RendererStyleFlags3, isProceduralRenderer } from '../interfaces/renderer';
16
- import { NO_CHANGE } from '../tokens';
17
- import { DEFAULT_BINDING_INDEX, DEFAULT_BINDING_VALUE, DEFAULT_GUARD_MASK_VALUE, MAP_BASED_ENTRY_PROP_NAME, TEMPLATE_DIRECTIVE_INDEX, concatString, forceStylesAsString, getBindingValue, getDefaultValue, getGuardMask, getInitialStylingValue, getMapProp, getMapValue, getProp, getPropValuesStartPosition, getStylingMapArray, getTotalSources, getValue, getValuesCount, hasConfig, hasValueChanged, isHostStylingActive, isSanitizationRequired, isStylingMapArray, isStylingValueDefined, normalizeIntoStylingMap, patchConfig, setDefaultValue, setGuardMask, setMapAsDirty, setValue } from '../util/styling_utils';
18
- import { getStylingState, resetStylingState } from './state';
19
- /** @type {?} */
20
- const VALUE_IS_EXTERNALLY_MODIFIED = {};
21
- /**
22
- * The guard/update mask bit index location for map-based bindings.
23
- *
24
- * All map-based bindings (i.e. `[style]` and `[class]` )
25
- * @type {?}
26
- */
27
- const STYLING_INDEX_FOR_MAP_BINDING = 0;
28
- /**
29
- * Visits a class-based binding and updates the new value (if changed).
30
- *
31
- * This function is called each time a class-based styling instruction
32
- * is executed. It's important that it's always called (even if the value
33
- * has not changed) so that the inner counter index value is incremented.
34
- * This way, each instruction is always guaranteed to get the same counter
35
- * state each time it's called (which then allows the `TStylingContext`
36
- * and the bit mask values to be in sync).
37
- * @param {?} context
38
- * @param {?} tNode
39
- * @param {?} data
40
- * @param {?} element
41
- * @param {?} directiveIndex
42
- * @param {?} prop
43
- * @param {?} bindingIndex
44
- * @param {?} value
45
- * @param {?} forceUpdate
46
- * @param {?} firstUpdatePass
47
- * @return {?}
48
- */
49
- export function updateClassViaContext(context, tNode, data, element, directiveIndex, prop, bindingIndex, value, forceUpdate, firstUpdatePass) {
50
- /** @type {?} */
51
- const isMapBased = !prop;
52
- /** @type {?} */
53
- const state = getStylingState(element, directiveIndex);
54
- /** @type {?} */
55
- const countIndex = isMapBased ? STYLING_INDEX_FOR_MAP_BINDING : state.classesIndex++;
56
- // even if the initial value is a `NO_CHANGE` value (e.g. interpolation or [ngClass])
57
- // then we still need to register the binding within the context so that the context
58
- // is aware of the binding even if things change after the first update pass.
59
- if (firstUpdatePass || value !== NO_CHANGE) {
60
- /** @type {?} */
61
- const updated = updateBindingData(context, tNode, data, countIndex, state.sourceIndex, prop, bindingIndex, value, forceUpdate, false, firstUpdatePass, true);
62
- if (updated || forceUpdate) {
63
- // We flip the bit in the bitMask to reflect that the binding
64
- // at the `index` slot has changed. This identifies to the flushing
65
- // phase that the bindings for this particular CSS class need to be
66
- // applied again because on or more of the bindings for the CSS
67
- // class have changed.
68
- state.classesBitMask |= 1 << countIndex;
69
- return true;
70
- }
71
- }
72
- return false;
73
- }
74
- /**
75
- * Visits a style-based binding and updates the new value (if changed).
76
- *
77
- * This function is called each time a style-based styling instruction
78
- * is executed. It's important that it's always called (even if the value
79
- * has not changed) so that the inner counter index value is incremented.
80
- * This way, each instruction is always guaranteed to get the same counter
81
- * state each time it's called (which then allows the `TStylingContext`
82
- * and the bit mask values to be in sync).
83
- * @param {?} context
84
- * @param {?} tNode
85
- * @param {?} data
86
- * @param {?} element
87
- * @param {?} directiveIndex
88
- * @param {?} prop
89
- * @param {?} bindingIndex
90
- * @param {?} value
91
- * @param {?} sanitizer
92
- * @param {?} forceUpdate
93
- * @param {?} firstUpdatePass
94
- * @return {?}
95
- */
96
- export function updateStyleViaContext(context, tNode, data, element, directiveIndex, prop, bindingIndex, value, sanitizer, forceUpdate, firstUpdatePass) {
97
- /** @type {?} */
98
- const isMapBased = !prop;
99
- /** @type {?} */
100
- const state = getStylingState(element, directiveIndex);
101
- /** @type {?} */
102
- const countIndex = isMapBased ? STYLING_INDEX_FOR_MAP_BINDING : state.stylesIndex++;
103
- // even if the initial value is a `NO_CHANGE` value (e.g. interpolation or [ngStyle])
104
- // then we still need to register the binding within the context so that the context
105
- // is aware of the binding even if things change after the first update pass.
106
- if (firstUpdatePass || value !== NO_CHANGE) {
107
- /** @type {?} */
108
- const sanitizationRequired = isMapBased ?
109
- true :
110
- (sanitizer ? sanitizer((/** @type {?} */ (prop)), null, 1 /* ValidateProperty */) : false);
111
- /** @type {?} */
112
- const updated = updateBindingData(context, tNode, data, countIndex, state.sourceIndex, prop, bindingIndex, value, forceUpdate, sanitizationRequired, firstUpdatePass, false);
113
- if (updated || forceUpdate) {
114
- // We flip the bit in the bitMask to reflect that the binding
115
- // at the `index` slot has changed. This identifies to the flushing
116
- // phase that the bindings for this particular property need to be
117
- // applied again because on or more of the bindings for the CSS
118
- // property have changed.
119
- state.stylesBitMask |= 1 << countIndex;
120
- return true;
121
- }
122
- }
123
- return false;
124
- }
125
- /**
126
- * Called each time a binding value has changed within the provided `TStylingContext`.
127
- *
128
- * This function is designed to be called from `updateStyleBinding` and `updateClassBinding`.
129
- * If called during the first update pass, the binding will be registered in the context.
130
- *
131
- * This function will also update binding slot in the provided `LStylingData` with the
132
- * new binding entry (if it has changed).
133
- *
134
- * @param {?} context
135
- * @param {?} tNode
136
- * @param {?} data
137
- * @param {?} counterIndex
138
- * @param {?} sourceIndex
139
- * @param {?} prop
140
- * @param {?} bindingIndex
141
- * @param {?} value
142
- * @param {?} forceUpdate
143
- * @param {?} sanitizationRequired
144
- * @param {?} firstUpdatePass
145
- * @param {?} isClassBased
146
- * @return {?} whether or not the binding value was updated in the `LStylingData`.
147
- */
148
- function updateBindingData(context, tNode, data, counterIndex, sourceIndex, prop, bindingIndex, value, forceUpdate, sanitizationRequired, firstUpdatePass, isClassBased) {
149
- /** @type {?} */
150
- const hostBindingsMode = isHostStylingActive(sourceIndex);
151
- /** @type {?} */
152
- const hostBindingsFlag = isClassBased ? 4096 /* hasHostClassBindings */ : 131072 /* hasHostStyleBindings */;
153
- if (firstUpdatePass) {
154
- // this will only happen during the first update pass of the
155
- // context. The reason why we can't use `tView.firstCreatePass`
156
- // here is because its not guaranteed to be true when the first
157
- // update pass is executed (remember that all styling instructions
158
- // are run in the update phase, and, as a result, are no more
159
- // styling instructions that are run in the creation phase).
160
- registerBinding(context, tNode, counterIndex, sourceIndex, prop, bindingIndex, sanitizationRequired, isClassBased);
161
- }
162
- /** @type {?} */
163
- const changed = forceUpdate || hasValueChanged(data[bindingIndex], value);
164
- if (changed) {
165
- setValue(data, bindingIndex, value);
166
- /** @type {?} */
167
- const doSetValuesAsStale = hasConfig(tNode, hostBindingsFlag) && !hostBindingsMode && (prop ? !value : true);
168
- if (doSetValuesAsStale) {
169
- renderHostBindingsAsStale(context, tNode, data, prop, isClassBased);
170
- }
171
- }
172
- return changed;
173
- }
174
- /**
175
- * Iterates over all host-binding values for the given `prop` value in the context and sets their
176
- * corresponding binding values to `null`.
177
- *
178
- * Whenever a template binding changes its value to `null`, all host-binding values should be
179
- * re-applied
180
- * to the element when the host bindings are evaluated. This may not always happen in the event
181
- * that none of the bindings changed within the host bindings code. For this reason this function
182
- * is expected to be called each time a template binding becomes falsy or when a map-based template
183
- * binding changes.
184
- * @param {?} context
185
- * @param {?} tNode
186
- * @param {?} data
187
- * @param {?} prop
188
- * @param {?} isClassBased
189
- * @return {?}
190
- */
191
- function renderHostBindingsAsStale(context, tNode, data, prop, isClassBased) {
192
- /** @type {?} */
193
- const valuesCount = getValuesCount(context);
194
- /** @type {?} */
195
- const hostBindingsFlag = isClassBased ? 4096 /* hasHostClassBindings */ : 131072 /* hasHostStyleBindings */;
196
- if (prop !== null && hasConfig(tNode, hostBindingsFlag)) {
197
- /** @type {?} */
198
- const itemsPerRow = 4 /* BindingsStartOffset */ + valuesCount;
199
- /** @type {?} */
200
- let i = 2 /* ValuesStartPosition */;
201
- /** @type {?} */
202
- let found = false;
203
- while (i < context.length) {
204
- if (getProp(context, i) === prop) {
205
- found = true;
206
- break;
207
- }
208
- i += itemsPerRow;
209
- }
210
- if (found) {
211
- /** @type {?} */
212
- const bindingsStart = i + 4 /* BindingsStartOffset */;
213
- /** @type {?} */
214
- const valuesStart = bindingsStart + 1;
215
- // the first column is template bindings
216
- /** @type {?} */
217
- const valuesEnd = bindingsStart + valuesCount - 1;
218
- for (let i = valuesStart; i < valuesEnd; i++) {
219
- /** @type {?} */
220
- const bindingIndex = (/** @type {?} */ (context[i]));
221
- if (bindingIndex !== 0) {
222
- setValue(data, bindingIndex, null);
223
- }
224
- }
225
- }
226
- }
227
- /** @type {?} */
228
- const mapBindingsFlag = isClassBased ? 512 /* hasClassMapBindings */ : 16384 /* hasStyleMapBindings */;
229
- if (hasConfig(tNode, mapBindingsFlag)) {
230
- /** @type {?} */
231
- const bindingsStart = 2 /* ValuesStartPosition */ + 4 /* BindingsStartOffset */;
232
- /** @type {?} */
233
- const valuesStart = bindingsStart + 1;
234
- // the first column is template bindings
235
- /** @type {?} */
236
- const valuesEnd = bindingsStart + valuesCount - 1;
237
- for (let i = valuesStart; i < valuesEnd; i++) {
238
- /** @type {?} */
239
- const stylingMap = getValue(data, (/** @type {?} */ (context[i])));
240
- if (stylingMap) {
241
- setMapAsDirty(stylingMap);
242
- }
243
- }
244
- }
245
- }
246
- /**
247
- * Registers the provided binding (prop + bindingIndex) into the context.
248
- *
249
- * It is needed because it will either update or insert a styling property
250
- * into the context at the correct spot.
251
- *
252
- * When called, one of two things will happen:
253
- *
254
- * 1) If the property already exists in the context then it will just add
255
- * the provided `bindingValue` to the end of the binding sources region
256
- * for that particular property.
257
- *
258
- * - If the binding value is a number then it will be added as a new
259
- * binding index source next to the other binding sources for the property.
260
- *
261
- * - Otherwise, if the binding value is a string/boolean/null type then it will
262
- * replace the default value for the property if the default value is `null`.
263
- *
264
- * 2) If the property does not exist then it will be inserted into the context.
265
- * The styling context relies on all properties being stored in alphabetical
266
- * order, so it knows exactly where to store it.
267
- *
268
- * When inserted, a default `null` value is created for the property which exists
269
- * as the default value for the binding. If the bindingValue property is inserted
270
- * and it is either a string, number or null value then that will replace the default
271
- * value.
272
- *
273
- * Note that this function is also used for map-based styling bindings. They are treated
274
- * much the same as prop-based bindings, but, their property name value is set as `[MAP]`.
275
- * @param {?} context
276
- * @param {?} tNode
277
- * @param {?} countId
278
- * @param {?} sourceIndex
279
- * @param {?} prop
280
- * @param {?} bindingValue
281
- * @param {?} sanitizationRequired
282
- * @param {?} isClassBased
283
- * @return {?}
284
- */
285
- export function registerBinding(context, tNode, countId, sourceIndex, prop, bindingValue, sanitizationRequired, isClassBased) {
286
- /** @type {?} */
287
- let found = false;
288
- prop = prop || MAP_BASED_ENTRY_PROP_NAME;
289
- /** @type {?} */
290
- let totalSources = getTotalSources(context);
291
- // if a new source is detected then a new column needs to be allocated into
292
- // the styling context. The column is basically a new allocation of binding
293
- // sources that will be available to each property.
294
- while (totalSources <= sourceIndex) {
295
- addNewSourceColumn(context);
296
- totalSources++;
297
- }
298
- /** @type {?} */
299
- const collisionFlag = isClassBased ? 8192 /* hasDuplicateClassBindings */ : 262144 /* hasDuplicateStyleBindings */;
300
- /** @type {?} */
301
- const isBindingIndexValue = typeof bindingValue === 'number';
302
- /** @type {?} */
303
- const entriesPerRow = 4 /* BindingsStartOffset */ + getValuesCount(context);
304
- /** @type {?} */
305
- let i = 2 /* ValuesStartPosition */;
306
- // all style/class bindings are sorted by property name
307
- while (i < context.length) {
308
- /** @type {?} */
309
- const p = getProp(context, i);
310
- if (prop <= p) {
311
- if (prop < p) {
312
- allocateNewContextEntry(context, i, prop, sanitizationRequired);
313
- }
314
- else if (isBindingIndexValue) {
315
- patchConfig(tNode, collisionFlag);
316
- }
317
- addBindingIntoContext(context, i, bindingValue, countId, sourceIndex);
318
- found = true;
319
- break;
320
- }
321
- i += entriesPerRow;
322
- }
323
- if (!found) {
324
- allocateNewContextEntry(context, context.length, prop, sanitizationRequired);
325
- addBindingIntoContext(context, i, bindingValue, countId, sourceIndex);
326
- }
327
- }
328
- /**
329
- * Inserts a new row into the provided `TStylingContext` and assigns the provided `prop` value as
330
- * the property entry.
331
- * @param {?} context
332
- * @param {?} index
333
- * @param {?} prop
334
- * @param {?=} sanitizationRequired
335
- * @return {?}
336
- */
337
- function allocateNewContextEntry(context, index, prop, sanitizationRequired) {
338
- /** @type {?} */
339
- const config = sanitizationRequired ? 1 /* SanitizationRequired */ :
340
- 0 /* Default */;
341
- context.splice(index, 0, config, // 1) config value
342
- DEFAULT_GUARD_MASK_VALUE, // 2) template bit mask
343
- DEFAULT_GUARD_MASK_VALUE, // 3) host bindings bit mask
344
- prop);
345
- index += 4; // the 4 values above
346
- // the 4 values above
347
- // 5...) default binding index for the template value
348
- // depending on how many sources already exist in the context,
349
- // multiple default index entries may need to be inserted for
350
- // the new value in the context.
351
- /** @type {?} */
352
- const totalBindingsPerEntry = getTotalSources(context);
353
- for (let i = 0; i < totalBindingsPerEntry; i++) {
354
- context.splice(index, 0, DEFAULT_BINDING_INDEX);
355
- index++;
356
- }
357
- // 6) default binding value for the new entry
358
- context.splice(index, 0, DEFAULT_BINDING_VALUE);
359
- }
360
- /**
361
- * Inserts a new binding value into a styling property tuple in the `TStylingContext`.
362
- *
363
- * A bindingValue is inserted into a context during the first update pass
364
- * of a template or host bindings function. When this occurs, two things
365
- * happen:
366
- *
367
- * - If the bindingValue value is a number then it is treated as a bindingIndex
368
- * value (a index in the `LView`) and it will be inserted next to the other
369
- * binding index entries.
370
- *
371
- * - Otherwise the binding value will update the default value for the property
372
- * and this will only happen if the default value is `null`.
373
- * @param {?} context
374
- * @param {?} index
375
- * @param {?} bindingValue
376
- * @param {?} bitIndex
377
- * @param {?} sourceIndex
378
- * @return {?}
379
- */
380
- function addBindingIntoContext(context, index, bindingValue, bitIndex, sourceIndex) {
381
- if (typeof bindingValue === 'number') {
382
- /** @type {?} */
383
- const hostBindingsMode = isHostStylingActive(sourceIndex);
384
- /** @type {?} */
385
- const cellIndex = index + 4 /* BindingsStartOffset */ + sourceIndex;
386
- context[cellIndex] = bindingValue;
387
- /** @type {?} */
388
- const updatedBitMask = getGuardMask(context, index, hostBindingsMode) | (1 << bitIndex);
389
- setGuardMask(context, index, updatedBitMask, hostBindingsMode);
390
- }
391
- else if (bindingValue !== null && getDefaultValue(context, index) === null) {
392
- setDefaultValue(context, index, bindingValue);
393
- }
394
- }
395
- /**
396
- * Registers a new column into the provided `TStylingContext`.
397
- *
398
- * If and when a new source is detected then a new column needs to
399
- * be allocated into the styling context. The column is basically
400
- * a new allocation of binding sources that will be available to each
401
- * property.
402
- *
403
- * Each column that exists in the styling context resembles a styling
404
- * source. A styling source an either be the template or one or more
405
- * components or directives all containing styling host bindings.
406
- * @param {?} context
407
- * @return {?}
408
- */
409
- function addNewSourceColumn(context) {
410
- // we use -1 here because we want to insert right before the last value (the default value)
411
- /** @type {?} */
412
- const insertOffset = 4 /* BindingsStartOffset */ + getValuesCount(context) - 1;
413
- /** @type {?} */
414
- let index = 2 /* ValuesStartPosition */;
415
- while (index < context.length) {
416
- index += insertOffset;
417
- context.splice(index++, 0, DEFAULT_BINDING_INDEX);
418
- // the value was inserted just before the default value, but the
419
- // next entry in the context starts just after it. Therefore++.
420
- index++;
421
- }
422
- context[0 /* TotalSourcesPosition */]++;
423
- }
424
- /**
425
- * Applies all pending style and class bindings to the provided element.
426
- *
427
- * This function will attempt to flush styling via the provided `classesContext`
428
- * and `stylesContext` context values. This function is designed to be run from
429
- * the internal `stylingApply` function (which is scheduled to run at the very
430
- * end of change detection for an element if one or more style/class bindings
431
- * were processed) and will rely on any state values that are set from when
432
- * any of the styling bindings executed.
433
- *
434
- * This function is designed to be called twice: one when change detection has
435
- * processed an element within the template bindings (i.e. just as `advance()`
436
- * is called) and when host bindings have been processed. In both cases the
437
- * styles and classes in both contexts will be applied to the element, but the
438
- * algorithm will selectively decide which bindings to run depending on the
439
- * columns in the context. The provided `directiveIndex` value will help the
440
- * algorithm determine which bindings to apply: either the template bindings or
441
- * the host bindings (see `applyStylingToElement` for more information).
442
- *
443
- * Note that once this function is called all temporary styling state data
444
- * (i.e. the `bitMask` and `counter` values for styles and classes will be cleared).
445
- * @param {?} renderer
446
- * @param {?} data
447
- * @param {?} tNode
448
- * @param {?} classesContext
449
- * @param {?} stylesContext
450
- * @param {?} element
451
- * @param {?} directiveIndex
452
- * @param {?} styleSanitizer
453
- * @param {?} firstUpdatePass
454
- * @return {?}
455
- */
456
- export function flushStyling(renderer, data, tNode, classesContext, stylesContext, element, directiveIndex, styleSanitizer, firstUpdatePass) {
457
- ngDevMode && ngDevMode.flushStyling++;
458
- /** @type {?} */
459
- const state = getStylingState(element, directiveIndex);
460
- /** @type {?} */
461
- const hostBindingsMode = isHostStylingActive(state.sourceIndex);
462
- if (stylesContext) {
463
- firstUpdatePass && syncContextInitialStyling(stylesContext, tNode, false);
464
- if (state.stylesBitMask !== 0) {
465
- applyStylingViaContext(stylesContext, tNode, renderer, element, data, state.stylesBitMask, setStyle, styleSanitizer, hostBindingsMode, false);
466
- }
467
- }
468
- if (classesContext) {
469
- firstUpdatePass && syncContextInitialStyling(classesContext, tNode, true);
470
- if (state.classesBitMask !== 0) {
471
- applyStylingViaContext(classesContext, tNode, renderer, element, data, state.classesBitMask, setClass, null, hostBindingsMode, true);
472
- }
473
- }
474
- resetStylingState();
475
- }
476
- /**
477
- * Registers all static styling values into the context as default values.
478
- *
479
- * Static styles are stored on the `tNode.styles` and `tNode.classes`
480
- * properties as instances of `StylingMapArray`. When an instance of
481
- * `TStylingContext` is assigned to `tNode.styles` and `tNode.classes`
482
- * then the existing initial styling values are copied into the the
483
- * `InitialStylingValuePosition` slot.
484
- *
485
- * Because all static styles/classes are collected and registered on
486
- * the initial styling array each time a directive is instantiated,
487
- * the context may not yet know about the static values. When this
488
- * function is called it will copy over all the static style/class
489
- * values from the initial styling array into the context as default
490
- * values for each of the matching entries in the context.
491
- *
492
- * Let's imagine the following example:
493
- *
494
- * ```html
495
- * <div style="color:red"
496
- * [style.color]="myColor"
497
- * dir-that-has-static-height>
498
- * ...
499
- * </div>
500
- * ```
501
- *
502
- * When the code above is processed, the underlying element/styling
503
- * instructions will create an instance of `TStylingContext` for
504
- * the `tNode.styles` property. Here's what that looks like:
505
- *
506
- * ```typescript
507
- * tNode.styles = [
508
- * // ...
509
- * // initial styles
510
- * ['color:red; height:200px', 'color', 'red', 'height', '200px'],
511
- *
512
- * 0, 0b1, 0b0, 'color', 20, null, // [style.color] binding
513
- * ]
514
- * ```
515
- *
516
- * After this function is called it will balance out the context with
517
- * the static `color` and `height` values and set them as defaults within
518
- * the context:
519
- *
520
- * ```typescript
521
- * tNode.styles = [
522
- * // ...
523
- * // initial styles
524
- * ['color:red; height:200px', 'color', 'red', 'height', '200px'],
525
- *
526
- * 0, 0b1, 0b0, 'color', 20, 'red',
527
- * 0, 0b0, 0b0, 'height', 0, '200px',
528
- * ]
529
- * ```
530
- * @param {?} context
531
- * @param {?} tNode
532
- * @param {?} isClassBased
533
- * @return {?}
534
- */
535
- function syncContextInitialStyling(context, tNode, isClassBased) {
536
- // the TStylingContext always has initial style/class values which are
537
- // stored in styling array format.
538
- updateInitialStylingOnContext(context, tNode, (/** @type {?} */ (getStylingMapArray(context))), isClassBased);
539
- }
540
- /**
541
- * Registers all initial styling entries into the provided context.
542
- *
543
- * This function will iterate over all entries in the provided `initialStyling` ar}ray and register
544
- * them as default (initial) values in the provided context. Initial styling values in a context are
545
- * the default values that are to be applied unless overwritten by a binding.
546
- *
547
- * The reason why this function exists and isn't a part of the context construction is because
548
- * host binding is evaluated at a later stage after the element is created. This means that
549
- * if a directive or component contains any initial styling code (i.e. `<div class="foo">`)
550
- * then that initial styling data can only be applied once the styling for that element
551
- * is first applied (at the end of the update phase). Once that happens then the context will
552
- * update itself with the complete initial styling for the element.
553
- * @param {?} context
554
- * @param {?} tNode
555
- * @param {?} initialStyling
556
- * @param {?} isClassBased
557
- * @return {?}
558
- */
559
- function updateInitialStylingOnContext(context, tNode, initialStyling, isClassBased) {
560
- // `-1` is used here because all initial styling data is not a apart
561
- // of a binding (since it's static)
562
- /** @type {?} */
563
- const COUNT_ID_FOR_STYLING = -1;
564
- /** @type {?} */
565
- let hasInitialStyling = false;
566
- for (let i = 1 /* ValuesStartPosition */; i < initialStyling.length; i += 2 /* TupleSize */) {
567
- /** @type {?} */
568
- const value = getMapValue(initialStyling, i);
569
- if (value) {
570
- /** @type {?} */
571
- const prop = getMapProp(initialStyling, i);
572
- registerBinding(context, tNode, COUNT_ID_FOR_STYLING, 0, prop, value, false, isClassBased);
573
- hasInitialStyling = true;
574
- }
575
- }
576
- if (hasInitialStyling) {
577
- patchConfig(tNode, 256 /* hasInitialStyling */);
578
- }
579
- }
580
- /**
581
- * Runs through the provided styling context and applies each value to
582
- * the provided element (via the renderer) if one or more values are present.
583
- *
584
- * This function will iterate over all entries present in the provided
585
- * `TStylingContext` array (both prop-based and map-based bindings).-
586
- *
587
- * Each entry, within the `TStylingContext` array, is stored alphabetically
588
- * and this means that each prop/value entry will be applied in order
589
- * (so long as it is marked dirty in the provided `bitMask` value).
590
- *
591
- * If there are any map-based entries present (which are applied to the
592
- * element via the `[style]` and `[class]` bindings) then those entries
593
- * will be applied as well. However, the code for that is not a part of
594
- * this function. Instead, each time a property is visited, then the
595
- * code below will call an external function called `stylingMapsSyncFn`
596
- * and, if present, it will keep the application of styling values in
597
- * map-based bindings up to sync with the application of prop-based
598
- * bindings.
599
- *
600
- * Visit `styling/map_based_bindings.ts` to learn more about how the
601
- * algorithm works for map-based styling bindings.
602
- *
603
- * Note that this function is not designed to be called in isolation (use
604
- * the `flushStyling` function so that it can call this function for both
605
- * the styles and classes contexts).
606
- * @param {?} context
607
- * @param {?} tNode
608
- * @param {?} renderer
609
- * @param {?} element
610
- * @param {?} bindingData
611
- * @param {?} bitMaskValue
612
- * @param {?} applyStylingFn
613
- * @param {?} sanitizer
614
- * @param {?} hostBindingsMode
615
- * @param {?} isClassBased
616
- * @return {?}
617
- */
618
- export function applyStylingViaContext(context, tNode, renderer, element, bindingData, bitMaskValue, applyStylingFn, sanitizer, hostBindingsMode, isClassBased) {
619
- /** @type {?} */
620
- const bitMask = normalizeBitMaskValue(bitMaskValue);
621
- /** @type {?} */
622
- let stylingMapsSyncFn = null;
623
- /** @type {?} */
624
- let applyAllValues = false;
625
- /** @type {?} */
626
- const mapBindingsFlag = isClassBased ? 512 /* hasClassMapBindings */ : 16384 /* hasStyleMapBindings */;
627
- if (hasConfig(tNode, mapBindingsFlag)) {
628
- stylingMapsSyncFn = getStylingMapsSyncFn();
629
- /** @type {?} */
630
- const mapsGuardMask = getGuardMask(context, 2 /* ValuesStartPosition */, hostBindingsMode);
631
- applyAllValues = (bitMask & mapsGuardMask) !== 0;
632
- }
633
- /** @type {?} */
634
- const valuesCount = getValuesCount(context);
635
- /** @type {?} */
636
- let totalBindingsToVisit = 1;
637
- /** @type {?} */
638
- let mapsMode = applyAllValues ? 1 /* ApplyAllValues */ : 0 /* TraverseValues */;
639
- if (hostBindingsMode) {
640
- mapsMode |= 8 /* RecurseInnerMaps */;
641
- totalBindingsToVisit = valuesCount - 1;
642
- }
643
- /** @type {?} */
644
- let i = getPropValuesStartPosition(context, tNode, isClassBased);
645
- while (i < context.length) {
646
- /** @type {?} */
647
- const guardMask = getGuardMask(context, i, hostBindingsMode);
648
- if (bitMask & guardMask) {
649
- /** @type {?} */
650
- let valueApplied = false;
651
- /** @type {?} */
652
- const prop = getProp(context, i);
653
- /** @type {?} */
654
- const defaultValue = getDefaultValue(context, i);
655
- // Part 1: Visit the `[styling.prop]` value
656
- for (let j = 0; j < totalBindingsToVisit; j++) {
657
- /** @type {?} */
658
- const bindingIndex = (/** @type {?} */ (getBindingValue(context, i, j)));
659
- if (!valueApplied && bindingIndex !== 0) {
660
- /** @type {?} */
661
- const value = getValue(bindingData, bindingIndex);
662
- if (isStylingValueDefined(value)) {
663
- /** @type {?} */
664
- const checkValueOnly = hostBindingsMode && j === 0;
665
- if (!checkValueOnly) {
666
- /** @type {?} */
667
- const finalValue = sanitizer && isSanitizationRequired(context, i) ?
668
- sanitizer(prop, value, 2 /* SanitizeOnly */) :
669
- unwrapSafeValue(value);
670
- applyStylingFn(renderer, element, prop, finalValue, bindingIndex);
671
- }
672
- valueApplied = true;
673
- }
674
- }
675
- // Part 2: Visit the `[style]` or `[class]` map-based value
676
- if (stylingMapsSyncFn) {
677
- // determine whether or not to apply the target property or to skip it
678
- /** @type {?} */
679
- let mode = mapsMode | (valueApplied ? 4 /* SkipTargetProp */ :
680
- 2 /* ApplyTargetProp */);
681
- // the first column in the context (when `j == 0`) is special-cased for
682
- // template bindings. If and when host bindings are being processed then
683
- // the first column will still be iterated over, but the values will only
684
- // be checked against (not applied). If and when this happens we need to
685
- // notify the map-based syncing code to know not to apply the values it
686
- // comes across in the very first map-based binding (which is also located
687
- // in column zero).
688
- if (hostBindingsMode && j === 0) {
689
- mode |= 16 /* CheckValuesOnly */;
690
- }
691
- /** @type {?} */
692
- const valueAppliedWithinMap = stylingMapsSyncFn(context, renderer, element, bindingData, j, applyStylingFn, sanitizer, mode, prop, defaultValue);
693
- valueApplied = valueApplied || valueAppliedWithinMap;
694
- }
695
- }
696
- // Part 3: apply the default value (e.g. `<div style="width:200">` => `200px` gets applied)
697
- // if the value has not yet been applied then a truthy value does not exist in the
698
- // prop-based or map-based bindings code. If and when this happens, just apply the
699
- // default value (even if the default value is `null`).
700
- if (!valueApplied) {
701
- applyStylingFn(renderer, element, prop, defaultValue);
702
- }
703
- }
704
- i += 4 /* BindingsStartOffset */ + valuesCount;
705
- }
706
- // the map-based styling entries may have not applied all their
707
- // values. For this reason, one more call to the sync function
708
- // needs to be issued at the end.
709
- if (stylingMapsSyncFn) {
710
- if (hostBindingsMode) {
711
- mapsMode |= 16 /* CheckValuesOnly */;
712
- }
713
- stylingMapsSyncFn(context, renderer, element, bindingData, 0, applyStylingFn, sanitizer, mapsMode);
714
- }
715
- }
716
- /**
717
- * Applies the provided styling map to the element directly (without context resolution).
718
- *
719
- * This function is designed to be run from the styling instructions and will be called
720
- * automatically. This function is intended to be used for performance reasons in the
721
- * event that there is no need to apply styling via context resolution.
722
- *
723
- * This function has three different cases that can occur (for each item in the map):
724
- *
725
- * - Case 1: Attempt to apply the current value in the map to the element (if it's `non null`).
726
- *
727
- * - Case 2: If a map value fails to be applied then the algorithm will find a matching entry in
728
- * the initial values present in the context and attempt to apply that.
729
- *
730
- * - Default Case: If the initial value cannot be applied then a default value of `null` will be
731
- * applied (which will remove the style/class value from the element).
732
- *
733
- * See `allowDirectStylingApply` to learn the logic used to determine whether any style/class
734
- * bindings can be directly applied.
735
- *
736
- * @param {?} renderer
737
- * @param {?} context
738
- * @param {?} tNode
739
- * @param {?} element
740
- * @param {?} data
741
- * @param {?} bindingIndex
742
- * @param {?} value
743
- * @param {?} isClassBased
744
- * @param {?} sanitizer
745
- * @param {?} forceUpdate
746
- * @param {?} bindingValueContainsInitial
747
- * @return {?} whether or not the styling map was applied to the element.
748
- */
749
- export function applyStylingMapDirectly(renderer, context, tNode, element, data, bindingIndex, value, isClassBased, sanitizer, forceUpdate, bindingValueContainsInitial) {
750
- /** @type {?} */
751
- const oldValue = getValue(data, bindingIndex);
752
- if (forceUpdate || hasValueChanged(oldValue, value)) {
753
- /** @type {?} */
754
- const hasInitial = hasConfig(tNode, 256 /* hasInitialStyling */);
755
- /** @type {?} */
756
- const initialValue = hasInitial && !bindingValueContainsInitial ? getInitialStylingValue(context) : null;
757
- setValue(data, bindingIndex, value);
758
- // the cached value is the last snapshot of the style or class
759
- // attribute value and is used in the if statement below to
760
- // keep track of internal/external changes.
761
- /** @type {?} */
762
- const cachedValueIndex = bindingIndex + 1;
763
- /** @type {?} */
764
- let cachedValue = getValue(data, cachedValueIndex);
765
- if (cachedValue === NO_CHANGE) {
766
- cachedValue = initialValue;
767
- }
768
- cachedValue = typeof cachedValue !== 'string' ? '' : cachedValue;
769
- // If a class/style value was modified externally then the styling
770
- // fast pass cannot guarantee that the external values are retained.
771
- // When this happens, the algorithm will bail out and not write to
772
- // the style or className attribute directly.
773
- /** @type {?} */
774
- const propBindingsFlag = isClassBased ? 1024 /* hasClassPropBindings */ : 32768 /* hasStylePropBindings */;
775
- /** @type {?} */
776
- let writeToAttrDirectly = !hasConfig(tNode, propBindingsFlag);
777
- if (writeToAttrDirectly &&
778
- checkIfExternallyModified((/** @type {?} */ (element)), cachedValue, isClassBased)) {
779
- writeToAttrDirectly = false;
780
- if (oldValue !== VALUE_IS_EXTERNALLY_MODIFIED) {
781
- // direct styling will reset the attribute entirely each time,
782
- // and, for this reason, if the algorithm decides it cannot
783
- // write to the class/style attributes directly then it must
784
- // reset all the previous style/class values before it starts
785
- // to apply values in the non-direct way.
786
- removeStylingValues(renderer, element, oldValue, isClassBased);
787
- // this will instruct the algorithm not to apply class or style
788
- // values directly anymore.
789
- setValue(data, cachedValueIndex, VALUE_IS_EXTERNALLY_MODIFIED);
790
- }
791
- }
792
- if (writeToAttrDirectly) {
793
- /** @type {?} */
794
- const initialValue = hasInitial && !bindingValueContainsInitial ? getInitialStylingValue(context) : null;
795
- /** @type {?} */
796
- const valueToApply = writeStylingValueDirectly(renderer, element, value, isClassBased, initialValue);
797
- setValue(data, cachedValueIndex, valueToApply || null);
798
- }
799
- else {
800
- /** @type {?} */
801
- const applyFn = isClassBased ? setClass : setStyle;
802
- /** @type {?} */
803
- const map = normalizeIntoStylingMap(oldValue, value, !isClassBased);
804
- /** @type {?} */
805
- const initialStyles = hasInitial ? getStylingMapArray(context) : null;
806
- for (let i = 1 /* ValuesStartPosition */; i < map.length; i += 2 /* TupleSize */) {
807
- /** @type {?} */
808
- const prop = getMapProp(map, i);
809
- /** @type {?} */
810
- const value = getMapValue(map, i);
811
- // case 1: apply the map value (if it exists)
812
- /** @type {?} */
813
- let applied = applyStylingValue(renderer, element, prop, value, applyFn, bindingIndex, sanitizer);
814
- // case 2: apply the initial value (if it exists)
815
- if (!applied && initialStyles) {
816
- applied = findAndApplyMapValue(renderer, element, applyFn, initialStyles, prop, bindingIndex, sanitizer);
817
- }
818
- // default case: apply `null` to remove the value
819
- if (!applied) {
820
- applyFn(renderer, element, prop, null, bindingIndex);
821
- }
822
- }
823
- /** @type {?} */
824
- const state = getStylingState(element, TEMPLATE_DIRECTIVE_INDEX);
825
- if (isClassBased) {
826
- state.lastDirectClassMap = map;
827
- }
828
- else {
829
- state.lastDirectStyleMap = map;
830
- }
831
- }
832
- }
833
- }
834
- /**
835
- * @param {?} renderer
836
- * @param {?} element
837
- * @param {?} value
838
- * @param {?} isClassBased
839
- * @param {?} initialValue
840
- * @return {?}
841
- */
842
- export function writeStylingValueDirectly(renderer, element, value, isClassBased, initialValue) {
843
- /** @type {?} */
844
- let valueToApply;
845
- if (isClassBased) {
846
- valueToApply = typeof value === 'string' ? value : objectToClassName(value);
847
- if (initialValue !== null) {
848
- valueToApply = concatString(initialValue, valueToApply, ' ');
849
- }
850
- setClassName(renderer, element, valueToApply);
851
- }
852
- else {
853
- valueToApply = forceStylesAsString(value, true);
854
- if (initialValue !== null) {
855
- valueToApply = initialValue + ';' + valueToApply;
856
- }
857
- setStyleAttr(renderer, element, valueToApply);
858
- }
859
- return valueToApply;
860
- }
861
- /**
862
- * Applies the provided styling prop/value to the element directly (without context resolution).
863
- *
864
- * This function is designed to be run from the styling instructions and will be called
865
- * automatically. This function is intended to be used for performance reasons in the
866
- * event that there is no need to apply styling via context resolution.
867
- *
868
- * This function has four different cases that can occur:
869
- *
870
- * - Case 1: Apply the provided prop/value (style or class) entry to the element
871
- * (if it is `non null`).
872
- *
873
- * - Case 2: If value does not get applied (because its `null` or `undefined`) then the algorithm
874
- * will check to see if a styling map value was applied to the element as well just
875
- * before this (via `styleMap` or `classMap`). If and when a map is present then the
876
- * algorithm will find the matching property in the map and apply its value.
877
- *
878
- * - Case 3: If a map value fails to be applied then the algorithm will check to see if there
879
- * are any initial values present and attempt to apply a matching value based on
880
- * the target prop.
881
- *
882
- * - Default Case: If a matching initial value cannot be applied then a default value
883
- * of `null` will be applied (which will remove the style/class value
884
- * from the element).
885
- *
886
- * See `allowDirectStylingApply` to learn the logic used to determine whether any style/class
887
- * bindings can be directly applied.
888
- *
889
- * @param {?} renderer
890
- * @param {?} context
891
- * @param {?} tNode
892
- * @param {?} element
893
- * @param {?} data
894
- * @param {?} bindingIndex
895
- * @param {?} prop
896
- * @param {?} value
897
- * @param {?} isClassBased
898
- * @param {?=} sanitizer
899
- * @return {?} whether or not the prop/value styling was applied to the element.
900
- */
901
- export function applyStylingValueDirectly(renderer, context, tNode, element, data, bindingIndex, prop, value, isClassBased, sanitizer) {
902
- /** @type {?} */
903
- let applied = false;
904
- if (hasValueChanged(data[bindingIndex], value)) {
905
- setValue(data, bindingIndex, value);
906
- /** @type {?} */
907
- const applyFn = isClassBased ? setClass : setStyle;
908
- // case 1: apply the provided value (if it exists)
909
- applied = applyStylingValue(renderer, element, prop, value, applyFn, bindingIndex, sanitizer);
910
- // case 2: find the matching property in a styling map and apply the detected value
911
- /** @type {?} */
912
- const mapBindingsFlag = isClassBased ? 512 /* hasClassMapBindings */ : 16384 /* hasStyleMapBindings */;
913
- if (!applied && hasConfig(tNode, mapBindingsFlag)) {
914
- /** @type {?} */
915
- const state = getStylingState(element, TEMPLATE_DIRECTIVE_INDEX);
916
- /** @type {?} */
917
- const map = isClassBased ? state.lastDirectClassMap : state.lastDirectStyleMap;
918
- applied = map ?
919
- findAndApplyMapValue(renderer, element, applyFn, map, prop, bindingIndex, sanitizer) :
920
- false;
921
- }
922
- // case 3: apply the initial value (if it exists)
923
- if (!applied && hasConfig(tNode, 256 /* hasInitialStyling */)) {
924
- /** @type {?} */
925
- const map = getStylingMapArray(context);
926
- applied =
927
- map ? findAndApplyMapValue(renderer, element, applyFn, map, prop, bindingIndex) : false;
928
- }
929
- // default case: apply `null` to remove the value
930
- if (!applied) {
931
- applyFn(renderer, element, prop, null, bindingIndex);
932
- }
933
- }
934
- return applied;
935
- }
936
- /**
937
- * @param {?} renderer
938
- * @param {?} element
939
- * @param {?} prop
940
- * @param {?} value
941
- * @param {?} applyFn
942
- * @param {?} bindingIndex
943
- * @param {?=} sanitizer
944
- * @return {?}
945
- */
946
- function applyStylingValue(renderer, element, prop, value, applyFn, bindingIndex, sanitizer) {
947
- /** @type {?} */
948
- let valueToApply = unwrapSafeValue(value);
949
- if (isStylingValueDefined(valueToApply)) {
950
- valueToApply =
951
- sanitizer ? sanitizer(prop, value, 3 /* ValidateAndSanitize */) : valueToApply;
952
- applyFn(renderer, element, prop, valueToApply, bindingIndex);
953
- return true;
954
- }
955
- return false;
956
- }
957
- /**
958
- * @param {?} renderer
959
- * @param {?} element
960
- * @param {?} applyFn
961
- * @param {?} map
962
- * @param {?} prop
963
- * @param {?} bindingIndex
964
- * @param {?=} sanitizer
965
- * @return {?}
966
- */
967
- function findAndApplyMapValue(renderer, element, applyFn, map, prop, bindingIndex, sanitizer) {
968
- for (let i = 1 /* ValuesStartPosition */; i < map.length; i += 2 /* TupleSize */) {
969
- /** @type {?} */
970
- const p = getMapProp(map, i);
971
- if (p === prop) {
972
- /** @type {?} */
973
- let valueToApply = getMapValue(map, i);
974
- valueToApply = sanitizer ?
975
- sanitizer(prop, valueToApply, 3 /* ValidateAndSanitize */) :
976
- valueToApply;
977
- applyFn(renderer, element, prop, valueToApply, bindingIndex);
978
- return true;
979
- }
980
- if (p > prop) {
981
- break;
982
- }
983
- }
984
- return false;
985
- }
986
- /**
987
- * @param {?} value
988
- * @return {?}
989
- */
990
- function normalizeBitMaskValue(value) {
991
- // if pass => apply all values (-1 implies that all bits are flipped to true)
992
- if (value === true)
993
- return -1;
994
- // if pass => skip all values
995
- if (value === false)
996
- return 0;
997
- // return the bit mask value as is
998
- return value;
999
- }
1000
- /** @type {?} */
1001
- let _activeStylingMapApplyFn = null;
1002
- /**
1003
- * @return {?}
1004
- */
1005
- export function getStylingMapsSyncFn() {
1006
- return _activeStylingMapApplyFn;
1007
- }
1008
- /**
1009
- * @param {?} fn
1010
- * @return {?}
1011
- */
1012
- export function setStylingMapsSyncFn(fn) {
1013
- _activeStylingMapApplyFn = fn;
1014
- }
1015
- /**
1016
- * Assigns a style value to a style property for the given element.
1017
- * @type {?}
1018
- */
1019
- export const setStyle = (/**
1020
- * @param {?} renderer
1021
- * @param {?} native
1022
- * @param {?} prop
1023
- * @param {?} value
1024
- * @return {?}
1025
- */
1026
- (renderer, native, prop, value) => {
1027
- if (renderer !== null) {
1028
- // Use `isStylingValueDefined` to account for falsy values that should be bound like 0.
1029
- if (isStylingValueDefined(value)) {
1030
- // opacity, z-index and flexbox all have number values
1031
- // and these need to be converted into strings so that
1032
- // they can be assigned properly.
1033
- value = value.toString();
1034
- ngDevMode && ngDevMode.rendererSetStyle++;
1035
- if (isProceduralRenderer(renderer)) {
1036
- renderer.setStyle(native, prop, value, RendererStyleFlags3.DashCase);
1037
- }
1038
- else {
1039
- // The reason why native style may be `null` is either because
1040
- // it's a container element or it's a part of a test
1041
- // environment that doesn't have styling. In either
1042
- // case it's safe not to apply styling to the element.
1043
- /** @type {?} */
1044
- const nativeStyle = native.style;
1045
- if (nativeStyle != null) {
1046
- nativeStyle.setProperty(prop, value);
1047
- }
1048
- }
1049
- }
1050
- else {
1051
- ngDevMode && ngDevMode.rendererRemoveStyle++;
1052
- if (isProceduralRenderer(renderer)) {
1053
- renderer.removeStyle(native, prop, RendererStyleFlags3.DashCase);
1054
- }
1055
- else {
1056
- /** @type {?} */
1057
- const nativeStyle = native.style;
1058
- if (nativeStyle != null) {
1059
- nativeStyle.removeProperty(prop);
1060
- }
1061
- }
1062
- }
1063
- }
1064
- });
1065
- /**
1066
- * Adds/removes the provided className value to the provided element.
1067
- * @type {?}
1068
- */
1069
- export const setClass = (/**
1070
- * @param {?} renderer
1071
- * @param {?} native
1072
- * @param {?} className
1073
- * @param {?} value
1074
- * @return {?}
1075
- */
1076
- (renderer, native, className, value) => {
1077
- if (renderer !== null && className !== '') {
1078
- if (value) {
1079
- ngDevMode && ngDevMode.rendererAddClass++;
1080
- if (isProceduralRenderer(renderer)) {
1081
- renderer.addClass(native, className);
1082
- }
1083
- else {
1084
- // the reason why classList may be `null` is either because
1085
- // it's a container element or it's a part of a test
1086
- // environment that doesn't have styling. In either
1087
- // case it's safe not to apply styling to the element.
1088
- /** @type {?} */
1089
- const classList = native.classList;
1090
- if (classList != null) {
1091
- classList.add(className);
1092
- }
1093
- }
1094
- }
1095
- else {
1096
- ngDevMode && ngDevMode.rendererRemoveClass++;
1097
- if (isProceduralRenderer(renderer)) {
1098
- renderer.removeClass(native, className);
1099
- }
1100
- else {
1101
- /** @type {?} */
1102
- const classList = native.classList;
1103
- if (classList != null) {
1104
- classList.remove(className);
1105
- }
1106
- }
1107
- }
1108
- }
1109
- });
1110
- /** @type {?} */
1111
- export const setClassName = (/**
1112
- * @param {?} renderer
1113
- * @param {?} native
1114
- * @param {?} className
1115
- * @return {?}
1116
- */
1117
- (renderer, native, className) => {
1118
- if (renderer !== null) {
1119
- if (isProceduralRenderer(renderer)) {
1120
- renderer.setAttribute(native, 'class', className);
1121
- }
1122
- else {
1123
- native.className = className;
1124
- }
1125
- }
1126
- });
1127
- /** @type {?} */
1128
- export const setStyleAttr = (/**
1129
- * @param {?} renderer
1130
- * @param {?} native
1131
- * @param {?} value
1132
- * @return {?}
1133
- */
1134
- (renderer, native, value) => {
1135
- if (renderer !== null) {
1136
- if (isProceduralRenderer(renderer)) {
1137
- renderer.setAttribute(native, 'style', value);
1138
- }
1139
- else {
1140
- native.setAttribute('style', value);
1141
- }
1142
- }
1143
- });
1144
- /**
1145
- * Iterates over all provided styling entries and renders them on the element.
1146
- *
1147
- * This function is used alongside a `StylingMapArray` entry. This entry is not
1148
- * the same as the `TStylingContext` and is only really used when an element contains
1149
- * initial styling values (e.g. `<div style="width:200px">`), but no style/class bindings
1150
- * are present. If and when that happens then this function will be called to render all
1151
- * initial styling values on an element.
1152
- * @param {?} renderer
1153
- * @param {?} element
1154
- * @param {?} stylingValues
1155
- * @param {?} isClassBased
1156
- * @return {?}
1157
- */
1158
- export function renderStylingMap(renderer, element, stylingValues, isClassBased) {
1159
- /** @type {?} */
1160
- const stylingMapArr = getStylingMapArray(stylingValues);
1161
- if (stylingMapArr) {
1162
- for (let i = 1 /* ValuesStartPosition */; i < stylingMapArr.length; i += 2 /* TupleSize */) {
1163
- /** @type {?} */
1164
- const prop = getMapProp(stylingMapArr, i);
1165
- /** @type {?} */
1166
- const value = getMapValue(stylingMapArr, i);
1167
- if (isClassBased) {
1168
- setClass(renderer, element, prop, value, null);
1169
- }
1170
- else {
1171
- setStyle(renderer, element, prop, value, null);
1172
- }
1173
- }
1174
- }
1175
- }
1176
- /**
1177
- * @param {?} obj
1178
- * @return {?}
1179
- */
1180
- function objectToClassName(obj) {
1181
- /** @type {?} */
1182
- let str = '';
1183
- if (obj) {
1184
- for (let key in obj) {
1185
- /** @type {?} */
1186
- const value = obj[key];
1187
- if (value) {
1188
- str += (str.length ? ' ' : '') + key;
1189
- }
1190
- }
1191
- }
1192
- return str;
1193
- }
1194
- /**
1195
- * Determines whether or not an element style/className value has changed since the last update.
1196
- *
1197
- * This function helps Angular determine if a style or class attribute value was
1198
- * modified by an external plugin or API outside of the style binding code. This
1199
- * means any JS code that adds/removes class/style values on an element outside
1200
- * of Angular's styling binding algorithm.
1201
- *
1202
- * @param {?} element
1203
- * @param {?} cachedValue
1204
- * @param {?} isClassBased
1205
- * @return {?} true when the value was modified externally.
1206
- */
1207
- function checkIfExternallyModified(element, cachedValue, isClassBased) {
1208
- // this means it was checked before and there is no reason
1209
- // to compare the style/class values again. Either that or
1210
- // web workers are being used.
1211
- if (global.Node === 'undefined' || cachedValue === VALUE_IS_EXTERNALLY_MODIFIED)
1212
- return true;
1213
- // comparing the DOM value against the cached value is the best way to
1214
- // see if something has changed.
1215
- /** @type {?} */
1216
- const currentValue = (isClassBased ? element.className : (element.style && element.style.cssText)) || '';
1217
- return currentValue !== (cachedValue || '');
1218
- }
1219
- /**
1220
- * Removes provided styling values from the element
1221
- * @param {?} renderer
1222
- * @param {?} element
1223
- * @param {?} values
1224
- * @param {?} isClassBased
1225
- * @return {?}
1226
- */
1227
- function removeStylingValues(renderer, element, values, isClassBased) {
1228
- /** @type {?} */
1229
- let arr;
1230
- if (isStylingMapArray(values)) {
1231
- arr = (/** @type {?} */ (values));
1232
- }
1233
- else {
1234
- arr = normalizeIntoStylingMap(null, values, !isClassBased);
1235
- }
1236
- /** @type {?} */
1237
- const applyFn = isClassBased ? setClass : setStyle;
1238
- for (let i = 1 /* ValuesStartPosition */; i < arr.length; i += 2 /* TupleSize */) {
1239
- /** @type {?} */
1240
- const value = getMapValue(arr, i);
1241
- if (value) {
1242
- /** @type {?} */
1243
- const prop = getMapProp(arr, i);
1244
- applyFn(renderer, element, prop, null);
1245
- }
1246
- }
1247
- }
1248
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmluZGluZ3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb3JlL3NyYy9yZW5kZXIzL3N0eWxpbmcvYmluZGluZ3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBT0EsT0FBTyxFQUFZLGVBQWUsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBRXJFLE9BQU8sRUFBQyxNQUFNLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUV6QyxPQUFPLEVBQTJDLG1CQUFtQixFQUFFLG9CQUFvQixFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFFM0gsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUMscUJBQXFCLEVBQUUscUJBQXFCLEVBQUUsd0JBQXdCLEVBQUUseUJBQXlCLEVBQUUsd0JBQXdCLEVBQUUsWUFBWSxFQUFFLG1CQUFtQixFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsWUFBWSxFQUFFLHNCQUFzQixFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLGtCQUFrQixFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsbUJBQW1CLEVBQUUsc0JBQXNCLEVBQUUsaUJBQWlCLEVBQUUscUJBQXFCLEVBQUUsdUJBQXVCLEVBQUUsV0FBVyxFQUFFLGVBQWUsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLFFBQVEsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBRTNsQixPQUFPLEVBQUMsZUFBZSxFQUFFLGlCQUFpQixFQUFDLE1BQU0sU0FBUyxDQUFDOztNQUVyRCw0QkFBNEIsR0FBRyxFQUFFOzs7Ozs7O01BMEJqQyw2QkFBNkIsR0FBRyxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBWXZDLE1BQU0sVUFBVSxxQkFBcUIsQ0FDakMsT0FBd0IsRUFBRSxLQUFtQixFQUFFLElBQWtCLEVBQUUsT0FBaUIsRUFDcEYsY0FBc0IsRUFBRSxJQUFtQixFQUFFLFlBQW9CLEVBQ2pFLEtBQXdFLEVBQUUsV0FBb0IsRUFDOUYsZUFBd0I7O1VBQ3BCLFVBQVUsR0FBRyxDQUFDLElBQUk7O1VBQ2xCLEtBQUssR0FBRyxlQUFlLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQzs7VUFDaEQsVUFBVSxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsNkJBQTZCLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUU7SUFFcEYscUZBQXFGO0lBQ3JGLG9GQUFvRjtJQUNwRiw2RUFBNkU7SUFDN0UsSUFBSSxlQUFlLElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRTs7Y0FDcEMsT0FBTyxHQUFHLGlCQUFpQixDQUM3QixPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsS0FBSyxDQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQzNGLEtBQUssRUFBRSxlQUFlLEVBQUUsSUFBSSxDQUFDO1FBQ2pDLElBQUksT0FBTyxJQUFJLFdBQVcsRUFBRTtZQUMxQiw2REFBNkQ7WUFDN0QsbUVBQW1FO1lBQ25FLG1FQUFtRTtZQUNuRSwrREFBK0Q7WUFDL0Qsc0JBQXNCO1lBQ3RCLEtBQUssQ0FBQyxjQUFjLElBQUksQ0FBQyxJQUFJLFVBQVUsQ0FBQztZQUN4QyxPQUFPLElBQUksQ0FBQztTQUNiO0tBQ0Y7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBWUQsTUFBTSxVQUFVLHFCQUFxQixDQUNqQyxPQUF3QixFQUFFLEtBQW1CLEVBQUUsSUFBa0IsRUFBRSxPQUFpQixFQUNwRixjQUFzQixFQUFFLElBQW1CLEVBQUUsWUFBb0IsRUFDakUsS0FBbUYsRUFDbkYsU0FBaUMsRUFBRSxXQUFvQixFQUFFLGVBQXdCOztVQUM3RSxVQUFVLEdBQUcsQ0FBQyxJQUFJOztVQUNsQixLQUFLLEdBQUcsZUFBZSxDQUFDLE9BQU8sRUFBRSxjQUFjLENBQUM7O1VBQ2hELFVBQVUsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLDZCQUE2QixDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFO0lBRW5GLHFGQUFxRjtJQUNyRixvRkFBb0Y7SUFDcEYsNkVBQTZFO0lBQzdFLElBQUksZUFBZSxJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUU7O2NBQ3BDLG9CQUFvQixHQUFHLFVBQVUsQ0FBQyxDQUFDO1lBQ3JDLElBQUksQ0FBQyxDQUFDO1lBQ04sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxtQkFBQSxJQUFJLEVBQUUsRUFBRSxJQUFJLDJCQUFxQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7O2NBQy9FLE9BQU8sR0FBRyxpQkFBaUIsQ0FDN0IsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEtBQUssQ0FBQyxXQUFXLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUMzRixvQkFBb0IsRUFBRSxlQUFlLEVBQUUsS0FBSyxDQUFDO1FBQ2pELElBQUksT0FBTyxJQUFJLFdBQVcsRUFBRTtZQUMxQiw2REFBNkQ7WUFDN0QsbUVBQW1FO1lBQ25FLGtFQUFrRTtZQUNsRSwrREFBK0Q7WUFDL0QseUJBQXlCO1lBQ3pCLEtBQUssQ0FBQyxhQUFhLElBQUksQ0FBQyxJQUFJLFVBQVUsQ0FBQztZQUN2QyxPQUFPLElBQUksQ0FBQztTQUNiO0tBQ0Y7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWFELFNBQVMsaUJBQWlCLENBQ3RCLE9BQXdCLEVBQUUsS0FBbUIsRUFBRSxJQUFrQixFQUFFLFlBQW9CLEVBQ3ZGLFdBQW1CLEVBQUUsSUFBbUIsRUFBRSxZQUFvQixFQUM5RCxLQUFpRixFQUNqRixXQUFvQixFQUFFLG9CQUE2QixFQUFFLGVBQXdCLEVBQzdFLFlBQXFCOztVQUNqQixnQkFBZ0IsR0FBRyxtQkFBbUIsQ0FBQyxXQUFXLENBQUM7O1VBQ25ELGdCQUFnQixHQUNsQixZQUFZLENBQUMsQ0FBQyxpQ0FBaUMsQ0FBQyxrQ0FBZ0M7SUFDcEYsSUFBSSxlQUFlLEVBQUU7UUFDbkIsNERBQTREO1FBQzVELCtEQUErRDtRQUMvRCwrREFBK0Q7UUFDL0Qsa0VBQWtFO1FBQ2xFLDZEQUE2RDtRQUM3RCw0REFBNEQ7UUFDNUQsZUFBZSxDQUNYLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUNuRixZQUFZLENBQUMsQ0FBQztLQUNuQjs7VUFFSyxPQUFPLEdBQUcsV0FBVyxJQUFJLGVBQWUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsS0FBSyxDQUFDO0lBQ3pFLElBQUksT0FBTyxFQUFFO1FBQ1gsUUFBUSxDQUFDLElBQUksRUFBRSxZQUFZLEVBQUUsS0FBSyxDQUFDLENBQUM7O2NBQzlCLGtCQUFrQixHQUNwQixTQUFTLENBQUMsS0FBSyxFQUFFLGdCQUFnQixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNyRixJQUFJLGtCQUFrQixFQUFFO1lBQ3RCLHlCQUF5QixDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxZQUFZLENBQUMsQ0FBQztTQUNyRTtLQUNGO0lBQ0QsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBYUQsU0FBUyx5QkFBeUIsQ0FDOUIsT0FBd0IsRUFBRSxLQUFtQixFQUFFLElBQWtCLEVBQUUsSUFBbUIsRUFDdEYsWUFBcUI7O1VBQ2pCLFdBQVcsR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDOztVQUVyQyxnQkFBZ0IsR0FDbEIsWUFBWSxDQUFDLENBQUMsaUNBQWlDLENBQUMsa0NBQWdDO0lBQ3BGLElBQUksSUFBSSxLQUFLLElBQUksSUFBSSxTQUFTLENBQUMsS0FBSyxFQUFFLGdCQUFnQixDQUFDLEVBQUU7O2NBQ2pELFdBQVcsR0FBRyw4QkFBMkMsV0FBVzs7WUFFdEUsQ0FBQyw4QkFBMkM7O1lBQzVDLEtBQUssR0FBRyxLQUFLO1FBQ2pCLE9BQU8sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUU7WUFDekIsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxLQUFLLElBQUksRUFBRTtnQkFDaEMsS0FBSyxHQUFHLElBQUksQ0FBQztnQkFDYixNQUFNO2FBQ1A7WUFDRCxDQUFDLElBQUksV0FBVyxDQUFDO1NBQ2xCO1FBRUQsSUFBSSxLQUFLLEVBQUU7O2tCQUNILGFBQWEsR0FBRyxDQUFDLDhCQUEyQzs7a0JBQzVELFdBQVcsR0FBRyxhQUFhLEdBQUcsQ0FBQzs7O2tCQUMvQixTQUFTLEdBQUcsYUFBYSxHQUFHLFdBQVcsR0FBRyxDQUFDO1lBRWpELEtBQUssSUFBSSxDQUFDLEdBQUcsV0FBVyxFQUFFLENBQUMsR0FBRyxTQUFTLEVBQUUsQ0FBQyxFQUFFLEVBQUU7O3NCQUN0QyxZQUFZLEdBQUcsbUJBQUEsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFVO2dCQUN6QyxJQUFJLFlBQVksS0FBSyxDQUFDLEVBQUU7b0JBQ3RCLFFBQVEsQ0FBQyxJQUFJLEVBQUUsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFDO2lCQUNwQzthQUNGO1NBQ0Y7S0FDRjs7VUFFSyxlQUFlLEdBQ2pCLFlBQVksQ0FBQyxDQUFDLCtCQUFnQyxDQUFDLGdDQUErQjtJQUNsRixJQUFJLFNBQVMsQ0FBQyxLQUFLLEVBQUUsZUFBZSxDQUFDLEVBQUU7O2NBQy9CLGFBQWEsR0FDZix5REFBbUY7O2NBQ2pGLFdBQVcsR0FBRyxhQUFhLEdBQUcsQ0FBQzs7O2NBQy9CLFNBQVMsR0FBRyxhQUFhLEdBQUcsV0FBVyxHQUFHLENBQUM7UUFDakQsS0FBSyxJQUFJLENBQUMsR0FBRyxXQUFXLEVBQUUsQ0FBQyxHQUFHLFNBQVMsRUFBRSxDQUFDLEVBQUUsRUFBRTs7a0JBQ3RDLFVBQVUsR0FBRyxRQUFRLENBQWtCLElBQUksRUFBRSxtQkFBQSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQVUsQ0FBQztZQUN4RSxJQUFJLFVBQVUsRUFBRTtnQkFDZCxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDM0I7U0FDRjtLQUNGO0FBQ0gsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWdDRCxNQUFNLFVBQVUsZUFBZSxDQUMzQixPQUF3QixFQUFFLEtBQW1CLEVBQUUsT0FBZSxFQUFFLFdBQW1CLEVBQ25GLElBQW1CLEVBQUUsWUFBOEMsRUFDbkUsb0JBQTZCLEVBQUUsWUFBcUI7O1FBQ2xELEtBQUssR0FBRyxLQUFLO0lBQ2pCLElBQUksR0FBRyxJQUFJLElBQUkseUJBQXlCLENBQUM7O1FBRXJDLFlBQVksR0FBRyxlQUFlLENBQUMsT0FBTyxDQUFDO0lBRTNDLDJFQUEyRTtJQUMzRSwyRUFBMkU7SUFDM0UsbURBQW1EO0lBQ25ELE9BQU8sWUFBWSxJQUFJLFdBQVcsRUFBRTtRQUNsQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM1QixZQUFZLEVBQUUsQ0FBQztLQUNoQjs7VUFFSyxhQUFhLEdBQ2YsWUFBWSxDQUFDLENBQUMsc0NBQXNDLENBQUMsdUNBQXFDOztVQUN4RixtQkFBbUIsR0FBRyxPQUFPLFlBQVksS0FBSyxRQUFROztVQUN0RCxhQUFhLEdBQUcsOEJBQTJDLGNBQWMsQ0FBQyxPQUFPLENBQUM7O1FBQ3BGLENBQUMsOEJBQTJDO0lBRWhELHVEQUF1RDtJQUN2RCxPQUFPLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFOztjQUNuQixDQUFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDN0IsSUFBSSxJQUFJLElBQUksQ0FBQyxFQUFFO1lBQ2IsSUFBSSxJQUFJLEdBQUcsQ0FBQyxFQUFFO2dCQUNaLHVCQUF1QixDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLG9CQUFvQixDQUFDLENBQUM7YUFDakU7aUJBQU0sSUFBSSxtQkFBbUIsRUFBRTtnQkFDOUIsV0FBVyxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQzthQUNuQztZQUNELHFCQUFxQixDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQztZQUN0RSxLQUFLLEdBQUcsSUFBSSxDQUFDO1lBQ2IsTUFBTTtTQUNQO1FBQ0QsQ0FBQyxJQUFJLGFBQWEsQ0FBQztLQUNwQjtJQUVELElBQUksQ0FBQyxLQUFLLEVBQUU7UUFDVix1QkFBdUIsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztRQUM3RSxxQkFBcUIsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsV0FBVyxDQUFDLENBQUM7S0FDdkU7QUFDSCxDQUFDOzs7Ozs7Ozs7O0FBTUQsU0FBUyx1QkFBdUIsQ0FDNUIsT0FBd0IsRUFBRSxLQUFhLEVBQUUsSUFBWSxFQUFFLG9CQUE4Qjs7VUFDakYsTUFBTSxHQUFHLG9CQUFvQixDQUFDLENBQUMsOEJBQXFELENBQUM7dUJBQ2Y7SUFDNUUsT0FBTyxDQUFDLE1BQU0sQ0FDVixLQUFLLEVBQUUsQ0FBQyxFQUNSLE1BQU0sRUFBcUIsa0JBQWtCO0lBQzdDLHdCQUF3QixFQUFHLHVCQUF1QjtJQUNsRCx3QkFBd0IsRUFBRyw0QkFBNEI7SUFDdkQsSUFBSSxDQUNILENBQUM7SUFFTixLQUFLLElBQUksQ0FBQyxDQUFDLENBQUUscUJBQXFCOzs7Ozs7O1VBTTVCLHFCQUFxQixHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUM7SUFDdEQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLHFCQUFxQixFQUFFLENBQUMsRUFBRSxFQUFFO1FBQzlDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1FBQ2hELEtBQUssRUFBRSxDQUFDO0tBQ1Q7SUFFRCw2Q0FBNkM7SUFDN0MsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLHFCQUFxQixDQUFDLENBQUM7QUFDbEQsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JELFNBQVMscUJBQXFCLENBQzFCLE9BQXdCLEVBQUUsS0FBYSxFQUFFLFlBQThDLEVBQ3ZGLFFBQWdCLEVBQUUsV0FBbUI7SUFDdkMsSUFBSSxPQUFPLFlBQVksS0FBSyxRQUFRLEVBQUU7O2NBQzlCLGdCQUFnQixHQUFHLG1CQUFtQixDQUFDLFdBQVcsQ0FBQzs7Y0FDbkQsU0FBUyxHQUFHLEtBQUssOEJBQTJDLEdBQUcsV0FBVztRQUNoRixPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsWUFBWSxDQUFDOztjQUM1QixjQUFjLEdBQUcsWUFBWSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxRQUFRLENBQUM7UUFDdkYsWUFBWSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixDQUFDLENBQUM7S0FDaEU7U0FBTSxJQUFJLFlBQVksS0FBSyxJQUFJLElBQUksZUFBZSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsS0FBSyxJQUFJLEVBQUU7UUFDNUUsZUFBZSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUM7S0FDL0M7QUFDSCxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7QUFjRCxTQUFTLGtCQUFrQixDQUFDLE9BQXdCOzs7VUFFNUMsWUFBWSxHQUFHLDhCQUEyQyxjQUFjLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQzs7UUFFdkYsS0FBSyw4QkFBMkM7SUFDcEQsT0FBTyxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRTtRQUM3QixLQUFLLElBQUksWUFBWSxDQUFDO1FBQ3RCLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxFQUFFLHFCQUFxQixDQUFDLENBQUM7UUFFbEQsZ0VBQWdFO1FBQ2hFLCtEQUErRDtRQUMvRCxLQUFLLEVBQUUsQ0FBQztLQUNUO0lBQ0QsT0FBTyw4QkFBMkMsRUFBRSxDQUFDO0FBQ3ZELENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXdCRCxNQUFNLFVBQVUsWUFBWSxDQUN4QixRQUFnRCxFQUFFLElBQWtCLEVBQUUsS0FBbUIsRUFDekYsY0FBc0MsRUFBRSxhQUFxQyxFQUM3RSxPQUFpQixFQUFFLGNBQXNCLEVBQUUsY0FBc0MsRUFDakYsZUFBd0I7SUFDMUIsU0FBUyxJQUFJLFNBQVMsQ0FBQyxZQUFZLEVBQUUsQ0FBQzs7VUFFaEMsS0FBSyxHQUFHLGVBQWUsQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDOztVQUNoRCxnQkFBZ0IsR0FBRyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDO0lBRS9ELElBQUksYUFBYSxFQUFFO1FBQ2pCLGVBQWUsSUFBSSx5QkFBeUIsQ0FBQyxhQUFhLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRTFFLElBQUksS0FBSyxDQUFDLGFBQWEsS0FBSyxDQUFDLEVBQUU7WUFDN0Isc0JBQXNCLENBQ2xCLGFBQWEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLGFBQWEsRUFBRSxRQUFRLEVBQzVFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUM5QztLQUNGO0lBRUQsSUFBSSxjQUFjLEVBQUU7UUFDbEIsZUFBZSxJQUFJLHlCQUF5QixDQUFDLGNBQWMsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFFMUUsSUFBSSxLQUFLLENBQUMsY0FBYyxLQUFLLENBQUMsRUFBRTtZQUM5QixzQkFBc0IsQ0FDbEIsY0FBYyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsY0FBYyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQ3BGLGdCQUFnQixFQUFFLElBQUksQ0FBQyxDQUFDO1NBQzdCO0tBQ0Y7SUFFRCxpQkFBaUIsRUFBRSxDQUFDO0FBQ3RCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXlERCxTQUFTLHlCQUF5QixDQUM5QixPQUF3QixFQUFFLEtBQW1CLEVBQUUsWUFBcUI7SUFDdEUsc0VBQXNFO0lBQ3RFLGtDQUFrQztJQUNsQyw2QkFBNkIsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLG1CQUFBLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDN0YsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFnQkQsU0FBUyw2QkFBNkIsQ0FDbEMsT0FBd0IsRUFBRSxLQUFtQixFQUFFLGNBQStCLEVBQzlFLFlBQXFCOzs7O1VBR2pCLG9CQUFvQixHQUFHLENBQUMsQ0FBQzs7UUFFM0IsaUJBQWlCLEdBQUcsS0FBSztJQUM3QixLQUFLLElBQUksQ0FBQyw4QkFBMkMsRUFBRSxDQUFDLEdBQUcsY0FBYyxDQUFDLE1BQU0sRUFDM0UsQ0FBQyxxQkFBa0MsRUFBRTs7Y0FDbEMsS0FBSyxHQUFHLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDO1FBQzVDLElBQUksS0FBSyxFQUFFOztrQkFDSCxJQUFJLEdBQUcsVUFBVSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7WUFDMUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQzNGLGlCQUFpQixHQUFHLElBQUksQ0FBQztTQUMxQjtLQUNGO0lBRUQsSUFBSSxpQkFBaUIsRUFBRTtRQUNyQixXQUFXLENBQUMsS0FBSyw4QkFBK0IsQ0FBQztLQUNsRDtBQUNILENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTZCRCxNQUFNLFVBQVUsc0JBQXNCLENBQ2xDLE9BQXdCLEVBQUUsS0FBbUIsRUFBRSxRQUFnRCxFQUMvRixPQUFpQixFQUFFLFdBQXlCLEVBQUUsWUFBOEIsRUFDNUUsY0FBOEIsRUFBRSxTQUFpQyxFQUFFLGdCQUF5QixFQUM1RixZQUFxQjs7VUFDakIsT0FBTyxHQUFHLHFCQUFxQixDQUFDLFlBQVksQ0FBQzs7UUFFL0MsaUJBQWlCLEdBQTJCLElBQUk7O1FBQ2hELGNBQWMsR0FBRyxLQUFLOztVQUNwQixlQUFlLEdBQ2pCLFlBQVksQ0FBQyxDQUFDLCtCQUFnQyxDQUFDLGdDQUErQjtJQUNsRixJQUFJLFNBQVMsQ0FBQyxLQUFLLEVBQUUsZUFBZSxDQUFDLEVBQUU7UUFDckMsaUJBQWlCLEdBQUcsb0JBQW9CLEVBQUUsQ0FBQzs7Y0FDckMsYUFBYSxHQUNmLFlBQVksQ0FBQyxPQUFPLCtCQUE0QyxnQkFBZ0IsQ0FBQztRQUNyRixjQUFjLEdBQUcsQ0FBQyxPQUFPLEdBQUcsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQ2xEOztVQUVLLFdBQVcsR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDOztRQUN2QyxvQkFBb0IsR0FBRyxDQUFDOztRQUN4QixRQUFRLEdBQ1IsY0FBYyxDQUFDLENBQUMsd0JBQW9DLENBQUMsdUJBQW1DO0lBQzVGLElBQUksZ0JBQWdCLEVBQUU7UUFDcEIsUUFBUSw0QkFBd0MsQ0FBQztRQUNqRCxvQkFBb0IsR0FBRyxXQUFXLEdBQUcsQ0FBQyxDQUFDO0tBQ3hDOztRQUVHLENBQUMsR0FBRywwQkFBMEIsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQztJQUNoRSxPQUFPLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFOztjQUNuQixTQUFTLEdBQUcsWUFBWSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsZ0JBQWdCLENBQUM7UUFDNUQsSUFBSSxPQUFPLEdBQUcsU0FBUyxFQUFFOztnQkFDbkIsWUFBWSxHQUFHLEtBQUs7O2tCQUNsQixJQUFJLEdBQUcsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7O2tCQUMxQixZQUFZLEdBQUcsZUFBZSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFFaEQsMkNBQTJDO1lBQzNDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxvQkFBb0IsRUFBRSxDQUFDLEVBQUUsRUFBRTs7c0JBQ3ZDLFlBQVksR0FBRyxtQkFBQSxlQUFlLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBVTtnQkFDN0QsSUFBSSxDQUFDLFlBQVksSUFBSSxZQUFZLEtBQUssQ0FBQyxFQUFFOzswQkFDakMsS0FBSyxHQUFHLFFBQVEsQ0FBQyxXQUFXLEVBQUUsWUFBWSxDQUFDO29CQUNqRCxJQUFJLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxFQUFFOzs4QkFDMUIsY0FBYyxHQUFHLGdCQUFnQixJQUFJLENBQUMsS0FBSyxDQUFDO3dCQUNsRCxJQUFJLENBQUMsY0FBYyxFQUFFOztrQ0FDYixVQUFVLEdBQUcsU0FBUyxJQUFJLHNCQUFzQixDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dDQUNoRSxTQUFTLENBQUMsSUFBSSxFQUFFLEtBQUssdUJBQWlDLENBQUMsQ0FBQztnQ0FDeEQsZUFBZSxDQUFDLEtBQUssQ0FBQzs0QkFDMUIsY0FBYyxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxZQUFZLENBQUMsQ0FBQzt5QkFDbkU7d0JBQ0QsWUFBWSxHQUFHLElBQUksQ0FBQztxQkFDckI7aUJBQ0Y7Z0JBRUQsMkRBQTJEO2dCQUMzRCxJQUFJLGlCQUFpQixFQUFFOzs7d0JBRWpCLElBQUksR0FBRyxRQUFRLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyx3QkFBb0MsQ0FBQzsrQ0FDRCxDQUFDO29CQUUxRSx1RUFBdUU7b0JBQ3ZFLHdFQUF3RTtvQkFDeEUseUVBQXlFO29CQUN6RSx3RUFBd0U7b0JBQ3hFLHVFQUF1RTtvQkFDdkUsMEVBQTBFO29CQUMxRSxtQkFBbUI7b0JBQ25CLElBQUksZ0JBQWdCLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRTt3QkFDL0IsSUFBSSw0QkFBdUMsQ0FBQztxQkFDN0M7OzBCQUVLLHFCQUFxQixHQUFHLGlCQUFpQixDQUMzQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLElBQUksRUFDakYsWUFBWSxDQUFDO29CQUNqQixZQUFZLEdBQUcsWUFBWSxJQUFJLHFCQUFxQixDQUFDO2lCQUN0RDthQUNGO1lBRUQsMkZBQTJGO1lBQzNGLGtGQUFrRjtZQUNsRixrRkFBa0Y7WUFDbEYsdURBQXVEO1lBQ3ZELElBQUksQ0FBQyxZQUFZLEVBQUU7Z0JBQ2pCLGNBQWMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxZQUFZLENBQUMsQ0FBQzthQUN2RDtTQUNGO1FBRUQsQ0FBQyxJQUFJLDhCQUEyQyxXQUFXLENBQUM7S0FDN0Q7SUFFRCwrREFBK0Q7SUFDL0QsOERBQThEO0lBQzlELGlDQUFpQztJQUNqQyxJQUFJLGlCQUFpQixFQUFFO1FBQ3JCLElBQUksZ0JBQWdCLEVBQUU7WUFDcEIsUUFBUSw0QkFBdUMsQ0FBQztTQUNqRDtRQUNELGlCQUFpQixDQUNiLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxDQUFDLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztLQUN0RjtBQUNILENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF3QkQsTUFBTSxVQUFVLHVCQUF1QixDQUNuQyxRQUFhLEVBQUUsT0FBd0IsRUFBRSxLQUFtQixFQUFFLE9BQWlCLEVBQy9FLElBQWtCLEVBQUUsWUFBb0IsRUFBRSxLQUEyQyxFQUNyRixZQUFxQixFQUFFLFNBQWlDLEVBQUUsV0FBb0IsRUFDOUUsMkJBQW9DOztVQUNoQyxRQUFRLEdBQUcsUUFBUSxDQUFDLElBQUksRUFBRSxZQUFZLENBQUM7SUFDN0MsSUFBSSxXQUFXLElBQUksZUFBZSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsRUFBRTs7Y0FDN0MsVUFBVSxHQUFHLFNBQVMsQ0FBQyxLQUFLLDhCQUErQjs7Y0FDM0QsWUFBWSxHQUNkLFVBQVUsSUFBSSxDQUFDLDJCQUEyQixDQUFDLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtRQUN2RixRQUFRLENBQUMsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQzs7Ozs7Y0FLOUIsZ0JBQWdCLEdBQUcsWUFBWSxHQUFHLENBQUM7O1lBQ3JDLFdBQVcsR0FBRyxRQUFRLENBQUMsSUFBSSxFQUFFLGdCQUFnQixDQUFDO1FBQ2xELElBQUksV0FBVyxLQUFLLFNBQVMsRUFBRTtZQUM3QixXQUFXLEdBQUcsWUFBWSxDQUFDO1NBQzVCO1FBQ0QsV0FBVyxHQUFHLE9BQU8sV0FBVyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUM7Ozs7OztjQU0zRCxnQkFBZ0IsR0FDbEIsWUFBWSxDQUFDLENBQUMsaUNBQWlDLENBQUMsaUNBQWdDOztZQUNoRixtQkFBbUIsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsZ0JBQWdCLENBQUM7UUFDN0QsSUFBSSxtQkFBbUI7WUFDbkIseUJBQXlCLENBQUMsbUJBQUEsT0FBTyxFQUFlLEVBQUUsV0FBVyxFQUFFLFlBQVksQ0FBQyxFQUFFO1lBQ2hGLG1CQUFtQixHQUFHLEtBQUssQ0FBQztZQUM1QixJQUFJLFFBQVEsS0FBSyw0QkFBNEIsRUFBRTtnQkFDN0MsOERBQThEO2dCQUM5RCwyREFBMkQ7Z0JBQzNELDREQUE0RDtnQkFDNUQsNkRBQTZEO2dCQUM3RCx5Q0FBeUM7Z0JBQ3pDLG1CQUFtQixDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUUvRCwrREFBK0Q7Z0JBQy9ELDJCQUEyQjtnQkFDM0IsUUFBUSxDQUFDLElBQUksRUFBRSxnQkFBZ0IsRUFBRSw0QkFBNEIsQ0FBQyxDQUFDO2FBQ2hFO1NBQ0Y7UUFFRCxJQUFJLG1CQUFtQixFQUFFOztrQkFDakIsWUFBWSxHQUNkLFVBQVUsSUFBSSxDQUFDLDJCQUEyQixDQUFDLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTs7a0JBQ2pGLFlBQVksR0FDZCx5QkFBeUIsQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsWUFBWSxDQUFDO1lBQ25GLFFBQVEsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxJQUFJLElBQUksQ0FBQyxDQUFDO1NBQ3hEO2FBQU07O2tCQUNDLE9BQU8sR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUTs7a0JBQzVDLEdBQUcsR0FBRyx1QkFBdUIsQ0FBQyxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsWUFBWSxDQUFDOztrQkFDN0QsYUFBYSxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUk7WUFFckUsS0FBSyxJQUFJLENBQUMsOEJBQTJDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQ2hFLENBQUMscUJBQWtDLEVBQUU7O3NCQUNsQyxJQUFJLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7O3NCQUN6QixLQUFLLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7OztvQkFHN0IsT0FBTyxHQUNQLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLFNBQVMsQ0FBQztnQkFFdkYsaURBQWlEO2dCQUNqRCxJQUFJLENBQUMsT0FBTyxJQUFJLGFBQWEsRUFBRTtvQkFDN0IsT0FBTyxHQUFHLG9CQUFvQixDQUMxQixRQUFRLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxTQUFTLENBQUMsQ0FBQztpQkFDL0U7Z0JBRUQsaURBQWlEO2dCQUNqRCxJQUFJLENBQUMsT0FBTyxFQUFFO29CQUNaLE9BQU8sQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUM7aUJBQ3REO2FBQ0Y7O2tCQUVLLEtBQUssR0FBRyxlQUFlLENBQUMsT0FBTyxFQUFFLHdCQUF3QixDQUFDO1lBQ2hFLElBQUksWUFBWSxFQUFFO2dCQUNoQixLQUFLLENBQUMsa0JBQWtCLEdBQUcsR0FBRyxDQUFDO2FBQ2hDO2lCQUFNO2dCQUNMLEtBQUssQ0FBQyxrQkFBa0IsR0FBRyxHQUFHLENBQUM7YUFDaEM7U0FDRjtLQUNGO0FBQ0gsQ0FBQzs7Ozs7Ozs7O0FBRUQsTUFBTSxVQUFVLHlCQUF5QixDQUNyQyxRQUFhLEVBQUUsT0FBaUIsRUFBRSxLQUEyQyxFQUM3RSxZQUFxQixFQUFFLFlBQTJCOztRQUNoRCxZQUFvQjtJQUN4QixJQUFJLFlBQVksRUFBRTtRQUNoQixZQUFZLEdBQUcsT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzVFLElBQUksWUFBWSxLQUFLLElBQUksRUFBRTtZQUN6QixZQUFZLEdBQUcsWUFBWSxDQUFDLFlBQVksRUFBRSxZQUFZLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDOUQ7UUFDRCxZQUFZLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQztLQUMvQztTQUFNO1FBQ0wsWUFBWSxHQUFHLG1CQUFtQixDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNoRCxJQUFJLFlBQVksS0FBSyxJQUFJLEVBQUU7WUFDekIsWUFBWSxHQUFHLFlBQVksR0FBRyxHQUFHLEdBQUcsWUFBWSxDQUFDO1NBQ2xEO1FBQ0QsWUFBWSxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7S0FDL0M7SUFDRCxPQUFPLFlBQVksQ0FBQztBQUN0QixDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWdDRCxNQUFNLFVBQVUseUJBQXlCLENBQ3JDLFFBQWEsRUFBRSxPQUF3QixFQUFFLEtBQW1CLEVBQUUsT0FBaUIsRUFDL0UsSUFBa0IsRUFBRSxZQUFvQixFQUFFLElBQVksRUFBRSxLQUFVLEVBQUUsWUFBcUIsRUFDekYsU0FBa0M7O1FBQ2hDLE9BQU8sR0FBRyxLQUFLO0lBQ25CLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRTtRQUM5QyxRQUFRLENBQUMsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQzs7Y0FDOUIsT0FBTyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxRQUFRO1FBRWxELGtEQUFrRDtRQUNsRCxPQUFPLEdBQUcsaUJBQWlCLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxDQUFDLENBQUM7OztjQUd4RixlQUFlLEdBQ2pCLFlBQVksQ0FBQyxDQUFDLCtCQUFnQyxDQUFDLGdDQUErQjtRQUNsRixJQUFJLENBQUMsT0FBTyxJQUFJLFNBQVMsQ0FBQyxLQUFLLEVBQUUsZUFBZSxDQUFDLEVBQUU7O2tCQUMzQyxLQUFLLEdBQUcsZUFBZSxDQUFDLE9BQU8sRUFBRSx3QkFBd0IsQ0FBQzs7a0JBQzFELEdBQUcsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGtCQUFrQjtZQUM5RSxPQUFPLEdBQUcsR0FBRyxDQUFDLENBQUM7Z0JBQ1gsb0JBQW9CLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztnQkFDdEYsS0FBSyxDQUFDO1NBQ1g7UUFFRCxpREFBaUQ7UUFDakQsSUFBSSxDQUFDLE9BQU8sSUFBSSxTQUFTLENBQUMsS0FBSyw4QkFBK0IsRUFBRTs7a0JBQ3hELEdBQUcsR0FBRyxrQkFBa0IsQ0FBQyxPQUFPLENBQUM7WUFDdkMsT0FBTztnQkFDSCxHQUFHLENBQUMsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztTQUM3RjtRQUVELGlEQUFpRDtRQUNqRCxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ1osT0FBTyxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxZQUFZLENBQUMsQ0FBQztTQUN0RDtLQUNGO0lBQ0QsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQzs7Ozs7Ozs7Ozs7QUFFRCxTQUFTLGlCQUFpQixDQUN0QixRQUFhLEVBQUUsT0FBaUIsRUFBRSxJQUFZLEVBQUUsS0FBVSxFQUFFLE9BQXVCLEVBQ25GLFlBQW9CLEVBQUUsU0FBa0M7O1FBQ3RELFlBQVksR0FBZ0IsZUFBZSxDQUFDLEtBQUssQ0FBQztJQUN0RCxJQUFJLHFCQUFxQixDQUFDLFlBQVksQ0FBQyxFQUFFO1FBQ3ZDLFlBQVk7WUFDUixTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsS0FBSyw4QkFBd0MsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDO1FBQzdGLE9BQU8sQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDN0QsT0FBTyxJQUFJLENBQUM7S0FDYjtJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQzs7Ozs7Ozs7Ozs7QUFFRCxTQUFTLG9CQUFvQixDQUN6QixRQUFhLEVBQUUsT0FBaUIsRUFBRSxPQUF1QixFQUFFLEdBQW9CLEVBQUUsSUFBWSxFQUM3RixZQUFvQixFQUFFLFNBQWtDO0lBQzFELEtBQUssSUFBSSxDQUFDLDhCQUEyQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUNoRSxDQUFDLHFCQUFrQyxFQUFFOztjQUNsQyxDQUFDLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFOztnQkFDVixZQUFZLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDdEMsWUFBWSxHQUFHLFNBQVMsQ0FBQyxDQUFDO2dCQUN0QixTQUFTLENBQUMsSUFBSSxFQUFFLFlBQVksOEJBQXdDLENBQUMsQ0FBQztnQkFDdEUsWUFBWSxDQUFDO1lBQ2pCLE9BQU8sQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDN0QsT0FBTyxJQUFJLENBQUM7U0FDYjtRQUNELElBQUksQ0FBQyxHQUFHLElBQUksRUFBRTtZQUNaLE1BQU07U0FDUDtLQUNGO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDOzs7OztBQUVELFNBQVMscUJBQXFCLENBQUMsS0FBdUI7SUFDcEQsNkVBQTZFO0lBQzdFLElBQUksS0FBSyxLQUFLLElBQUk7UUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBRTlCLDZCQUE2QjtJQUM3QixJQUFJLEtBQUssS0FBSyxLQUFLO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFFOUIsa0NBQWtDO0lBQ2xDLE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQzs7SUFFRyx3QkFBd0IsR0FBMkIsSUFBSTs7OztBQUMzRCxNQUFNLFVBQVUsb0JBQW9CO0lBQ2xDLE9BQU8sd0JBQXdCLENBQUM7QUFDbEMsQ0FBQzs7Ozs7QUFFRCxNQUFNLFVBQVUsb0JBQW9CLENBQUMsRUFBcUI7SUFDeEQsd0JBQXdCLEdBQUcsRUFBRSxDQUFDO0FBQ2hDLENBQUM7Ozs7O0FBS0QsTUFBTSxPQUFPLFFBQVE7Ozs7Ozs7QUFDakIsQ0FBQyxRQUEwQixFQUFFLE1BQWdCLEVBQUUsSUFBWSxFQUFFLEtBQW9CLEVBQUUsRUFBRTtJQUNuRixJQUFJLFFBQVEsS0FBSyxJQUFJLEVBQUU7UUFDckIsdUZBQXVGO1FBQ3ZGLElBQUkscUJBQXFCLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDaEMsc0RBQXNEO1lBQ3RELHNEQUFzRDtZQUN0RCxpQ0FBaUM7WUFDakMsS0FBSyxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN6QixTQUFTLElBQUksU0FBUyxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDMUMsSUFBSSxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsRUFBRTtnQkFDbEMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUN0RTtpQkFBTTs7Ozs7O3NCQUtDLFdBQVcsR0FBRyxNQUFNLENBQUMsS0FBSztnQkFDaEMsSUFBSSxXQUFXLElBQUksSUFBSSxFQUFFO29CQUN2QixXQUFXLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztpQkFDdEM7YUFDRjtTQUNGO2FBQU07WUFDTCxTQUFTLElBQUksU0FBUyxDQUFDLG1CQUFtQixFQUFFLENBQUM7WUFFN0MsSUFBSSxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsRUFBRTtnQkFDbEMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQ2xFO2lCQUFNOztzQkFDQyxXQUFXLEdBQUcsTUFBTSxDQUFDLEtBQUs7Z0JBQ2hDLElBQUksV0FBVyxJQUFJLElBQUksRUFBRTtvQkFDdkIsV0FBVyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztpQkFDbEM7YUFDRjtTQUNGO0tBQ0Y7QUFDSCxDQUFDLENBQUE7Ozs7O0FBS0wsTUFBTSxPQUFPLFFBQVE7Ozs7Ozs7QUFDakIsQ0FBQyxRQUEwQixFQUFFLE1BQWdCLEVBQUUsU0FBaUIsRUFBRSxLQUFVLEVBQUUsRUFBRTtJQUM5RSxJQUFJLFFBQVEsS0FBSyxJQUFJLElBQUksU0FBUyxLQUFLLEVBQUUsRUFBRTtRQUN6QyxJQUFJLEtBQUssRUFBRTtZQUNULFNBQVMsSUFBSSxTQUFTLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMxQyxJQUFJLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxFQUFFO2dCQUNsQyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQzthQUN0QztpQkFBTTs7Ozs7O3NCQUtDLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUztnQkFDbEMsSUFBSSxTQUFTLElBQUksSUFBSSxFQUFFO29CQUNyQixTQUFTLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2lCQUMxQjthQUNGO1NBQ0Y7YUFBTTtZQUNMLFNBQVMsSUFBSSxTQUFTLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUM3QyxJQUFJLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxFQUFFO2dCQUNsQyxRQUFRLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQzthQUN6QztpQkFBTTs7c0JBQ0MsU0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTO2dCQUNsQyxJQUFJLFNBQVMsSUFBSSxJQUFJLEVBQUU7b0JBQ3JCLFNBQVMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7aUJBQzdCO2FBQ0Y7U0FDRjtLQUNGO0FBQ0gsQ0FBQyxDQUFBOztBQUVMLE1BQU0sT0FBTyxZQUFZOzs7Ozs7QUFBRyxDQUFDLFFBQTBCLEVBQUUsTUFBZ0IsRUFBRSxTQUFpQixFQUFFLEVBQUU7SUFDOUYsSUFBSSxRQUFRLEtBQUssSUFBSSxFQUFFO1FBQ3JCLElBQUksb0JBQW9CLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDbEMsUUFBUSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1NBQ25EO2FBQU07WUFDTCxNQUFNLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztTQUM5QjtLQUNGO0FBQ0gsQ0FBQyxDQUFBOztBQUVELE1BQU0sT0FBTyxZQUFZOzs7Ozs7QUFBRyxDQUFDLFFBQTBCLEVBQUUsTUFBZ0IsRUFBRSxLQUFhLEVBQUUsRUFBRTtJQUMxRixJQUFJLFFBQVEsS0FBSyxJQUFJLEVBQUU7UUFDckIsSUFBSSxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsRUFBRTtZQUNsQyxRQUFRLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDL0M7YUFBTTtZQUNMLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ3JDO0tBQ0Y7QUFDSCxDQUFDLENBQUE7Ozs7Ozs7Ozs7Ozs7OztBQVdELE1BQU0sVUFBVSxnQkFBZ0IsQ0FDNUIsUUFBbUIsRUFBRSxPQUFpQixFQUFFLGFBQXVELEVBQy9GLFlBQXFCOztVQUNqQixhQUFhLEdBQUcsa0JBQWtCLENBQUMsYUFBYSxDQUFDO0lBQ3ZELElBQUksYUFBYSxFQUFFO1FBQ2pCLEtBQUssSUFBSSxDQUFDLDhCQUEyQyxFQUFFLENBQUMsR0FBRyxhQUFhLENBQUMsTUFBTSxFQUMxRSxDQUFDLHFCQUFrQyxFQUFFOztrQkFDbEMsSUFBSSxHQUFHLFVBQVUsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDOztrQkFDbkMsS0FBSyxHQUFHLFdBQVcsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO1lBQzNDLElBQUksWUFBWSxFQUFFO2dCQUNoQixRQUFRLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO2FBQ2hEO2lCQUFNO2dCQUNMLFFBQVEsQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7YUFDaEQ7U0FDRjtLQUNGO0FBQ0gsQ0FBQzs7Ozs7QUFFRCxTQUFTLGlCQUFpQixDQUFDLEdBQWdDOztRQUNyRCxHQUFHLEdBQUcsRUFBRTtJQUNaLElBQUksR0FBRyxFQUFFO1FBQ1AsS0FBSyxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQUU7O2tCQUNiLEtBQUssR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDO1lBQ3RCLElBQUksS0FBSyxFQUFFO2dCQUNULEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDO2FBQ3RDO1NBQ0Y7S0FDRjtJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7QUFZRCxTQUFTLHlCQUF5QixDQUFDLE9BQW9CLEVBQUUsV0FBZ0IsRUFBRSxZQUFxQjtJQUM5RiwwREFBMEQ7SUFDMUQsMERBQTBEO0lBQzFELDhCQUE4QjtJQUM5QixJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssV0FBVyxJQUFJLFdBQVcsS0FBSyw0QkFBNEI7UUFBRSxPQUFPLElBQUksQ0FBQzs7OztVQUl2RixZQUFZLEdBQ2QsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRTtJQUN2RixPQUFPLFlBQVksS0FBSyxDQUFDLFdBQVcsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUM5QyxDQUFDOzs7Ozs7Ozs7QUFLRCxTQUFTLG1CQUFtQixDQUN4QixRQUFhLEVBQUUsT0FBaUIsRUFBRSxNQUF1RCxFQUN6RixZQUFxQjs7UUFDbkIsR0FBb0I7SUFDeEIsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsRUFBRTtRQUM3QixHQUFHLEdBQUcsbUJBQUEsTUFBTSxFQUFtQixDQUFDO0tBQ2pDO1NBQU07UUFDTCxHQUFHLEdBQUcsdUJBQXVCLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDO0tBQzVEOztVQUVLLE9BQU8sR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUTtJQUNsRCxLQUFLLElBQUksQ0FBQyw4QkFBMkMsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFDaEUsQ0FBQyxxQkFBa0MsRUFBRTs7Y0FDbEMsS0FBSyxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQ2pDLElBQUksS0FBSyxFQUFFOztrQkFDSCxJQUFJLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDL0IsT0FBTyxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3hDO0tBQ0Y7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4qIEBsaWNlbnNlXG4qIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuKlxuKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4qL1xuaW1wb3J0IHtTYWZlVmFsdWUsIHVud3JhcFNhZmVWYWx1ZX0gZnJvbSAnLi4vLi4vc2FuaXRpemF0aW9uL2J5cGFzcyc7XG5pbXBvcnQge1N0eWxlU2FuaXRpemVGbiwgU3R5bGVTYW5pdGl6ZU1vZGV9IGZyb20gJy4uLy4uL3Nhbml0aXphdGlvbi9zdHlsZV9zYW5pdGl6ZXInO1xuaW1wb3J0IHtnbG9iYWx9IGZyb20gJy4uLy4uL3V0aWwvZ2xvYmFsJztcbmltcG9ydCB7VE5vZGVGbGFnc30gZnJvbSAnLi4vaW50ZXJmYWNlcy9ub2RlJztcbmltcG9ydCB7UHJvY2VkdXJhbFJlbmRlcmVyMywgUkVsZW1lbnQsIFJlbmRlcmVyMywgUmVuZGVyZXJTdHlsZUZsYWdzMywgaXNQcm9jZWR1cmFsUmVuZGVyZXJ9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVuZGVyZXInO1xuaW1wb3J0IHtBcHBseVN0eWxpbmdGbiwgTFN0eWxpbmdEYXRhLCBTdHlsaW5nTWFwQXJyYXksIFN0eWxpbmdNYXBBcnJheUluZGV4LCBTdHlsaW5nTWFwc1N5bmNNb2RlLCBTeW5jU3R5bGluZ01hcHNGbiwgVFN0eWxpbmdDb250ZXh0LCBUU3R5bGluZ0NvbnRleHRJbmRleCwgVFN0eWxpbmdDb250ZXh0UHJvcENvbmZpZ0ZsYWdzLCBUU3R5bGluZ05vZGV9IGZyb20gJy4uL2ludGVyZmFjZXMvc3R5bGluZyc7XG5pbXBvcnQge05PX0NIQU5HRX0gZnJvbSAnLi4vdG9rZW5zJztcbmltcG9ydCB7REVGQVVMVF9CSU5ESU5HX0lOREVYLCBERUZBVUxUX0JJTkRJTkdfVkFMVUUsIERFRkFVTFRfR1VBUkRfTUFTS19WQUxVRSwgTUFQX0JBU0VEX0VOVFJZX1BST1BfTkFNRSwgVEVNUExBVEVfRElSRUNUSVZFX0lOREVYLCBjb25jYXRTdHJpbmcsIGZvcmNlU3R5bGVzQXNTdHJpbmcsIGdldEJpbmRpbmdWYWx1ZSwgZ2V0RGVmYXVsdFZhbHVlLCBnZXRHdWFyZE1hc2ssIGdldEluaXRpYWxTdHlsaW5nVmFsdWUsIGdldE1hcFByb3AsIGdldE1hcFZhbHVlLCBnZXRQcm9wLCBnZXRQcm9wVmFsdWVzU3RhcnRQb3NpdGlvbiwgZ2V0U3R5bGluZ01hcEFycmF5LCBnZXRUb3RhbFNvdXJjZXMsIGdldFZhbHVlLCBnZXRWYWx1ZXNDb3VudCwgaGFzQ29uZmlnLCBoYXNWYWx1ZUNoYW5nZWQsIGlzSG9zdFN0eWxpbmdBY3RpdmUsIGlzU2FuaXRpemF0aW9uUmVxdWlyZWQsIGlzU3R5bGluZ01hcEFycmF5LCBpc1N0eWxpbmdWYWx1ZURlZmluZWQsIG5vcm1hbGl6ZUludG9TdHlsaW5nTWFwLCBwYXRjaENvbmZpZywgc2V0RGVmYXVsdFZhbHVlLCBzZXRHdWFyZE1hc2ssIHNldE1hcEFzRGlydHksIHNldFZhbHVlfSBmcm9tICcuLi91dGlsL3N0eWxpbmdfdXRpbHMnO1xuXG5pbXBvcnQge2dldFN0eWxpbmdTdGF0ZSwgcmVzZXRTdHlsaW5nU3RhdGV9IGZyb20gJy4vc3RhdGUnO1xuXG5jb25zdCBWQUxVRV9JU19FWFRFUk5BTExZX01PRElGSUVEID0ge307XG5cbi8qKlxuICogLS0tLS0tLS1cbiAqXG4gKiBUaGlzIGZpbGUgY29udGFpbnMgdGhlIGNvcmUgbG9naWMgZm9yIHN0eWxpbmcgaW4gQW5ndWxhci5cbiAqXG4gKiBBbGwgc3R5bGluZyBiaW5kaW5ncyAoaS5lLiBgW3N0eWxlXWAsIGBbc3R5bGUucHJvcF1gLCBgW2NsYXNzXWAgYW5kIGBbY2xhc3MubmFtZV1gKVxuICogd2lsbCBoYXZlIHRoZWlyIHZhbHVlcyBiZSBhcHBsaWVkIHRocm91Z2ggdGhlIGxvZ2ljIGluIHRoaXMgZmlsZS5cbiAqXG4gKiBXaGVuIGEgYmluZGluZyBpcyBlbmNvdW50ZXJlZCAoZS5nLiBgPGRpdiBbc3R5bGUud2lkdGhdPVwid1wiPmApIHRoZW5cbiAqIHRoZSBiaW5kaW5nIGRhdGEgd2lsbCBiZSBwb3B1bGF0ZWQgaW50byBhIGBUU3R5bGluZ0NvbnRleHRgIGRhdGEtc3RydWN0dXJlLlxuICogVGhlcmUgaXMgb25seSBvbmUgYFRTdHlsaW5nQ29udGV4dGAgcGVyIGBUU3R5bGluZ05vZGVgIGFuZCBlYWNoIGVsZW1lbnQgaW5zdGFuY2VcbiAqIHdpbGwgdXBkYXRlIGl0cyBzdHlsZS9jbGFzcyBiaW5kaW5nIHZhbHVlcyBpbiBjb25jZXJ0IHdpdGggdGhlIHN0eWxpbmdcbiAqIGNvbnRleHQuXG4gKlxuICogVG8gbGVhcm4gbW9yZSBhYm91dCB0aGUgYWxnb3JpdGhtIHNlZSBgVFN0eWxpbmdDb250ZXh0YC5cbiAqXG4gKiAtLS0tLS0tLVxuICovXG5cbi8qKlxuICogVGhlIGd1YXJkL3VwZGF0ZSBtYXNrIGJpdCBpbmRleCBsb2NhdGlvbiBmb3IgbWFwLWJhc2VkIGJpbmRpbmdzLlxuICpcbiAqIEFsbCBtYXAtYmFzZWQgYmluZGluZ3MgKGkuZS4gYFtzdHlsZV1gIGFuZCBgW2NsYXNzXWAgKVxuICovXG5jb25zdCBTVFlMSU5HX0lOREVYX0ZPUl9NQVBfQklORElORyA9IDA7XG5cbi8qKlxuICogVmlzaXRzIGEgY2xhc3MtYmFzZWQgYmluZGluZyBhbmQgdXBkYXRlcyB0aGUgbmV3IHZhbHVlIChpZiBjaGFuZ2VkKS5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBlYWNoIHRpbWUgYSBjbGFzcy1iYXNlZCBzdHlsaW5nIGluc3RydWN0aW9uXG4gKiBpcyBleGVjdXRlZC4gSXQncyBpbXBvcnRhbnQgdGhhdCBpdCdzIGFsd2F5cyBjYWxsZWQgKGV2ZW4gaWYgdGhlIHZhbHVlXG4gKiBoYXMgbm90IGNoYW5nZWQpIHNvIHRoYXQgdGhlIGlubmVyIGNvdW50ZXIgaW5kZXggdmFsdWUgaXMgaW5jcmVtZW50ZWQuXG4gKiBUaGlzIHdheSwgZWFjaCBpbnN0cnVjdGlvbiBpcyBhbHdheXMgZ3VhcmFudGVlZCB0byBnZXQgdGhlIHNhbWUgY291bnRlclxuICogc3RhdGUgZWFjaCB0aW1lIGl0J3MgY2FsbGVkICh3aGljaCB0aGVuIGFsbG93cyB0aGUgYFRTdHlsaW5nQ29udGV4dGBcbiAqIGFuZCB0aGUgYml0IG1hc2sgdmFsdWVzIHRvIGJlIGluIHN5bmMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlQ2xhc3NWaWFDb250ZXh0KFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgdE5vZGU6IFRTdHlsaW5nTm9kZSwgZGF0YTogTFN0eWxpbmdEYXRhLCBlbGVtZW50OiBSRWxlbWVudCxcbiAgICBkaXJlY3RpdmVJbmRleDogbnVtYmVyLCBwcm9wOiBzdHJpbmcgfCBudWxsLCBiaW5kaW5nSW5kZXg6IG51bWJlcixcbiAgICB2YWx1ZTogYm9vbGVhbiB8IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQgfCBTdHlsaW5nTWFwQXJyYXkgfCBOT19DSEFOR0UsIGZvcmNlVXBkYXRlOiBib29sZWFuLFxuICAgIGZpcnN0VXBkYXRlUGFzczogYm9vbGVhbik6IGJvb2xlYW4ge1xuICBjb25zdCBpc01hcEJhc2VkID0gIXByb3A7XG4gIGNvbnN0IHN0YXRlID0gZ2V0U3R5bGluZ1N0YXRlKGVsZW1lbnQsIGRpcmVjdGl2ZUluZGV4KTtcbiAgY29uc3QgY291bnRJbmRleCA9IGlzTWFwQmFzZWQgPyBTVFlMSU5HX0lOREVYX0ZPUl9NQVBfQklORElORyA6IHN0YXRlLmNsYXNzZXNJbmRleCsrO1xuXG4gIC8vIGV2ZW4gaWYgdGhlIGluaXRpYWwgdmFsdWUgaXMgYSBgTk9fQ0hBTkdFYCB2YWx1ZSAoZS5nLiBpbnRlcnBvbGF0aW9uIG9yIFtuZ0NsYXNzXSlcbiAgLy8gdGhlbiB3ZSBzdGlsbCBuZWVkIHRvIHJlZ2lzdGVyIHRoZSBiaW5kaW5nIHdpdGhpbiB0aGUgY29udGV4dCBzbyB0aGF0IHRoZSBjb250ZXh0XG4gIC8vIGlzIGF3YXJlIG9mIHRoZSBiaW5kaW5nIGV2ZW4gaWYgdGhpbmdzIGNoYW5nZSBhZnRlciB0aGUgZmlyc3QgdXBkYXRlIHBhc3MuXG4gIGlmIChmaXJzdFVwZGF0ZVBhc3MgfHwgdmFsdWUgIT09IE5PX0NIQU5HRSkge1xuICAgIGNvbnN0IHVwZGF0ZWQgPSB1cGRhdGVCaW5kaW5nRGF0YShcbiAgICAgICAgY29udGV4dCwgdE5vZGUsIGRhdGEsIGNvdW50SW5kZXgsIHN0YXRlLnNvdXJjZUluZGV4LCBwcm9wLCBiaW5kaW5nSW5kZXgsIHZhbHVlLCBmb3JjZVVwZGF0ZSxcbiAgICAgICAgZmFsc2UsIGZpcnN0VXBkYXRlUGFzcywgdHJ1ZSk7XG4gICAgaWYgKHVwZGF0ZWQgfHwgZm9yY2VVcGRhdGUpIHtcbiAgICAgIC8vIFdlIGZsaXAgdGhlIGJpdCBpbiB0aGUgYml0TWFzayB0byByZWZsZWN0IHRoYXQgdGhlIGJpbmRpbmdcbiAgICAgIC8vIGF0IHRoZSBgaW5kZXhgIHNsb3QgaGFzIGNoYW5nZWQuIFRoaXMgaWRlbnRpZmllcyB0byB0aGUgZmx1c2hpbmdcbiAgICAgIC8vIHBoYXNlIHRoYXQgdGhlIGJpbmRpbmdzIGZvciB0aGlzIHBhcnRpY3VsYXIgQ1NTIGNsYXNzIG5lZWQgdG8gYmVcbiAgICAgIC8vIGFwcGxpZWQgYWdhaW4gYmVjYXVzZSBvbiBvciBtb3JlIG9mIHRoZSBiaW5kaW5ncyBmb3IgdGhlIENTU1xuICAgICAgLy8gY2xhc3MgaGF2ZSBjaGFuZ2VkLlxuICAgICAgc3RhdGUuY2xhc3Nlc0JpdE1hc2sgfD0gMSA8PCBjb3VudEluZGV4O1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBWaXNpdHMgYSBzdHlsZS1iYXNlZCBiaW5kaW5nIGFuZCB1cGRhdGVzIHRoZSBuZXcgdmFsdWUgKGlmIGNoYW5nZWQpLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGVhY2ggdGltZSBhIHN0eWxlLWJhc2VkIHN0eWxpbmcgaW5zdHJ1Y3Rpb25cbiAqIGlzIGV4ZWN1dGVkLiBJdCdzIGltcG9ydGFudCB0aGF0IGl0J3MgYWx3YXlzIGNhbGxlZCAoZXZlbiBpZiB0aGUgdmFsdWVcbiAqIGhhcyBub3QgY2hhbmdlZCkgc28gdGhhdCB0aGUgaW5uZXIgY291bnRlciBpbmRleCB2YWx1ZSBpcyBpbmNyZW1lbnRlZC5cbiAqIFRoaXMgd2F5LCBlYWNoIGluc3RydWN0aW9uIGlzIGFsd2F5cyBndWFyYW50ZWVkIHRvIGdldCB0aGUgc2FtZSBjb3VudGVyXG4gKiBzdGF0ZSBlYWNoIHRpbWUgaXQncyBjYWxsZWQgKHdoaWNoIHRoZW4gYWxsb3dzIHRoZSBgVFN0eWxpbmdDb250ZXh0YFxuICogYW5kIHRoZSBiaXQgbWFzayB2YWx1ZXMgdG8gYmUgaW4gc3luYykuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVTdHlsZVZpYUNvbnRleHQoXG4gICAgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LCB0Tm9kZTogVFN0eWxpbmdOb2RlLCBkYXRhOiBMU3R5bGluZ0RhdGEsIGVsZW1lbnQ6IFJFbGVtZW50LFxuICAgIGRpcmVjdGl2ZUluZGV4OiBudW1iZXIsIHByb3A6IHN0cmluZyB8IG51bGwsIGJpbmRpbmdJbmRleDogbnVtYmVyLFxuICAgIHZhbHVlOiBzdHJpbmcgfCBudW1iZXIgfCBTYWZlVmFsdWUgfCBudWxsIHwgdW5kZWZpbmVkIHwgU3R5bGluZ01hcEFycmF5IHwgTk9fQ0hBTkdFLFxuICAgIHNhbml0aXplcjogU3R5bGVTYW5pdGl6ZUZuIHwgbnVsbCwgZm9yY2VVcGRhdGU6IGJvb2xlYW4sIGZpcnN0VXBkYXRlUGFzczogYm9vbGVhbik6IGJvb2xlYW4ge1xuICBjb25zdCBpc01hcEJhc2VkID0gIXByb3A7XG4gIGNvbnN0IHN0YXRlID0gZ2V0U3R5bGluZ1N0YXRlKGVsZW1lbnQsIGRpcmVjdGl2ZUluZGV4KTtcbiAgY29uc3QgY291bnRJbmRleCA9IGlzTWFwQmFzZWQgPyBTVFlMSU5HX0lOREVYX0ZPUl9NQVBfQklORElORyA6IHN0YXRlLnN0eWxlc0luZGV4Kys7XG5cbiAgLy8gZXZlbiBpZiB0aGUgaW5pdGlhbCB2YWx1ZSBpcyBhIGBOT19DSEFOR0VgIHZhbHVlIChlLmcuIGludGVycG9sYXRpb24gb3IgW25nU3R5bGVdKVxuICAvLyB0aGVuIHdlIHN0aWxsIG5lZWQgdG8gcmVnaXN0ZXIgdGhlIGJpbmRpbmcgd2l0aGluIHRoZSBjb250ZXh0IHNvIHRoYXQgdGhlIGNvbnRleHRcbiAgLy8gaXMgYXdhcmUgb2YgdGhlIGJpbmRpbmcgZXZlbiBpZiB0aGluZ3MgY2hhbmdlIGFmdGVyIHRoZSBmaXJzdCB1cGRhdGUgcGFzcy5cbiAgaWYgKGZpcnN0VXBkYXRlUGFzcyB8fCB2YWx1ZSAhPT0gTk9fQ0hBTkdFKSB7XG4gICAgY29uc3Qgc2FuaXRpemF0aW9uUmVxdWlyZWQgPSBpc01hcEJhc2VkID9cbiAgICAgICAgdHJ1ZSA6XG4gICAgICAgIChzYW5pdGl6ZXIgPyBzYW5pdGl6ZXIocHJvcCAhLCBudWxsLCBTdHlsZVNhbml0aXplTW9kZS5WYWxpZGF0ZVByb3BlcnR5KSA6IGZhbHNlKTtcbiAgICBjb25zdCB1cGRhdGVkID0gdXBkYXRlQmluZGluZ0RhdGEoXG4gICAgICAgIGNvbnRleHQsIHROb2RlLCBkYXRhLCBjb3VudEluZGV4LCBzdGF0ZS5zb3VyY2VJbmRleCwgcHJvcCwgYmluZGluZ0luZGV4LCB2YWx1ZSwgZm9yY2VVcGRhdGUsXG4gICAgICAgIHNhbml0aXphdGlvblJlcXVpcmVkLCBmaXJzdFVwZGF0ZVBhc3MsIGZhbHNlKTtcbiAgICBpZiAodXBkYXRlZCB8fCBmb3JjZVVwZGF0ZSkge1xuICAgICAgLy8gV2UgZmxpcCB0aGUgYml0IGluIHRoZSBiaXRNYXNrIHRvIHJlZmxlY3QgdGhhdCB0aGUgYmluZGluZ1xuICAgICAgLy8gYXQgdGhlIGBpbmRleGAgc2xvdCBoYXMgY2hhbmdlZC4gVGhpcyBpZGVudGlmaWVzIHRvIHRoZSBmbHVzaGluZ1xuICAgICAgLy8gcGhhc2UgdGhhdCB0aGUgYmluZGluZ3MgZm9yIHRoaXMgcGFydGljdWxhciBwcm9wZXJ0eSBuZWVkIHRvIGJlXG4gICAgICAvLyBhcHBsaWVkIGFnYWluIGJlY2F1c2Ugb24gb3IgbW9yZSBvZiB0aGUgYmluZGluZ3MgZm9yIHRoZSBDU1NcbiAgICAgIC8vIHByb3BlcnR5IGhhdmUgY2hhbmdlZC5cbiAgICAgIHN0YXRlLnN0eWxlc0JpdE1hc2sgfD0gMSA8PCBjb3VudEluZGV4O1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBDYWxsZWQgZWFjaCB0aW1lIGEgYmluZGluZyB2YWx1ZSBoYXMgY2hhbmdlZCB3aXRoaW4gdGhlIHByb3ZpZGVkIGBUU3R5bGluZ0NvbnRleHRgLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgZGVzaWduZWQgdG8gYmUgY2FsbGVkIGZyb20gYHVwZGF0ZVN0eWxlQmluZGluZ2AgYW5kIGB1cGRhdGVDbGFzc0JpbmRpbmdgLlxuICogSWYgY2FsbGVkIGR1cmluZyB0aGUgZmlyc3QgdXBkYXRlIHBhc3MsIHRoZSBiaW5kaW5nIHdpbGwgYmUgcmVnaXN0ZXJlZCBpbiB0aGUgY29udGV4dC5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgYWxzbyB1cGRhdGUgYmluZGluZyBzbG90IGluIHRoZSBwcm92aWRlZCBgTFN0eWxpbmdEYXRhYCB3aXRoIHRoZVxuICogbmV3IGJpbmRpbmcgZW50cnkgKGlmIGl0IGhhcyBjaGFuZ2VkKS5cbiAqXG4gKiBAcmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgYmluZGluZyB2YWx1ZSB3YXMgdXBkYXRlZCBpbiB0aGUgYExTdHlsaW5nRGF0YWAuXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZUJpbmRpbmdEYXRhKFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgdE5vZGU6IFRTdHlsaW5nTm9kZSwgZGF0YTogTFN0eWxpbmdEYXRhLCBjb3VudGVySW5kZXg6IG51bWJlcixcbiAgICBzb3VyY2VJbmRleDogbnVtYmVyLCBwcm9wOiBzdHJpbmcgfCBudWxsLCBiaW5kaW5nSW5kZXg6IG51bWJlcixcbiAgICB2YWx1ZTogc3RyaW5nIHwgU2FmZVZhbHVlIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG51bGwgfCB1bmRlZmluZWQgfCBTdHlsaW5nTWFwQXJyYXksXG4gICAgZm9yY2VVcGRhdGU6IGJvb2xlYW4sIHNhbml0aXphdGlvblJlcXVpcmVkOiBib29sZWFuLCBmaXJzdFVwZGF0ZVBhc3M6IGJvb2xlYW4sXG4gICAgaXNDbGFzc0Jhc2VkOiBib29sZWFuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGhvc3RCaW5kaW5nc01vZGUgPSBpc0hvc3RTdHlsaW5nQWN0aXZlKHNvdXJjZUluZGV4KTtcbiAgY29uc3QgaG9zdEJpbmRpbmdzRmxhZyA9XG4gICAgICBpc0NsYXNzQmFzZWQgPyBUTm9kZUZsYWdzLmhhc0hvc3RDbGFzc0JpbmRpbmdzIDogVE5vZGVGbGFncy5oYXNIb3N0U3R5bGVCaW5kaW5ncztcbiAgaWYgKGZpcnN0VXBkYXRlUGFzcykge1xuICAgIC8vIHRoaXMgd2lsbCBvbmx5IGhhcHBlbiBkdXJpbmcgdGhlIGZpcnN0IHVwZGF0ZSBwYXNzIG9mIHRoZVxuICAgIC8vIGNvbnRleHQuIFRoZSByZWFzb24gd2h5IHdlIGNhbid0IHVzZSBgdFZpZXcuZmlyc3RDcmVhdGVQYXNzYFxuICAgIC8vIGhlcmUgaXMgYmVjYXVzZSBpdHMgbm90IGd1YXJhbnRlZWQgdG8gYmUgdHJ1ZSB3aGVuIHRoZSBmaXJzdFxuICAgIC8vIHVwZGF0ZSBwYXNzIGlzIGV4ZWN1dGVkIChyZW1lbWJlciB0aGF0IGFsbCBzdHlsaW5nIGluc3RydWN0aW9uc1xuICAgIC8vIGFyZSBydW4gaW4gdGhlIHVwZGF0ZSBwaGFzZSwgYW5kLCBhcyBhIHJlc3VsdCwgYXJlIG5vIG1vcmVcbiAgICAvLyBzdHlsaW5nIGluc3RydWN0aW9ucyB0aGF0IGFyZSBydW4gaW4gdGhlIGNyZWF0aW9uIHBoYXNlKS5cbiAgICByZWdpc3RlckJpbmRpbmcoXG4gICAgICAgIGNvbnRleHQsIHROb2RlLCBjb3VudGVySW5kZXgsIHNvdXJjZUluZGV4LCBwcm9wLCBiaW5kaW5nSW5kZXgsIHNhbml0aXphdGlvblJlcXVpcmVkLFxuICAgICAgICBpc0NsYXNzQmFzZWQpO1xuICB9XG5cbiAgY29uc3QgY2hhbmdlZCA9IGZvcmNlVXBkYXRlIHx8IGhhc1ZhbHVlQ2hhbmdlZChkYXRhW2JpbmRpbmdJbmRleF0sIHZhbHVlKTtcbiAgaWYgKGNoYW5nZWQpIHtcbiAgICBzZXRWYWx1ZShkYXRhLCBiaW5kaW5nSW5kZXgsIHZhbHVlKTtcbiAgICBjb25zdCBkb1NldFZhbHVlc0FzU3RhbGUgPVxuICAgICAgICBoYXNDb25maWcodE5vZGUsIGhvc3RCaW5kaW5nc0ZsYWcpICYmICFob3N0QmluZGluZ3NNb2RlICYmIChwcm9wID8gIXZhbHVlIDogdHJ1ZSk7XG4gICAgaWYgKGRvU2V0VmFsdWVzQXNTdGFsZSkge1xuICAgICAgcmVuZGVySG9zdEJpbmRpbmdzQXNTdGFsZShjb250ZXh0LCB0Tm9kZSwgZGF0YSwgcHJvcCwgaXNDbGFzc0Jhc2VkKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGNoYW5nZWQ7XG59XG5cbi8qKlxuICogSXRlcmF0ZXMgb3ZlciBhbGwgaG9zdC1iaW5kaW5nIHZhbHVlcyBmb3IgdGhlIGdpdmVuIGBwcm9wYCB2YWx1ZSBpbiB0aGUgY29udGV4dCBhbmQgc2V0cyB0aGVpclxuICogY29ycmVzcG9uZGluZyBiaW5kaW5nIHZhbHVlcyB0byBgbnVsbGAuXG4gKlxuICogV2hlbmV2ZXIgYSB0ZW1wbGF0ZSBiaW5kaW5nIGNoYW5nZXMgaXRzIHZhbHVlIHRvIGBudWxsYCwgYWxsIGhvc3QtYmluZGluZyB2YWx1ZXMgc2hvdWxkIGJlXG4gKiByZS1hcHBsaWVkXG4gKiB0byB0aGUgZWxlbWVudCB3aGVuIHRoZSBob3N0IGJpbmRpbmdzIGFyZSBldmFsdWF0ZWQuIFRoaXMgbWF5IG5vdCBhbHdheXMgaGFwcGVuIGluIHRoZSBldmVudFxuICogdGhhdCBub25lIG9mIHRoZSBiaW5kaW5ncyBjaGFuZ2VkIHdpdGhpbiB0aGUgaG9zdCBiaW5kaW5ncyBjb2RlLiBGb3IgdGhpcyByZWFzb24gdGhpcyBmdW5jdGlvblxuICogaXMgZXhwZWN0ZWQgdG8gYmUgY2FsbGVkIGVhY2ggdGltZSBhIHRlbXBsYXRlIGJpbmRpbmcgYmVjb21lcyBmYWxzeSBvciB3aGVuIGEgbWFwLWJhc2VkIHRlbXBsYXRlXG4gKiBiaW5kaW5nIGNoYW5nZXMuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckhvc3RCaW5kaW5nc0FzU3RhbGUoXG4gICAgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LCB0Tm9kZTogVFN0eWxpbmdOb2RlLCBkYXRhOiBMU3R5bGluZ0RhdGEsIHByb3A6IHN0cmluZyB8IG51bGwsXG4gICAgaXNDbGFzc0Jhc2VkOiBib29sZWFuKTogdm9pZCB7XG4gIGNvbnN0IHZhbHVlc0NvdW50ID0gZ2V0VmFsdWVzQ291bnQoY29udGV4dCk7XG5cbiAgY29uc3QgaG9zdEJpbmRpbmdzRmxhZyA9XG4gICAgICBpc0NsYXNzQmFzZWQgPyBUTm9kZUZsYWdzLmhhc0hvc3RDbGFzc0JpbmRpbmdzIDogVE5vZGVGbGFncy5oYXNIb3N0U3R5bGVCaW5kaW5ncztcbiAgaWYgKHByb3AgIT09IG51bGwgJiYgaGFzQ29uZmlnKHROb2RlLCBob3N0QmluZGluZ3NGbGFnKSkge1xuICAgIGNvbnN0IGl0ZW1zUGVyUm93ID0gVFN0eWxpbmdDb250ZXh0SW5kZXguQmluZGluZ3NTdGFydE9mZnNldCArIHZhbHVlc0NvdW50O1xuXG4gICAgbGV0IGkgPSBUU3R5bGluZ0NvbnRleHRJbmRleC5WYWx1ZXNTdGFydFBvc2l0aW9uO1xuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIHdoaWxlIChpIDwgY29udGV4dC5sZW5ndGgpIHtcbiAgICAgIGlmIChnZXRQcm9wKGNvbnRleHQsIGkpID09PSBwcm9wKSB7XG4gICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBpICs9IGl0ZW1zUGVyUm93O1xuICAgIH1cblxuICAgIGlmIChmb3VuZCkge1xuICAgICAgY29uc3QgYmluZGluZ3NTdGFydCA9IGkgKyBUU3R5bGluZ0NvbnRleHRJbmRleC5CaW5kaW5nc1N0YXJ0T2Zmc2V0O1xuICAgICAgY29uc3QgdmFsdWVzU3RhcnQgPSBiaW5kaW5nc1N0YXJ0ICsgMTsgIC8vIHRoZSBmaXJzdCBjb2x1bW4gaXMgdGVtcGxhdGUgYmluZGluZ3NcbiAgICAgIGNvbnN0IHZhbHVlc0VuZCA9IGJpbmRpbmdzU3RhcnQgKyB2YWx1ZXNDb3VudCAtIDE7XG5cbiAgICAgIGZvciAobGV0IGkgPSB2YWx1ZXNTdGFydDsgaSA8IHZhbHVlc0VuZDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGJpbmRpbmdJbmRleCA9IGNvbnRleHRbaV0gYXMgbnVtYmVyO1xuICAgICAgICBpZiAoYmluZGluZ0luZGV4ICE9PSAwKSB7XG4gICAgICAgICAgc2V0VmFsdWUoZGF0YSwgYmluZGluZ0luZGV4LCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG1hcEJpbmRpbmdzRmxhZyA9XG4gICAgICBpc0NsYXNzQmFzZWQgPyBUTm9kZUZsYWdzLmhhc0NsYXNzTWFwQmluZGluZ3MgOiBUTm9kZUZsYWdzLmhhc1N0eWxlTWFwQmluZGluZ3M7XG4gIGlmIChoYXNDb25maWcodE5vZGUsIG1hcEJpbmRpbmdzRmxhZykpIHtcbiAgICBjb25zdCBiaW5kaW5nc1N0YXJ0ID1cbiAgICAgICAgVFN0eWxpbmdDb250ZXh0SW5kZXguVmFsdWVzU3RhcnRQb3NpdGlvbiArIFRTdHlsaW5nQ29udGV4dEluZGV4LkJpbmRpbmdzU3RhcnRPZmZzZXQ7XG4gICAgY29uc3QgdmFsdWVzU3RhcnQgPSBiaW5kaW5nc1N0YXJ0ICsgMTsgIC8vIHRoZSBmaXJzdCBjb2x1bW4gaXMgdGVtcGxhdGUgYmluZGluZ3NcbiAgICBjb25zdCB2YWx1ZXNFbmQgPSBiaW5kaW5nc1N0YXJ0ICsgdmFsdWVzQ291bnQgLSAxO1xuICAgIGZvciAobGV0IGkgPSB2YWx1ZXNTdGFydDsgaSA8IHZhbHVlc0VuZDsgaSsrKSB7XG4gICAgICBjb25zdCBzdHlsaW5nTWFwID0gZ2V0VmFsdWU8U3R5bGluZ01hcEFycmF5PihkYXRhLCBjb250ZXh0W2ldIGFzIG51bWJlcik7XG4gICAgICBpZiAoc3R5bGluZ01hcCkge1xuICAgICAgICBzZXRNYXBBc0RpcnR5KHN0eWxpbmdNYXApO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFJlZ2lzdGVycyB0aGUgcHJvdmlkZWQgYmluZGluZyAocHJvcCArIGJpbmRpbmdJbmRleCkgaW50byB0aGUgY29udGV4dC5cbiAqXG4gKiBJdCBpcyBuZWVkZWQgYmVjYXVzZSBpdCB3aWxsIGVpdGhlciB1cGRhdGUgb3IgaW5zZXJ0IGEgc3R5bGluZyBwcm9wZXJ0eVxuICogaW50byB0aGUgY29udGV4dCBhdCB0aGUgY29ycmVjdCBzcG90LlxuICpcbiAqIFdoZW4gY2FsbGVkLCBvbmUgb2YgdHdvIHRoaW5ncyB3aWxsIGhhcHBlbjpcbiAqXG4gKiAxKSBJZiB0aGUgcHJvcGVydHkgYWxyZWFkeSBleGlzdHMgaW4gdGhlIGNvbnRleHQgdGhlbiBpdCB3aWxsIGp1c3QgYWRkXG4gKiAgICB0aGUgcHJvdmlkZWQgYGJpbmRpbmdWYWx1ZWAgdG8gdGhlIGVuZCBvZiB0aGUgYmluZGluZyBzb3VyY2VzIHJlZ2lvblxuICogICAgZm9yIHRoYXQgcGFydGljdWxhciBwcm9wZXJ0eS5cbiAqXG4gKiAgICAtIElmIHRoZSBiaW5kaW5nIHZhbHVlIGlzIGEgbnVtYmVyIHRoZW4gaXQgd2lsbCBiZSBhZGRlZCBhcyBhIG5ld1xuICogICAgICBiaW5kaW5nIGluZGV4IHNvdXJjZSBuZXh0IHRvIHRoZSBvdGhlciBiaW5kaW5nIHNvdXJjZXMgZm9yIHRoZSBwcm9wZXJ0eS5cbiAqXG4gKiAgICAtIE90aGVyd2lzZSwgaWYgdGhlIGJpbmRpbmcgdmFsdWUgaXMgYSBzdHJpbmcvYm9vbGVhbi9udWxsIHR5cGUgdGhlbiBpdCB3aWxsXG4gKiAgICAgIHJlcGxhY2UgdGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSBwcm9wZXJ0eSBpZiB0aGUgZGVmYXVsdCB2YWx1ZSBpcyBgbnVsbGAuXG4gKlxuICogMikgSWYgdGhlIHByb3BlcnR5IGRvZXMgbm90IGV4aXN0IHRoZW4gaXQgd2lsbCBiZSBpbnNlcnRlZCBpbnRvIHRoZSBjb250ZXh0LlxuICogICAgVGhlIHN0eWxpbmcgY29udGV4dCByZWxpZXMgb24gYWxsIHByb3BlcnRpZXMgYmVpbmcgc3RvcmVkIGluIGFscGhhYmV0aWNhbFxuICogICAgb3JkZXIsIHNvIGl0IGtub3dzIGV4YWN0bHkgd2hlcmUgdG8gc3RvcmUgaXQuXG4gKlxuICogICAgV2hlbiBpbnNlcnRlZCwgYSBkZWZhdWx0IGBudWxsYCB2YWx1ZSBpcyBjcmVhdGVkIGZvciB0aGUgcHJvcGVydHkgd2hpY2ggZXhpc3RzXG4gKiAgICBhcyB0aGUgZGVmYXVsdCB2YWx1ZSBmb3IgdGhlIGJpbmRpbmcuIElmIHRoZSBiaW5kaW5nVmFsdWUgcHJvcGVydHkgaXMgaW5zZXJ0ZWRcbiAqICAgIGFuZCBpdCBpcyBlaXRoZXIgYSBzdHJpbmcsIG51bWJlciBvciBudWxsIHZhbHVlIHRoZW4gdGhhdCB3aWxsIHJlcGxhY2UgdGhlIGRlZmF1bHRcbiAqICAgIHZhbHVlLlxuICpcbiAqIE5vdGUgdGhhdCB0aGlzIGZ1bmN0aW9uIGlzIGFsc28gdXNlZCBmb3IgbWFwLWJhc2VkIHN0eWxpbmcgYmluZGluZ3MuIFRoZXkgYXJlIHRyZWF0ZWRcbiAqIG11Y2ggdGhlIHNhbWUgYXMgcHJvcC1iYXNlZCBiaW5kaW5ncywgYnV0LCB0aGVpciBwcm9wZXJ0eSBuYW1lIHZhbHVlIGlzIHNldCBhcyBgW01BUF1gLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJCaW5kaW5nKFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgdE5vZGU6IFRTdHlsaW5nTm9kZSwgY291bnRJZDogbnVtYmVyLCBzb3VyY2VJbmRleDogbnVtYmVyLFxuICAgIHByb3A6IHN0cmluZyB8IG51bGwsIGJpbmRpbmdWYWx1ZTogbnVtYmVyIHwgbnVsbCB8IHN0cmluZyB8IGJvb2xlYW4sXG4gICAgc2FuaXRpemF0aW9uUmVxdWlyZWQ6IGJvb2xlYW4sIGlzQ2xhc3NCYXNlZDogYm9vbGVhbik6IHZvaWQge1xuICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgcHJvcCA9IHByb3AgfHwgTUFQX0JBU0VEX0VOVFJZX1BST1BfTkFNRTtcblxuICBsZXQgdG90YWxTb3VyY2VzID0gZ2V0VG90YWxTb3VyY2VzKGNvbnRleHQpO1xuXG4gIC8vIGlmIGEgbmV3IHNvdXJjZSBpcyBkZXRlY3RlZCB0aGVuIGEgbmV3IGNvbHVtbiBuZWVkcyB0byBiZSBhbGxvY2F0ZWQgaW50b1xuICAvLyB0aGUgc3R5bGluZyBjb250ZXh0LiBUaGUgY29sdW1uIGlzIGJhc2ljYWxseSBhIG5ldyBhbGxvY2F0aW9uIG9mIGJpbmRpbmdcbiAgLy8gc291cmNlcyB0aGF0IHdpbGwgYmUgYXZhaWxhYmxlIHRvIGVhY2ggcHJvcGVydHkuXG4gIHdoaWxlICh0b3RhbFNvdXJjZXMgPD0gc291cmNlSW5kZXgpIHtcbiAgICBhZGROZXdTb3VyY2VDb2x1bW4oY29udGV4dCk7XG4gICAgdG90YWxTb3VyY2VzKys7XG4gIH1cblxuICBjb25zdCBjb2xsaXNpb25GbGFnID1cbiAgICAgIGlzQ2xhc3NCYXNlZCA/IFROb2RlRmxhZ3MuaGFzRHVwbGljYXRlQ2xhc3NCaW5kaW5ncyA6IFROb2RlRmxhZ3MuaGFzRHVwbGljYXRlU3R5bGVCaW5kaW5ncztcbiAgY29uc3QgaXNCaW5kaW5nSW5kZXhWYWx1ZSA9IHR5cGVvZiBiaW5kaW5nVmFsdWUgPT09ICdudW1iZXInO1xuICBjb25zdCBlbnRyaWVzUGVyUm93ID0gVFN0eWxpbmdDb250ZXh0SW5kZXguQmluZGluZ3NTdGFydE9mZnNldCArIGdldFZhbHVlc0NvdW50KGNvbnRleHQpO1xuICBsZXQgaSA9IFRTdHlsaW5nQ29udGV4dEluZGV4LlZhbHVlc1N0YXJ0UG9zaXRpb247XG5cbiAgLy8gYWxsIHN0eWxlL2NsYXNzIGJpbmRpbmdzIGFyZSBzb3J0ZWQgYnkgcHJvcGVydHkgbmFtZVxuICB3aGlsZSAoaSA8IGNvbnRleHQubGVuZ3RoKSB7XG4gICAgY29uc3QgcCA9IGdldFByb3AoY29udGV4dCwgaSk7XG4gICAgaWYgKHByb3AgPD0gcCkge1xuICAgICAgaWYgKHByb3AgPCBwKSB7XG4gICAgICAgIGFsbG9jYXRlTmV3Q29udGV4dEVudHJ5KGNvbnRleHQsIGksIHByb3AsIHNhbml0aXphdGlvblJlcXVpcmVkKTtcbiAgICAgIH0gZWxzZSBpZiAoaXNCaW5kaW5nSW5kZXhWYWx1ZSkge1xuICAgICAgICBwYXRjaENvbmZpZyh0Tm9kZSwgY29sbGlzaW9uRmxhZyk7XG4gICAgICB9XG4gICAgICBhZGRCaW5kaW5nSW50b0NvbnRleHQoY29udGV4dCwgaSwgYmluZGluZ1ZhbHVlLCBjb3VudElkLCBzb3VyY2VJbmRleCk7XG4gICAgICBmb3VuZCA9IHRydWU7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgaSArPSBlbnRyaWVzUGVyUm93O1xuICB9XG5cbiAgaWYgKCFmb3VuZCkge1xuICAgIGFsbG9jYXRlTmV3Q29udGV4dEVudHJ5KGNvbnRleHQsIGNvbnRleHQubGVuZ3RoLCBwcm9wLCBzYW5pdGl6YXRpb25SZXF1aXJlZCk7XG4gICAgYWRkQmluZGluZ0ludG9Db250ZXh0KGNvbnRleHQsIGksIGJpbmRpbmdWYWx1ZSwgY291bnRJZCwgc291cmNlSW5kZXgpO1xuICB9XG59XG5cbi8qKlxuICogSW5zZXJ0cyBhIG5ldyByb3cgaW50byB0aGUgcHJvdmlkZWQgYFRTdHlsaW5nQ29udGV4dGAgYW5kIGFzc2lnbnMgdGhlIHByb3ZpZGVkIGBwcm9wYCB2YWx1ZSBhc1xuICogdGhlIHByb3BlcnR5IGVudHJ5LlxuICovXG5mdW5jdGlvbiBhbGxvY2F0ZU5ld0NvbnRleHRFbnRyeShcbiAgICBjb250ZXh0OiBUU3R5bGluZ0NvbnRleHQsIGluZGV4OiBudW1iZXIsIHByb3A6IHN0cmluZywgc2FuaXRpemF0aW9uUmVxdWlyZWQ/OiBib29sZWFuKTogdm9pZCB7XG4gIGNvbnN0IGNvbmZpZyA9IHNhbml0aXphdGlvblJlcXVpcmVkID8gVFN0eWxpbmdDb250ZXh0UHJvcENvbmZpZ0ZsYWdzLlNhbml0aXphdGlvblJlcXVpcmVkIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUU3R5bGluZ0NvbnRleHRQcm9wQ29uZmlnRmxhZ3MuRGVmYXVsdDtcbiAgY29udGV4dC5zcGxpY2UoXG4gICAgICBpbmRleCwgMCxcbiAgICAgIGNvbmZpZywgICAgICAgICAgICAgICAgICAgIC8vIDEpIGNvbmZpZyB2YWx1ZVxuICAgICAgREVGQVVMVF9HVUFSRF9NQVNLX1ZBTFVFLCAgLy8gMikgdGVtcGxhdGUgYml0IG1hc2tcbiAgICAgIERFRkFVTFRfR1VBUkRfTUFTS19WQUxVRSwgIC8vIDMpIGhvc3QgYmluZGluZ3MgYml0IG1hc2tcbiAgICAgIHByb3AsICAgICAgICAgICAgICAgICAgICAgIC8vIDQpIHByb3AgdmFsdWUgKGUuZy4gYHdpZHRoYCwgYG15Q2xhc3NgLCBldGMuLi4pXG4gICAgICApO1xuXG4gIGluZGV4ICs9IDQ7ICAvLyB0aGUgNCB2YWx1ZXMgYWJvdmVcblxuICAvLyA1Li4uKSBkZWZhdWx0IGJpbmRpbmcgaW5kZXggZm9yIHRoZSB0ZW1wbGF0ZSB2YWx1ZVxuICAvLyBkZXBlbmRpbmcgb24gaG93IG1hbnkgc291cmNlcyBhbHJlYWR5IGV4aXN0IGluIHRoZSBjb250ZXh0LFxuICAvLyBtdWx0aXBsZSBkZWZhdWx0IGluZGV4IGVudHJpZXMgbWF5IG5lZWQgdG8gYmUgaW5zZXJ0ZWQgZm9yXG4gIC8vIHRoZSBuZXcgdmFsdWUgaW4gdGhlIGNvbnRleHQuXG4gIGNvbnN0IHRvdGFsQmluZGluZ3NQZXJFbnRyeSA9IGdldFRvdGFsU291cmNlcyhjb250ZXh0KTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB0b3RhbEJpbmRpbmdzUGVyRW50cnk7IGkrKykge1xuICAgIGNvbnRleHQuc3BsaWNlKGluZGV4LCAwLCBERUZBVUxUX0JJTkRJTkdfSU5ERVgpO1xuICAgIGluZGV4Kys7XG4gIH1cblxuICAvLyA2KSBkZWZhdWx0IGJpbmRpbmcgdmFsdWUgZm9yIHRoZSBuZXcgZW50cnlcbiAgY29udGV4dC5zcGxpY2UoaW5kZXgsIDAsIERFRkFVTFRfQklORElOR19WQUxVRSk7XG59XG5cbi8qKlxuICogSW5zZXJ0cyBhIG5ldyBiaW5kaW5nIHZhbHVlIGludG8gYSBzdHlsaW5nIHByb3BlcnR5IHR1cGxlIGluIHRoZSBgVFN0eWxpbmdDb250ZXh0YC5cbiAqXG4gKiBBIGJpbmRpbmdWYWx1ZSBpcyBpbnNlcnRlZCBpbnRvIGEgY29udGV4dCBkdXJpbmcgdGhlIGZpcnN0IHVwZGF0ZSBwYXNzXG4gKiBvZiBhIHRlbXBsYXRlIG9yIGhvc3QgYmluZGluZ3MgZnVuY3Rpb24uIFdoZW4gdGhpcyBvY2N1cnMsIHR3byB0aGluZ3NcbiAqIGhhcHBlbjpcbiAqXG4gKiAtIElmIHRoZSBiaW5kaW5nVmFsdWUgdmFsdWUgaXMgYSBudW1iZXIgdGhlbiBpdCBpcyB0cmVhdGVkIGFzIGEgYmluZGluZ0luZGV4XG4gKiAgIHZhbHVlIChhIGluZGV4IGluIHRoZSBgTFZpZXdgKSBhbmQgaXQgd2lsbCBiZSBpbnNlcnRlZCBuZXh0IHRvIHRoZSBvdGhlclxuICogICBiaW5kaW5nIGluZGV4IGVudHJpZXMuXG4gKlxuICogLSBPdGhlcndpc2UgdGhlIGJpbmRpbmcgdmFsdWUgd2lsbCB1cGRhdGUgdGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSBwcm9wZXJ0eVxuICogICBhbmQgdGhpcyB3aWxsIG9ubHkgaGFwcGVuIGlmIHRoZSBkZWZhdWx0IHZhbHVlIGlzIGBudWxsYC5cbiAqL1xuZnVuY3Rpb24gYWRkQmluZGluZ0ludG9Db250ZXh0KFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgaW5kZXg6IG51bWJlciwgYmluZGluZ1ZhbHVlOiBudW1iZXIgfCBzdHJpbmcgfCBib29sZWFuIHwgbnVsbCxcbiAgICBiaXRJbmRleDogbnVtYmVyLCBzb3VyY2VJbmRleDogbnVtYmVyKSB7XG4gIGlmICh0eXBlb2YgYmluZGluZ1ZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIGNvbnN0IGhvc3RCaW5kaW5nc01vZGUgPSBpc0hvc3RTdHlsaW5nQWN0aXZlKHNvdXJjZUluZGV4KTtcbiAgICBjb25zdCBjZWxsSW5kZXggPSBpbmRleCArIFRTdHlsaW5nQ29udGV4dEluZGV4LkJpbmRpbmdzU3RhcnRPZmZzZXQgKyBzb3VyY2VJbmRleDtcbiAgICBjb250ZXh0W2NlbGxJbmRleF0gPSBiaW5kaW5nVmFsdWU7XG4gICAgY29uc3QgdXBkYXRlZEJpdE1hc2sgPSBnZXRHdWFyZE1hc2soY29udGV4dCwgaW5kZXgsIGhvc3RCaW5kaW5nc01vZGUpIHwgKDEgPDwgYml0SW5kZXgpO1xuICAgIHNldEd1YXJkTWFzayhjb250ZXh0LCBpbmRleCwgdXBkYXRlZEJpdE1hc2ssIGhvc3RCaW5kaW5nc01vZGUpO1xuICB9IGVsc2UgaWYgKGJpbmRpbmdWYWx1ZSAhPT0gbnVsbCAmJiBnZXREZWZhdWx0VmFsdWUoY29udGV4dCwgaW5kZXgpID09PSBudWxsKSB7XG4gICAgc2V0RGVmYXVsdFZhbHVlKGNvbnRleHQsIGluZGV4LCBiaW5kaW5nVmFsdWUpO1xuICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIGEgbmV3IGNvbHVtbiBpbnRvIHRoZSBwcm92aWRlZCBgVFN0eWxpbmdDb250ZXh0YC5cbiAqXG4gKiBJZiBhbmQgd2hlbiBhIG5ldyBzb3VyY2UgaXMgZGV0ZWN0ZWQgdGhlbiBhIG5ldyBjb2x1bW4gbmVlZHMgdG9cbiAqIGJlIGFsbG9jYXRlZCBpbnRvIHRoZSBzdHlsaW5nIGNvbnRleHQuIFRoZSBjb2x1bW4gaXMgYmFzaWNhbGx5XG4gKiBhIG5ldyBhbGxvY2F0aW9uIG9mIGJpbmRpbmcgc291cmNlcyB0aGF0IHdpbGwgYmUgYXZhaWxhYmxlIHRvIGVhY2hcbiAqIHByb3BlcnR5LlxuICpcbiAqIEVhY2ggY29sdW1uIHRoYXQgZXhpc3RzIGluIHRoZSBzdHlsaW5nIGNvbnRleHQgcmVzZW1ibGVzIGEgc3R5bGluZ1xuICogc291cmNlLiBBIHN0eWxpbmcgc291cmNlIGFuIGVpdGhlciBiZSB0aGUgdGVtcGxhdGUgb3Igb25lIG9yIG1vcmVcbiAqIGNvbXBvbmVudHMgb3IgZGlyZWN0aXZlcyBhbGwgY29udGFpbmluZyBzdHlsaW5nIGhvc3QgYmluZGluZ3MuXG4gKi9cbmZ1bmN0aW9uIGFkZE5ld1NvdXJjZUNvbHVtbihjb250ZXh0OiBUU3R5bGluZ0NvbnRleHQpOiB2b2lkIHtcbiAgLy8gd2UgdXNlIC0xIGhlcmUgYmVjYXVzZSB3ZSB3YW50IHRvIGluc2VydCByaWdodCBiZWZvcmUgdGhlIGxhc3QgdmFsdWUgKHRoZSBkZWZhdWx0IHZhbHVlKVxuICBjb25zdCBpbnNlcnRPZmZzZXQgPSBUU3R5bGluZ0NvbnRleHRJbmRleC5CaW5kaW5nc1N0YXJ0T2Zmc2V0ICsgZ2V0VmFsdWVzQ291bnQoY29udGV4dCkgLSAxO1xuXG4gIGxldCBpbmRleCA9IFRTdHlsaW5nQ29udGV4dEluZGV4LlZhbHVlc1N0YXJ0UG9zaXRpb247XG4gIHdoaWxlIChpbmRleCA8IGNvbnRleHQubGVuZ3RoKSB7XG4gICAgaW5kZXggKz0gaW5zZXJ0T2Zmc2V0O1xuICAgIGNvbnRleHQuc3BsaWNlKGluZGV4KyssIDAsIERFRkFVTFRfQklORElOR19JTkRFWCk7XG5cbiAgICAvLyB0aGUgdmFsdWUgd2FzIGluc2VydGVkIGp1c3QgYmVmb3JlIHRoZSBkZWZhdWx0IHZhbHVlLCBidXQgdGhlXG4gICAgLy8gbmV4dCBlbnRyeSBpbiB0aGUgY29udGV4dCBzdGFydHMganVzdCBhZnRlciBpdC4gVGhlcmVmb3JlKysuXG4gICAgaW5kZXgrKztcbiAgfVxuICBjb250ZXh0W1RTdHlsaW5nQ29udGV4dEluZGV4LlRvdGFsU291cmNlc1Bvc2l0aW9uXSsrO1xufVxuXG4vKipcbiAqIEFwcGxpZXMgYWxsIHBlbmRpbmcgc3R5bGUgYW5kIGNsYXNzIGJpbmRpbmdzIHRvIHRoZSBwcm92aWRlZCBlbGVtZW50LlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBhdHRlbXB0IHRvIGZsdXNoIHN0eWxpbmcgdmlhIHRoZSBwcm92aWRlZCBgY2xhc3Nlc0NvbnRleHRgXG4gKiBhbmQgYHN0eWxlc0NvbnRleHRgIGNvbnRleHQgdmFsdWVzLiBUaGlzIGZ1bmN0aW9uIGlzIGRlc2lnbmVkIHRvIGJlIHJ1biBmcm9tXG4gKiB0aGUgaW50ZXJuYWwgYHN0eWxpbmdBcHBseWAgZnVuY3Rpb24gKHdoaWNoIGlzIHNjaGVkdWxlZCB0byBydW4gYXQgdGhlIHZlcnlcbiAqIGVuZCBvZiBjaGFuZ2UgZGV0ZWN0aW9uIGZvciBhbiBlbGVtZW50IGlmIG9uZSBvciBtb3JlIHN0eWxlL2NsYXNzIGJpbmRpbmdzXG4gKiB3ZXJlIHByb2Nlc3NlZCkgYW5kIHdpbGwgcmVseSBvbiBhbnkgc3RhdGUgdmFsdWVzIHRoYXQgYXJlIHNldCBmcm9tIHdoZW5cbiAqIGFueSBvZiB0aGUgc3R5bGluZyBiaW5kaW5ncyBleGVjdXRlZC5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGRlc2lnbmVkIHRvIGJlIGNhbGxlZCB0d2ljZTogb25lIHdoZW4gY2hhbmdlIGRldGVjdGlvbiBoYXNcbiAqIHByb2Nlc3NlZCBhbiBlbGVtZW50IHdpdGhpbiB0aGUgdGVtcGxhdGUgYmluZGluZ3MgKGkuZS4ganVzdCBhcyBgYWR2YW5jZSgpYFxuICogaXMgY2FsbGVkKSBhbmQgd2hlbiBob3N0IGJpbmRpbmdzIGhhdmUgYmVlbiBwcm9jZXNzZWQuIEluIGJvdGggY2FzZXMgdGhlXG4gKiBzdHlsZXMgYW5kIGNsYXNzZXMgaW4gYm90aCBjb250ZXh0cyB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIGVsZW1lbnQsIGJ1dCB0aGVcbiAqIGFsZ29yaXRobSB3aWxsIHNlbGVjdGl2ZWx5IGRlY2lkZSB3aGljaCBiaW5kaW5ncyB0byBydW4gZGVwZW5kaW5nIG9uIHRoZVxuICogY29sdW1ucyBpbiB0aGUgY29udGV4dC4gVGhlIHByb3ZpZGVkIGBkaXJlY3RpdmVJbmRleGAgdmFsdWUgd2lsbCBoZWxwIHRoZVxuICogYWxnb3JpdGhtIGRldGVybWluZSB3aGljaCBiaW5kaW5ncyB0byBhcHBseTogZWl0aGVyIHRoZSB0ZW1wbGF0ZSBiaW5kaW5ncyBvclxuICogdGhlIGhvc3QgYmluZGluZ3MgKHNlZSBgYXBwbHlTdHlsaW5nVG9FbGVtZW50YCBmb3IgbW9yZSBpbmZvcm1hdGlvbikuXG4gKlxuICogTm90ZSB0aGF0IG9uY2UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYWxsIHRlbXBvcmFyeSBzdHlsaW5nIHN0YXRlIGRhdGFcbiAqIChpLmUuIHRoZSBgYml0TWFza2AgYW5kIGBjb3VudGVyYCB2YWx1ZXMgZm9yIHN0eWxlcyBhbmQgY2xhc3NlcyB3aWxsIGJlIGNsZWFyZWQpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmx1c2hTdHlsaW5nKFxuICAgIHJlbmRlcmVyOiBSZW5kZXJlcjMgfCBQcm9jZWR1cmFsUmVuZGVyZXIzIHwgbnVsbCwgZGF0YTogTFN0eWxpbmdEYXRhLCB0Tm9kZTogVFN0eWxpbmdOb2RlLFxuICAgIGNsYXNzZXNDb250ZXh0OiBUU3R5bGluZ0NvbnRleHQgfCBudWxsLCBzdHlsZXNDb250ZXh0OiBUU3R5bGluZ0NvbnRleHQgfCBudWxsLFxuICAgIGVsZW1lbnQ6IFJFbGVtZW50LCBkaXJlY3RpdmVJbmRleDogbnVtYmVyLCBzdHlsZVNhbml0aXplcjogU3R5bGVTYW5pdGl6ZUZuIHwgbnVsbCxcbiAgICBmaXJzdFVwZGF0ZVBhc3M6IGJvb2xlYW4pOiB2b2lkIHtcbiAgbmdEZXZNb2RlICYmIG5nRGV2TW9kZS5mbHVzaFN0eWxpbmcrKztcblxuICBjb25zdCBzdGF0ZSA9IGdldFN0eWxpbmdTdGF0ZShlbGVtZW50LCBkaXJlY3RpdmVJbmRleCk7XG4gIGNvbnN0IGhvc3RCaW5kaW5nc01vZGUgPSBpc0hvc3RTdHlsaW5nQWN0aXZlKHN0YXRlLnNvdXJjZUluZGV4KTtcblxuICBpZiAoc3R5bGVzQ29udGV4dCkge1xuICAgIGZpcnN0VXBkYXRlUGFzcyAmJiBzeW5jQ29udGV4dEluaXRpYWxTdHlsaW5nKHN0eWxlc0NvbnRleHQsIHROb2RlLCBmYWxzZSk7XG5cbiAgICBpZiAoc3RhdGUuc3R5bGVzQml0TWFzayAhPT0gMCkge1xuICAgICAgYXBwbHlTdHlsaW5nVmlhQ29udGV4dChcbiAgICAgICAgICBzdHlsZXNDb250ZXh0LCB0Tm9kZSwgcmVuZGVyZXIsIGVsZW1lbnQsIGRhdGEsIHN0YXRlLnN0eWxlc0JpdE1hc2ssIHNldFN0eWxlLFxuICAgICAgICAgIHN0eWxlU2FuaXRpemVyLCBob3N0QmluZGluZ3NNb2RlLCBmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGNsYXNzZXNDb250ZXh0KSB7XG4gICAgZmlyc3RVcGRhdGVQYXNzICYmIHN5bmNDb250ZXh0SW5pdGlhbFN0eWxpbmcoY2xhc3Nlc0NvbnRleHQsIHROb2RlLCB0cnVlKTtcblxuICAgIGlmIChzdGF0ZS5jbGFzc2VzQml0TWFzayAhPT0gMCkge1xuICAgICAgYXBwbHlTdHlsaW5nVmlhQ29udGV4dChcbiAgICAgICAgICBjbGFzc2VzQ29udGV4dCwgdE5vZGUsIHJlbmRlcmVyLCBlbGVtZW50LCBkYXRhLCBzdGF0ZS5jbGFzc2VzQml0TWFzaywgc2V0Q2xhc3MsIG51bGwsXG4gICAgICAgICAgaG9zdEJpbmRpbmdzTW9kZSwgdHJ1ZSk7XG4gICAgfVxuICB9XG5cbiAgcmVzZXRTdHlsaW5nU3RhdGUoKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYWxsIHN0YXRpYyBzdHlsaW5nIHZhbHVlcyBpbnRvIHRoZSBjb250ZXh0IGFzIGRlZmF1bHQgdmFsdWVzLlxuICpcbiAqIFN0YXRpYyBzdHlsZXMgYXJlIHN0b3JlZCBvbiB0aGUgYHROb2RlLnN0eWxlc2AgYW5kIGB0Tm9kZS5jbGFzc2VzYFxuICogcHJvcGVydGllcyBhcyBpbnN0YW5jZXMgb2YgYFN0eWxpbmdNYXBBcnJheWAuIFdoZW4gYW4gaW5zdGFuY2Ugb2ZcbiAqIGBUU3R5bGluZ0NvbnRleHRgIGlzIGFzc2lnbmVkIHRvIGB0Tm9kZS5zdHlsZXNgIGFuZCBgdE5vZGUuY2xhc3Nlc2BcbiAqIHRoZW4gdGhlIGV4aXN0aW5nIGluaXRpYWwgc3R5bGluZyB2YWx1ZXMgYXJlIGNvcGllZCBpbnRvIHRoZSB0aGVcbiAqIGBJbml0aWFsU3R5bGluZ1ZhbHVlUG9zaXRpb25gIHNsb3QuXG4gKlxuICogQmVjYXVzZSBhbGwgc3RhdGljIHN0eWxlcy9jbGFzc2VzIGFyZSBjb2xsZWN0ZWQgYW5kIHJlZ2lzdGVyZWQgb25cbiAqIHRoZSBpbml0aWFsIHN0eWxpbmcgYXJyYXkgZWFjaCB0aW1lIGEgZGlyZWN0aXZlIGlzIGluc3RhbnRpYXRlZCxcbiAqIHRoZSBjb250ZXh0IG1heSBub3QgeWV0IGtub3cgYWJvdXQgdGhlIHN0YXRpYyB2YWx1ZXMuIFdoZW4gdGhpc1xuICogZnVuY3Rpb24gaXMgY2FsbGVkIGl0IHdpbGwgY29weSBvdmVyIGFsbCB0aGUgc3RhdGljIHN0eWxlL2NsYXNzXG4gKiB2YWx1ZXMgZnJvbSB0aGUgaW5pdGlhbCBzdHlsaW5nIGFycmF5IGludG8gdGhlIGNvbnRleHQgYXMgZGVmYXVsdFxuICogdmFsdWVzIGZvciBlYWNoIG9mIHRoZSBtYXRjaGluZyBlbnRyaWVzIGluIHRoZSBjb250ZXh0LlxuICpcbiAqIExldCdzIGltYWdpbmUgdGhlIGZvbGxvd2luZyBleGFtcGxlOlxuICpcbiAqIGBgYGh0bWxcbiAqIDxkaXYgc3R5bGU9XCJjb2xvcjpyZWRcIlxuICogICAgIFtzdHlsZS5jb2xvcl09XCJteUNvbG9yXCJcbiAqICAgICBkaXItdGhhdC1oYXMtc3RhdGljLWhlaWdodD5cbiAqICAgLi4uXG4gKiA8L2Rpdj5cbiAqIGBgYFxuICpcbiAqIFdoZW4gdGhlIGNvZGUgYWJvdmUgaXMgcHJvY2Vzc2VkLCB0aGUgdW5kZXJseWluZyBlbGVtZW50L3N0eWxpbmdcbiAqIGluc3RydWN0aW9ucyB3aWxsIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiBgVFN0eWxpbmdDb250ZXh0YCBmb3JcbiAqIHRoZSBgdE5vZGUuc3R5bGVzYCBwcm9wZXJ0eS4gSGVyZSdzIHdoYXQgdGhhdCBsb29rcyBsaWtlOlxuICpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIHROb2RlLnN0eWxlcyA9IFtcbiAqICAgLy8gLi4uXG4gKiAgIC8vIGluaXRpYWwgc3R5bGVzXG4gKiAgIFsnY29sb3I6cmVkOyBoZWlnaHQ6MjAwcHgnLCAnY29sb3InLCAncmVkJywgJ2hlaWdodCcsICcyMDBweCddLFxuICpcbiAqICAgMCwgMGIxLCAwYjAsICdjb2xvcicsIDIwLCBudWxsLCAvLyBbc3R5bGUuY29sb3JdIGJpbmRpbmdcbiAqIF1cbiAqIGBgYFxuICpcbiAqIEFmdGVyIHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGl0IHdpbGwgYmFsYW5jZSBvdXQgdGhlIGNvbnRleHQgd2l0aFxuICogdGhlIHN0YXRpYyBgY29sb3JgIGFuZCBgaGVpZ2h0YCB2YWx1ZXMgYW5kIHNldCB0aGVtIGFzIGRlZmF1bHRzIHdpdGhpblxuICogdGhlIGNvbnRleHQ6XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogdE5vZGUuc3R5bGVzID0gW1xuICogICAvLyAuLi5cbiAqICAgLy8gaW5pdGlhbCBzdHlsZXNcbiAqICAgWydjb2xvcjpyZWQ7IGhlaWdodDoyMDBweCcsICdjb2xvcicsICdyZWQnLCAnaGVpZ2h0JywgJzIwMHB4J10sXG4gKlxuICogICAwLCAwYjEsIDBiMCwgJ2NvbG9yJywgMjAsICdyZWQnLFxuICogICAwLCAwYjAsIDBiMCwgJ2hlaWdodCcsIDAsICcyMDBweCcsXG4gKiBdXG4gKiBgYGBcbiAqL1xuZnVuY3Rpb24gc3luY0NvbnRleHRJbml0aWFsU3R5bGluZyhcbiAgICBjb250ZXh0OiBUU3R5bGluZ0NvbnRleHQsIHROb2RlOiBUU3R5bGluZ05vZGUsIGlzQ2xhc3NCYXNlZDogYm9vbGVhbik6IHZvaWQge1xuICAvLyB0aGUgVFN0eWxpbmdDb250ZXh0IGFsd2F5cyBoYXMgaW5pdGlhbCBzdHlsZS9jbGFzcyB2YWx1ZXMgd2hpY2ggYXJlXG4gIC8vIHN0b3JlZCBpbiBzdHlsaW5nIGFycmF5IGZvcm1hdC5cbiAgdXBkYXRlSW5pdGlhbFN0eWxpbmdPbkNvbnRleHQoY29udGV4dCwgdE5vZGUsIGdldFN0eWxpbmdNYXBBcnJheShjb250ZXh0KSAhLCBpc0NsYXNzQmFzZWQpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbGwgaW5pdGlhbCBzdHlsaW5nIGVudHJpZXMgaW50byB0aGUgcHJvdmlkZWQgY29udGV4dC5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgaXRlcmF0ZSBvdmVyIGFsbCBlbnRyaWVzIGluIHRoZSBwcm92aWRlZCBgaW5pdGlhbFN0eWxpbmdgIGFyfXJheSBhbmQgcmVnaXN0ZXJcbiAqIHRoZW0gYXMgZGVmYXVsdCAoaW5pdGlhbCkgdmFsdWVzIGluIHRoZSBwcm92aWRlZCBjb250ZXh0LiBJbml0aWFsIHN0eWxpbmcgdmFsdWVzIGluIGEgY29udGV4dCBhcmVcbiAqIHRoZSBkZWZhdWx0IHZhbHVlcyB0aGF0IGFyZSB0byBiZSBhcHBsaWVkIHVubGVzcyBvdmVyd3JpdHRlbiBieSBhIGJpbmRpbmcuXG4gKlxuICogVGhlIHJlYXNvbiB3aHkgdGhpcyBmdW5jdGlvbiBleGlzdHMgYW5kIGlzbid0IGEgcGFydCBvZiB0aGUgY29udGV4dCBjb25zdHJ1Y3Rpb24gaXMgYmVjYXVzZVxuICogaG9zdCBiaW5kaW5nIGlzIGV2YWx1YXRlZCBhdCBhIGxhdGVyIHN0YWdlIGFmdGVyIHRoZSBlbGVtZW50IGlzIGNyZWF0ZWQuIFRoaXMgbWVhbnMgdGhhdFxuICogaWYgYSBkaXJlY3RpdmUgb3IgY29tcG9uZW50IGNvbnRhaW5zIGFueSBpbml0aWFsIHN0eWxpbmcgY29kZSAoaS5lLiBgPGRpdiBjbGFzcz1cImZvb1wiPmApXG4gKiB0aGVuIHRoYXQgaW5pdGlhbCBzdHlsaW5nIGRhdGEgY2FuIG9ubHkgYmUgYXBwbGllZCBvbmNlIHRoZSBzdHlsaW5nIGZvciB0aGF0IGVsZW1lbnRcbiAqIGlzIGZpcnN0IGFwcGxpZWQgKGF0IHRoZSBlbmQgb2YgdGhlIHVwZGF0ZSBwaGFzZSkuIE9uY2UgdGhhdCBoYXBwZW5zIHRoZW4gdGhlIGNvbnRleHQgd2lsbFxuICogdXBkYXRlIGl0c2VsZiB3aXRoIHRoZSBjb21wbGV0ZSBpbml0aWFsIHN0eWxpbmcgZm9yIHRoZSBlbGVtZW50LlxuICovXG5mdW5jdGlvbiB1cGRhdGVJbml0aWFsU3R5bGluZ09uQ29udGV4dChcbiAgICBjb250ZXh0OiBUU3R5bGluZ0NvbnRleHQsIHROb2RlOiBUU3R5bGluZ05vZGUsIGluaXRpYWxTdHlsaW5nOiBTdHlsaW5nTWFwQXJyYXksXG4gICAgaXNDbGFzc0Jhc2VkOiBib29sZWFuKTogdm9pZCB7XG4gIC8vIGAtMWAgaXMgdXNlZCBoZXJlIGJlY2F1c2UgYWxsIGluaXRpYWwgc3R5bGluZyBkYXRhIGlzIG5vdCBhIGFwYXJ0XG4gIC8vIG9mIGEgYmluZGluZyAoc2luY2UgaXQncyBzdGF0aWMpXG4gIGNvbnN0IENPVU5UX0lEX0ZPUl9TVFlMSU5HID0gLTE7XG5cbiAgbGV0IGhhc0luaXRpYWxTdHlsaW5nID0gZmFsc2U7XG4gIGZvciAobGV0IGkgPSBTdHlsaW5nTWFwQXJyYXlJbmRleC5WYWx1ZXNTdGFydFBvc2l0aW9uOyBpIDwgaW5pdGlhbFN0eWxpbmcubGVuZ3RoO1xuICAgICAgIGkgKz0gU3R5bGluZ01hcEFycmF5SW5kZXguVHVwbGVTaXplKSB7XG4gICAgY29uc3QgdmFsdWUgPSBnZXRNYXBWYWx1ZShpbml0aWFsU3R5bGluZywgaSk7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICBjb25zdCBwcm9wID0gZ2V0TWFwUHJvcChpbml0aWFsU3R5bGluZywgaSk7XG4gICAgICByZWdpc3RlckJpbmRpbmcoY29udGV4dCwgdE5vZGUsIENPVU5UX0lEX0ZPUl9TVFlMSU5HLCAwLCBwcm9wLCB2YWx1ZSwgZmFsc2UsIGlzQ2xhc3NCYXNlZCk7XG4gICAgICBoYXNJbml0aWFsU3R5bGluZyA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKGhhc0luaXRpYWxTdHlsaW5nKSB7XG4gICAgcGF0Y2hDb25maWcodE5vZGUsIFROb2RlRmxhZ3MuaGFzSW5pdGlhbFN0eWxpbmcpO1xuICB9XG59XG5cbi8qKlxuICogUnVucyB0aHJvdWdoIHRoZSBwcm92aWRlZCBzdHlsaW5nIGNvbnRleHQgYW5kIGFwcGxpZXMgZWFjaCB2YWx1ZSB0b1xuICogdGhlIHByb3ZpZGVkIGVsZW1lbnQgKHZpYSB0aGUgcmVuZGVyZXIpIGlmIG9uZSBvciBtb3JlIHZhbHVlcyBhcmUgcHJlc2VudC5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgaXRlcmF0ZSBvdmVyIGFsbCBlbnRyaWVzIHByZXNlbnQgaW4gdGhlIHByb3ZpZGVkXG4gKiBgVFN0eWxpbmdDb250ZXh0YCBhcnJheSAoYm90aCBwcm9wLWJhc2VkIGFuZCBtYXAtYmFzZWQgYmluZGluZ3MpLi1cbiAqXG4gKiBFYWNoIGVudHJ5LCB3aXRoaW4gdGhlIGBUU3R5bGluZ0NvbnRleHRgIGFycmF5LCBpcyBzdG9yZWQgYWxwaGFiZXRpY2FsbHlcbiAqIGFuZCB0aGlzIG1lYW5zIHRoYXQgZWFjaCBwcm9wL3ZhbHVlIGVudHJ5IHdpbGwgYmUgYXBwbGllZCBpbiBvcmRlclxuICogKHNvIGxvbmcgYXMgaXQgaXMgbWFya2VkIGRpcnR5IGluIHRoZSBwcm92aWRlZCBgYml0TWFza2AgdmFsdWUpLlxuICpcbiAqIElmIHRoZXJlIGFyZSBhbnkgbWFwLWJhc2VkIGVudHJpZXMgcHJlc2VudCAod2hpY2ggYXJlIGFwcGxpZWQgdG8gdGhlXG4gKiBlbGVtZW50IHZpYSB0aGUgYFtzdHlsZV1gIGFuZCBgW2NsYXNzXWAgYmluZGluZ3MpIHRoZW4gdGhvc2UgZW50cmllc1xuICogd2lsbCBiZSBhcHBsaWVkIGFzIHdlbGwuIEhvd2V2ZXIsIHRoZSBjb2RlIGZvciB0aGF0IGlzIG5vdCBhIHBhcnQgb2ZcbiAqIHRoaXMgZnVuY3Rpb24uIEluc3RlYWQsIGVhY2ggdGltZSBhIHByb3BlcnR5IGlzIHZpc2l0ZWQsIHRoZW4gdGhlXG4gKiBjb2RlIGJlbG93IHdpbGwgY2FsbCBhbiBleHRlcm5hbCBmdW5jdGlvbiBjYWxsZWQgYHN0eWxpbmdNYXBzU3luY0ZuYFxuICogYW5kLCBpZiBwcmVzZW50LCBpdCB3aWxsIGtlZXAgdGhlIGFwcGxpY2F0aW9uIG9mIHN0eWxpbmcgdmFsdWVzIGluXG4gKiBtYXAtYmFzZWQgYmluZGluZ3MgdXAgdG8gc3luYyB3aXRoIHRoZSBhcHBsaWNhdGlvbiBvZiBwcm9wLWJhc2VkXG4gKiBiaW5kaW5ncy5cbiAqXG4gKiBWaXNpdCBgc3R5bGluZy9tYXBfYmFzZWRfYmluZGluZ3MudHNgIHRvIGxlYXJuIG1vcmUgYWJvdXQgaG93IHRoZVxuICogYWxnb3JpdGhtIHdvcmtzIGZvciBtYXAtYmFzZWQgc3R5bGluZyBiaW5kaW5ncy5cbiAqXG4gKiBOb3RlIHRoYXQgdGhpcyBmdW5jdGlvbiBpcyBub3QgZGVzaWduZWQgdG8gYmUgY2FsbGVkIGluIGlzb2xhdGlvbiAodXNlXG4gKiB0aGUgYGZsdXNoU3R5bGluZ2AgZnVuY3Rpb24gc28gdGhhdCBpdCBjYW4gY2FsbCB0aGlzIGZ1bmN0aW9uIGZvciBib3RoXG4gKiB0aGUgc3R5bGVzIGFuZCBjbGFzc2VzIGNvbnRleHRzKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5U3R5bGluZ1ZpYUNvbnRleHQoXG4gICAgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LCB0Tm9kZTogVFN0eWxpbmdOb2RlLCByZW5kZXJlcjogUmVuZGVyZXIzIHwgUHJvY2VkdXJhbFJlbmRlcmVyMyB8IG51bGwsXG4gICAgZWxlbWVudDogUkVsZW1lbnQsIGJpbmRpbmdEYXRhOiBMU3R5bGluZ0RhdGEsIGJpdE1hc2tWYWx1ZTogbnVtYmVyIHwgYm9vbGVhbixcbiAgICBhcHBseVN0eWxpbmdGbjogQXBwbHlTdHlsaW5nRm4sIHNhbml0aXplcjogU3R5bGVTYW5pdGl6ZUZuIHwgbnVsbCwgaG9zdEJpbmRpbmdzTW9kZTogYm9vbGVhbixcbiAgICBpc0NsYXNzQmFzZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgY29uc3QgYml0TWFzayA9IG5vcm1hbGl6ZUJpdE1hc2tWYWx1ZShiaXRNYXNrVmFsdWUpO1xuXG4gIGxldCBzdHlsaW5nTWFwc1N5bmNGbjogU3luY1N0eWxpbmdNYXBzRm58bnVsbCA9IG51bGw7XG4gIGxldCBhcHBseUFsbFZhbHVlcyA9IGZhbHNlO1xuICBjb25zdCBtYXBCaW5kaW5nc0ZsYWcgPVxuICAgICAgaXNDbGFzc0Jhc2VkID8gVE5vZGVGbGFncy5oYXNDbGFzc01hcEJpbmRpbmdzIDogVE5vZGVGbGFncy5oYXNTdHlsZU1hcEJpbmRpbmdzO1xuICBpZiAoaGFzQ29uZmlnKHROb2RlLCBtYXBCaW5kaW5nc0ZsYWcpKSB7XG4gICAgc3R5bGluZ01hcHNTeW5jRm4gPSBnZXRTdHlsaW5nTWFwc1N5bmNGbigpO1xuICAgIGNvbnN0IG1hcHNHdWFyZE1hc2sgPVxuICAgICAgICBnZXRHdWFyZE1hc2soY29udGV4dCwgVFN0eWxpbmdDb250ZXh0SW5kZXguVmFsdWVzU3RhcnRQb3NpdGlvbiwgaG9zdEJpbmRpbmdzTW9kZSk7XG4gICAgYXBwbHlBbGxWYWx1ZXMgPSAoYml0TWFzayAmIG1hcHNHdWFyZE1hc2spICE9PSAwO1xuICB9XG5cbiAgY29uc3QgdmFsdWVzQ291bnQgPSBnZXRWYWx1ZXNDb3VudChjb250ZXh0KTtcbiAgbGV0IHRvdGFsQmluZGluZ3NUb1Zpc2l0ID0gMTtcbiAgbGV0IG1hcHNNb2RlID1cbiAgICAgIGFwcGx5QWxsVmFsdWVzID8gU3R5bGluZ01hcHNTeW5jTW9kZS5BcHBseUFsbFZhbHVlcyA6IFN0eWxpbmdNYXBzU3luY01vZGUuVHJhdmVyc2VWYWx1ZXM7XG4gIGlmIChob3N0QmluZGluZ3NNb2RlKSB7XG4gICAgbWFwc01vZGUgfD0gU3R5bGluZ01hcHNTeW5jTW9kZS5SZWN1cnNlSW5uZXJNYXBzO1xuICAgIHRvdGFsQmluZGluZ3NUb1Zpc2l0ID0gdmFsdWVzQ291bnQgLSAxO1xuICB9XG5cbiAgbGV0IGkgPSBnZXRQcm9wVmFsdWVzU3RhcnRQb3NpdGlvbihjb250ZXh0LCB0Tm9kZSwgaXNDbGFzc0Jhc2VkKTtcbiAgd2hpbGUgKGkgPCBjb250ZXh0Lmxlbmd0aCkge1xuICAgIGNvbnN0IGd1YXJkTWFzayA9IGdldEd1YXJkTWFzayhjb250ZXh0LCBpLCBob3N0QmluZGluZ3NNb2RlKTtcbiAgICBpZiAoYml0TWFzayAmIGd1YXJkTWFzaykge1xuICAgICAgbGV0IHZhbHVlQXBwbGllZCA9IGZhbHNlO1xuICAgICAgY29uc3QgcHJvcCA9IGdldFByb3AoY29udGV4dCwgaSk7XG4gICAgICBjb25zdCBkZWZhdWx0VmFsdWUgPSBnZXREZWZhdWx0VmFsdWUoY29udGV4dCwgaSk7XG5cbiAgICAgIC8vIFBhcnQgMTogVmlzaXQgdGhlIGBbc3R5bGluZy5wcm9wXWAgdmFsdWVcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdG90YWxCaW5kaW5nc1RvVmlzaXQ7IGorKykge1xuICAgICAgICBjb25zdCBiaW5kaW5nSW5kZXggPSBnZXRCaW5kaW5nVmFsdWUoY29udGV4dCwgaSwgaikgYXMgbnVtYmVyO1xuICAgICAgICBpZiAoIXZhbHVlQXBwbGllZCAmJiBiaW5kaW5nSW5kZXggIT09IDApIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IGdldFZhbHVlKGJpbmRpbmdEYXRhLCBiaW5kaW5nSW5kZXgpO1xuICAgICAgICAgIGlmIChpc1N0eWxpbmdWYWx1ZURlZmluZWQodmFsdWUpKSB7XG4gICAgICAgICAgICBjb25zdCBjaGVja1ZhbHVlT25seSA9IGhvc3RCaW5kaW5nc01vZGUgJiYgaiA9PT0gMDtcbiAgICAgICAgICAgIGlmICghY2hlY2tWYWx1ZU9ubHkpIHtcbiAgICAgICAgICAgICAgY29uc3QgZmluYWxWYWx1ZSA9IHNhbml0aXplciAmJiBpc1Nhbml0aXphdGlvblJlcXVpcmVkKGNvbnRleHQsIGkpID9cbiAgICAgICAgICAgICAgICAgIHNhbml0aXplcihwcm9wLCB2YWx1ZSwgU3R5bGVTYW5pdGl6ZU1vZGUuU2FuaXRpemVPbmx5KSA6XG4gICAgICAgICAgICAgICAgICB1bndyYXBTYWZlVmFsdWUodmFsdWUpO1xuICAgICAgICAgICAgICBhcHBseVN0eWxpbmdGbihyZW5kZXJlciwgZWxlbWVudCwgcHJvcCwgZmluYWxWYWx1ZSwgYmluZGluZ0luZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhbHVlQXBwbGllZCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUGFydCAyOiBWaXNpdCB0aGUgYFtzdHlsZV1gIG9yIGBbY2xhc3NdYCBtYXAtYmFzZWQgdmFsdWVcbiAgICAgICAgaWYgKHN0eWxpbmdNYXBzU3luY0ZuKSB7XG4gICAgICAgICAgLy8gZGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IHRvIGFwcGx5IHRoZSB0YXJnZXQgcHJvcGVydHkgb3IgdG8gc2tpcCBpdFxuICAgICAgICAgIGxldCBtb2RlID0gbWFwc01vZGUgfCAodmFsdWVBcHBsaWVkID8gU3R5bGluZ01hcHNTeW5jTW9kZS5Ta2lwVGFyZ2V0UHJvcCA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdHlsaW5nTWFwc1N5bmNNb2RlLkFwcGx5VGFyZ2V0UHJvcCk7XG5cbiAgICAgICAgICAvLyB0aGUgZmlyc3QgY29sdW1uIGluIHRoZSBjb250ZXh0ICh3aGVuIGBqID09IDBgKSBpcyBzcGVjaWFsLWNhc2VkIGZvclxuICAgICAgICAgIC8vIHRlbXBsYXRlIGJpbmRpbmdzLiBJZiBhbmQgd2hlbiBob3N0IGJpbmRpbmdzIGFyZSBiZWluZyBwcm9jZXNzZWQgdGhlblxuICAgICAgICAgIC8vIHRoZSBmaXJzdCBjb2x1bW4gd2lsbCBzdGlsbCBiZSBpdGVyYXRlZCBvdmVyLCBidXQgdGhlIHZhbHVlcyB3aWxsIG9ubHlcbiAgICAgICAgICAvLyBiZSBjaGVja2VkIGFnYWluc3QgKG5vdCBhcHBsaWVkKS4gSWYgYW5kIHdoZW4gdGhpcyBoYXBwZW5zIHdlIG5lZWQgdG9cbiAgICAgICAgICAvLyBub3RpZnkgdGhlIG1hcC1iYXNlZCBzeW5jaW5nIGNvZGUgdG8ga25vdyBub3QgdG8gYXBwbHkgdGhlIHZhbHVlcyBpdFxuICAgICAgICAgIC8vIGNvbWVzIGFjcm9zcyBpbiB0aGUgdmVyeSBmaXJzdCBtYXAtYmFzZWQgYmluZGluZyAod2hpY2ggaXMgYWxzbyBsb2NhdGVkXG4gICAgICAgICAgLy8gaW4gY29sdW1uIHplcm8pLlxuICAgICAgICAgIGlmIChob3N0QmluZGluZ3NNb2RlICYmIGogPT09IDApIHtcbiAgICAgICAgICAgIG1vZGUgfD0gU3R5bGluZ01hcHNTeW5jTW9kZS5DaGVja1ZhbHVlc09ubHk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgdmFsdWVBcHBsaWVkV2l0aGluTWFwID0gc3R5bGluZ01hcHNTeW5jRm4oXG4gICAgICAgICAgICAgIGNvbnRleHQsIHJlbmRlcmVyLCBlbGVtZW50LCBiaW5kaW5nRGF0YSwgaiwgYXBwbHlTdHlsaW5nRm4sIHNhbml0aXplciwgbW9kZSwgcHJvcCxcbiAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICB2YWx1ZUFwcGxpZWQgPSB2YWx1ZUFwcGxpZWQgfHwgdmFsdWVBcHBsaWVkV2l0aGluTWFwO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFBhcnQgMzogYXBwbHkgdGhlIGRlZmF1bHQgdmFsdWUgKGUuZy4gYDxkaXYgc3R5bGU9XCJ3aWR0aDoyMDBcIj5gID0+IGAyMDBweGAgZ2V0cyBhcHBsaWVkKVxuICAgICAgLy8gaWYgdGhlIHZhbHVlIGhhcyBub3QgeWV0IGJlZW4gYXBwbGllZCB0aGVuIGEgdHJ1dGh5IHZhbHVlIGRvZXMgbm90IGV4aXN0IGluIHRoZVxuICAgICAgLy8gcHJvcC1iYXNlZCBvciBtYXAtYmFzZWQgYmluZGluZ3MgY29kZS4gSWYgYW5kIHdoZW4gdGhpcyBoYXBwZW5zLCBqdXN0IGFwcGx5IHRoZVxuICAgICAgLy8gZGVmYXVsdCB2YWx1ZSAoZXZlbiBpZiB0aGUgZGVmYXVsdCB2YWx1ZSBpcyBgbnVsbGApLlxuICAgICAgaWYgKCF2YWx1ZUFwcGxpZWQpIHtcbiAgICAgICAgYXBwbHlTdHlsaW5nRm4ocmVuZGVyZXIsIGVsZW1lbnQsIHByb3AsIGRlZmF1bHRWYWx1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaSArPSBUU3R5bGluZ0NvbnRleHRJbmRleC5CaW5kaW5nc1N0YXJ0T2Zmc2V0ICsgdmFsdWVzQ291bnQ7XG4gIH1cblxuICAvLyB0aGUgbWFwLWJhc2VkIHN0eWxpbmcgZW50cmllcyBtYXkgaGF2ZSBub3QgYXBwbGllZCBhbGwgdGhlaXJcbiAgLy8gdmFsdWVzLiBGb3IgdGhpcyByZWFzb24sIG9uZSBtb3JlIGNhbGwgdG8gdGhlIHN5bmMgZnVuY3Rpb25cbiAgLy8gbmVlZHMgdG8gYmUgaXNzdWVkIGF0IHRoZSBlbmQuXG4gIGlmIChzdHlsaW5nTWFwc1N5bmNGbikge1xuICAgIGlmIChob3N0QmluZGluZ3NNb2RlKSB7XG4gICAgICBtYXBzTW9kZSB8PSBTdHlsaW5nTWFwc1N5bmNNb2RlLkNoZWNrVmFsdWVzT25seTtcbiAgICB9XG4gICAgc3R5bGluZ01hcHNTeW5jRm4oXG4gICAgICAgIGNvbnRleHQsIHJlbmRlcmVyLCBlbGVtZW50LCBiaW5kaW5nRGF0YSwgMCwgYXBwbHlTdHlsaW5nRm4sIHNhbml0aXplciwgbWFwc01vZGUpO1xuICB9XG59XG5cbi8qKlxuICogQXBwbGllcyB0aGUgcHJvdmlkZWQgc3R5bGluZyBtYXAgdG8gdGhlIGVsZW1lbnQgZGlyZWN0bHkgKHdpdGhvdXQgY29udGV4dCByZXNvbHV0aW9uKS5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGRlc2lnbmVkIHRvIGJlIHJ1biBmcm9tIHRoZSBzdHlsaW5nIGluc3RydWN0aW9ucyBhbmQgd2lsbCBiZSBjYWxsZWRcbiAqIGF1dG9tYXRpY2FsbHkuIFRoaXMgZnVuY3Rpb24gaXMgaW50ZW5kZWQgdG8gYmUgdXNlZCBmb3IgcGVyZm9ybWFuY2UgcmVhc29ucyBpbiB0aGVcbiAqIGV2ZW50IHRoYXQgdGhlcmUgaXMgbm8gbmVlZCB0byBhcHBseSBzdHlsaW5nIHZpYSBjb250ZXh0IHJlc29sdXRpb24uXG4gKlxuICogVGhpcyBmdW5jdGlvbiBoYXMgdGhyZWUgZGlmZmVyZW50IGNhc2VzIHRoYXQgY2FuIG9jY3VyIChmb3IgZWFjaCBpdGVtIGluIHRoZSBtYXApOlxuICpcbiAqIC0gQ2FzZSAxOiBBdHRlbXB0IHRvIGFwcGx5IHRoZSBjdXJyZW50IHZhbHVlIGluIHRoZSBtYXAgdG8gdGhlIGVsZW1lbnQgKGlmIGl0J3MgYG5vbiBudWxsYCkuXG4gKlxuICogLSBDYXNlIDI6IElmIGEgbWFwIHZhbHVlIGZhaWxzIHRvIGJlIGFwcGxpZWQgdGhlbiB0aGUgYWxnb3JpdGhtIHdpbGwgZmluZCBhIG1hdGNoaW5nIGVudHJ5IGluXG4gKiAgICAgICAgICAgdGhlIGluaXRpYWwgdmFsdWVzIHByZXNlbnQgaW4gdGhlIGNvbnRleHQgYW5kIGF0dGVtcHQgdG8gYXBwbHkgdGhhdC5cbiAqXG4gKiAtIERlZmF1bHQgQ2FzZTogSWYgdGhlIGluaXRpYWwgdmFsdWUgY2Fubm90IGJlIGFwcGxpZWQgdGhlbiBhIGRlZmF1bHQgdmFsdWUgb2YgYG51bGxgIHdpbGwgYmVcbiAqICAgICAgICAgICAgICAgICBhcHBsaWVkICh3aGljaCB3aWxsIHJlbW92ZSB0aGUgc3R5bGUvY2xhc3MgdmFsdWUgZnJvbSB0aGUgZWxlbWVudCkuXG4gKlxuICogU2VlIGBhbGxvd0RpcmVjdFN0eWxpbmdBcHBseWAgdG8gbGVhcm4gdGhlIGxvZ2ljIHVzZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgYW55IHN0eWxlL2NsYXNzXG4gKiBiaW5kaW5ncyBjYW4gYmUgZGlyZWN0bHkgYXBwbGllZC5cbiAqXG4gKiBAcmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgc3R5bGluZyBtYXAgd2FzIGFwcGxpZWQgdG8gdGhlIGVsZW1lbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVN0eWxpbmdNYXBEaXJlY3RseShcbiAgICByZW5kZXJlcjogYW55LCBjb250ZXh0OiBUU3R5bGluZ0NvbnRleHQsIHROb2RlOiBUU3R5bGluZ05vZGUsIGVsZW1lbnQ6IFJFbGVtZW50LFxuICAgIGRhdGE6IExTdHlsaW5nRGF0YSwgYmluZGluZ0luZGV4OiBudW1iZXIsIHZhbHVlOiB7W2tleTogc3RyaW5nXTogYW55fSB8IHN0cmluZyB8IG51bGwsXG4gICAgaXNDbGFzc0Jhc2VkOiBib29sZWFuLCBzYW5pdGl6ZXI6IFN0eWxlU2FuaXRpemVGbiB8IG51bGwsIGZvcmNlVXBkYXRlOiBib29sZWFuLFxuICAgIGJpbmRpbmdWYWx1ZUNvbnRhaW5zSW5pdGlhbDogYm9vbGVhbik6IHZvaWQge1xuICBjb25zdCBvbGRWYWx1ZSA9IGdldFZhbHVlKGRhdGEsIGJpbmRpbmdJbmRleCk7XG4gIGlmIChmb3JjZVVwZGF0ZSB8fCBoYXNWYWx1ZUNoYW5nZWQob2xkVmFsdWUsIHZhbHVlKSkge1xuICAgIGNvbnN0IGhhc0luaXRpYWwgPSBoYXNDb25maWcodE5vZGUsIFROb2RlRmxhZ3MuaGFzSW5pdGlhbFN0eWxpbmcpO1xuICAgIGNvbnN0IGluaXRpYWxWYWx1ZSA9XG4gICAgICAgIGhhc0luaXRpYWwgJiYgIWJpbmRpbmdWYWx1ZUNvbnRhaW5zSW5pdGlhbCA/IGdldEluaXRpYWxTdHlsaW5nVmFsdWUoY29udGV4dCkgOiBudWxsO1xuICAgIHNldFZhbHVlKGRhdGEsIGJpbmRpbmdJbmRleCwgdmFsdWUpO1xuXG4gICAgLy8gdGhlIGNhY2hlZCB2YWx1ZSBpcyB0aGUgbGFzdCBzbmFwc2hvdCBvZiB0aGUgc3R5bGUgb3IgY2xhc3NcbiAgICAvLyBhdHRyaWJ1dGUgdmFsdWUgYW5kIGlzIHVzZWQgaW4gdGhlIGlmIHN0YXRlbWVudCBiZWxvdyB0b1xuICAgIC8vIGtlZXAgdHJhY2sgb2YgaW50ZXJuYWwvZXh0ZXJuYWwgY2hhbmdlcy5cbiAgICBjb25zdCBjYWNoZWRWYWx1ZUluZGV4ID0gYmluZGluZ0luZGV4ICsgMTtcbiAgICBsZXQgY2FjaGVkVmFsdWUgPSBnZXRWYWx1ZShkYXRhLCBjYWNoZWRWYWx1ZUluZGV4KTtcbiAgICBpZiAoY2FjaGVkVmFsdWUgPT09IE5PX0NIQU5HRSkge1xuICAgICAgY2FjaGVkVmFsdWUgPSBpbml0aWFsVmFsdWU7XG4gICAgfVxuICAgIGNhY2hlZFZhbHVlID0gdHlwZW9mIGNhY2hlZFZhbHVlICE9PSAnc3RyaW5nJyA/ICcnIDogY2FjaGVkVmFsdWU7XG5cbiAgICAvLyBJZiBhIGNsYXNzL3N0eWxlIHZhbHVlIHdhcyBtb2RpZmllZCBleHRlcm5hbGx5IHRoZW4gdGhlIHN0eWxpbmdcbiAgICAvLyBmYXN0IHBhc3MgY2Fubm90IGd1YXJhbnRlZSB0aGF0IHRoZSBleHRlcm5hbCB2YWx1ZXMgYXJlIHJldGFpbmVkLlxuICAgIC8vIFdoZW4gdGhpcyBoYXBwZW5zLCB0aGUgYWxnb3JpdGhtIHdpbGwgYmFpbCBvdXQgYW5kIG5vdCB3cml0ZSB0b1xuICAgIC8vIHRoZSBzdHlsZSBvciBjbGFzc05hbWUgYXR0cmlidXRlIGRpcmVjdGx5LlxuICAgIGNvbnN0IHByb3BCaW5kaW5nc0ZsYWcgPVxuICAgICAgICBpc0NsYXNzQmFzZWQgPyBUTm9kZUZsYWdzLmhhc0NsYXNzUHJvcEJpbmRpbmdzIDogVE5vZGVGbGFncy5oYXNTdHlsZVByb3BCaW5kaW5ncztcbiAgICBsZXQgd3JpdGVUb0F0dHJEaXJlY3RseSA9ICFoYXNDb25maWcodE5vZGUsIHByb3BCaW5kaW5nc0ZsYWcpO1xuICAgIGlmICh3cml0ZVRvQXR0ckRpcmVjdGx5ICYmXG4gICAgICAgIGNoZWNrSWZFeHRlcm5hbGx5TW9kaWZpZWQoZWxlbWVudCBhcyBIVE1MRWxlbWVudCwgY2FjaGVkVmFsdWUsIGlzQ2xhc3NCYXNlZCkpIHtcbiAgICAgIHdyaXRlVG9BdHRyRGlyZWN0bHkgPSBmYWxzZTtcbiAgICAgIGlmIChvbGRWYWx1ZSAhPT0gVkFMVUVfSVNfRVhURVJOQUxMWV9NT0RJRklFRCkge1xuICAgICAgICAvLyBkaXJlY3Qgc3R5bGluZyB3aWxsIHJlc2V0IHRoZSBhdHRyaWJ1dGUgZW50aXJlbHkgZWFjaCB0aW1lLFxuICAgICAgICAvLyBhbmQsIGZvciB0aGlzIHJlYXNvbiwgaWYgdGhlIGFsZ29yaXRobSBkZWNpZGVzIGl0IGNhbm5vdFxuICAgICAgICAvLyB3cml0ZSB0byB0aGUgY2xhc3Mvc3R5bGUgYXR0cmlidXRlcyBkaXJlY3RseSB0aGVuIGl0IG11c3RcbiAgICAgICAgLy8gcmVzZXQgYWxsIHRoZSBwcmV2aW91cyBzdHlsZS9jbGFzcyB2YWx1ZXMgYmVmb3JlIGl0IHN0YXJ0c1xuICAgICAgICAvLyB0byBhcHBseSB2YWx1ZXMgaW4gdGhlIG5vbi1kaXJlY3Qgd2F5LlxuICAgICAgICByZW1vdmVTdHlsaW5nVmFsdWVzKHJlbmRlcmVyLCBlbGVtZW50LCBvbGRWYWx1ZSwgaXNDbGFzc0Jhc2VkKTtcblxuICAgICAgICAvLyB0aGlzIHdpbGwgaW5zdHJ1Y3QgdGhlIGFsZ29yaXRobSBub3QgdG8gYXBwbHkgY2xhc3Mgb3Igc3R5bGVcbiAgICAgICAgLy8gdmFsdWVzIGRpcmVjdGx5IGFueW1vcmUuXG4gICAgICAgIHNldFZhbHVlKGRhdGEsIGNhY2hlZFZhbHVlSW5kZXgsIFZBTFVFX0lTX0VYVEVSTkFMTFlfTU9ESUZJRUQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh3cml0ZVRvQXR0ckRpcmVjdGx5KSB7XG4gICAgICBjb25zdCBpbml0aWFsVmFsdWUgPVxuICAgICAgICAgIGhhc0luaXRpYWwgJiYgIWJpbmRpbmdWYWx1ZUNvbnRhaW5zSW5pdGlhbCA/IGdldEluaXRpYWxTdHlsaW5nVmFsdWUoY29udGV4dCkgOiBudWxsO1xuICAgICAgY29uc3QgdmFsdWVUb0FwcGx5ID1cbiAgICAgICAgICB3cml0ZVN0eWxpbmdWYWx1ZURpcmVjdGx5KHJlbmRlcmVyLCBlbGVtZW50LCB2YWx1ZSwgaXNDbGFzc0Jhc2VkLCBpbml0aWFsVmFsdWUpO1xuICAgICAgc2V0VmFsdWUoZGF0YSwgY2FjaGVkVmFsdWVJbmRleCwgdmFsdWVUb0FwcGx5IHx8IG51bGwpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBhcHBseUZuID0gaXNDbGFzc0Jhc2VkID8gc2V0Q2xhc3MgOiBzZXRTdHlsZTtcbiAgICAgIGNvbnN0IG1hcCA9IG5vcm1hbGl6ZUludG9TdHlsaW5nTWFwKG9sZFZhbHVlLCB2YWx1ZSwgIWlzQ2xhc3NCYXNlZCk7XG4gICAgICBjb25zdCBpbml0aWFsU3R5bGVzID0gaGFzSW5pdGlhbCA/IGdldFN0eWxpbmdNYXBBcnJheShjb250ZXh0KSA6IG51bGw7XG5cbiAgICAgIGZvciAobGV0IGkgPSBTdHlsaW5nTWFwQXJyYXlJbmRleC5WYWx1ZXNTdGFydFBvc2l0aW9uOyBpIDwgbWFwLmxlbmd0aDtcbiAgICAgICAgICAgaSArPSBTdHlsaW5nTWFwQXJyYXlJbmRleC5UdXBsZVNpemUpIHtcbiAgICAgICAgY29uc3QgcHJvcCA9IGdldE1hcFByb3AobWFwLCBpKTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBnZXRNYXBWYWx1ZShtYXAsIGkpO1xuXG4gICAgICAgIC8vIGNhc2UgMTogYXBwbHkgdGhlIG1hcCB2YWx1ZSAoaWYgaXQgZXhpc3RzKVxuICAgICAgICBsZXQgYXBwbGllZCA9XG4gICAgICAgICAgICBhcHBseVN0eWxpbmdWYWx1ZShyZW5kZXJlciwgZWxlbWVudCwgcHJvcCwgdmFsdWUsIGFwcGx5Rm4sIGJpbmRpbmdJbmRleCwgc2FuaXRpemVyKTtcblxuICAgICAgICAvLyBjYXNlIDI6IGFwcGx5IHRoZSBpbml0aWFsIHZhbHVlIChpZiBpdCBleGlzdHMpXG4gICAgICAgIGlmICghYXBwbGllZCAmJiBpbml0aWFsU3R5bGVzKSB7XG4gICAgICAgICAgYXBwbGllZCA9IGZpbmRBbmRBcHBseU1hcFZhbHVlKFxuICAgICAgICAgICAgICByZW5kZXJlciwgZWxlbWVudCwgYXBwbHlGbiwgaW5pdGlhbFN0eWxlcywgcHJvcCwgYmluZGluZ0luZGV4LCBzYW5pdGl6ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZGVmYXVsdCBjYXNlOiBhcHBseSBgbnVsbGAgdG8gcmVtb3ZlIHRoZSB2YWx1ZVxuICAgICAgICBpZiAoIWFwcGxpZWQpIHtcbiAgICAgICAgICBhcHBseUZuKHJlbmRlcmVyLCBlbGVtZW50LCBwcm9wLCBudWxsLCBiaW5kaW5nSW5kZXgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN0YXRlID0gZ2V0U3R5bGluZ1N0YXRlKGVsZW1lbnQsIFRFTVBMQVRFX0RJUkVDVElWRV9JTkRFWCk7XG4gICAgICBpZiAoaXNDbGFzc0Jhc2VkKSB7XG4gICAgICAgIHN0YXRlLmxhc3REaXJlY3RDbGFzc01hcCA9IG1hcDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0YXRlLmxhc3REaXJlY3RTdHlsZU1hcCA9IG1hcDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlU3R5bGluZ1ZhbHVlRGlyZWN0bHkoXG4gICAgcmVuZGVyZXI6IGFueSwgZWxlbWVudDogUkVsZW1lbnQsIHZhbHVlOiB7W2tleTogc3RyaW5nXTogYW55fSB8IHN0cmluZyB8IG51bGwsXG4gICAgaXNDbGFzc0Jhc2VkOiBib29sZWFuLCBpbml0aWFsVmFsdWU6IHN0cmluZyB8IG51bGwpOiBzdHJpbmcge1xuICBsZXQgdmFsdWVUb0FwcGx5OiBzdHJpbmc7XG4gIGlmIChpc0NsYXNzQmFzZWQpIHtcbiAgICB2YWx1ZVRvQXBwbHkgPSB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnID8gdmFsdWUgOiBvYmplY3RUb0NsYXNzTmFtZSh2YWx1ZSk7XG4gICAgaWYgKGluaXRpYWxWYWx1ZSAhPT0gbnVsbCkge1xuICAgICAgdmFsdWVUb0FwcGx5ID0gY29uY2F0U3RyaW5nKGluaXRpYWxWYWx1ZSwgdmFsdWVUb0FwcGx5LCAnICcpO1xuICAgIH1cbiAgICBzZXRDbGFzc05hbWUocmVuZGVyZXIsIGVsZW1lbnQsIHZhbHVlVG9BcHBseSk7XG4gIH0gZWxzZSB7XG4gICAgdmFsdWVUb0FwcGx5ID0gZm9yY2VTdHlsZXNBc1N0cmluZyh2YWx1ZSwgdHJ1ZSk7XG4gICAgaWYgKGluaXRpYWxWYWx1ZSAhPT0gbnVsbCkge1xuICAgICAgdmFsdWVUb0FwcGx5ID0gaW5pdGlhbFZhbHVlICsgJzsnICsgdmFsdWVUb0FwcGx5O1xuICAgIH1cbiAgICBzZXRTdHlsZUF0dHIocmVuZGVyZXIsIGVsZW1lbnQsIHZhbHVlVG9BcHBseSk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlVG9BcHBseTtcbn1cblxuLyoqXG4gKiBBcHBsaWVzIHRoZSBwcm92aWRlZCBzdHlsaW5nIHByb3AvdmFsdWUgdG8gdGhlIGVsZW1lbnQgZGlyZWN0bHkgKHdpdGhvdXQgY29udGV4dCByZXNvbHV0aW9uKS5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGRlc2lnbmVkIHRvIGJlIHJ1biBmcm9tIHRoZSBzdHlsaW5nIGluc3RydWN0aW9ucyBhbmQgd2lsbCBiZSBjYWxsZWRcbiAqIGF1dG9tYXRpY2FsbHkuIFRoaXMgZnVuY3Rpb24gaXMgaW50ZW5kZWQgdG8gYmUgdXNlZCBmb3IgcGVyZm9ybWFuY2UgcmVhc29ucyBpbiB0aGVcbiAqIGV2ZW50IHRoYXQgdGhlcmUgaXMgbm8gbmVlZCB0byBhcHBseSBzdHlsaW5nIHZpYSBjb250ZXh0IHJlc29sdXRpb24uXG4gKlxuICogVGhpcyBmdW5jdGlvbiBoYXMgZm91ciBkaWZmZXJlbnQgY2FzZXMgdGhhdCBjYW4gb2NjdXI6XG4gKlxuICogLSBDYXNlIDE6IEFwcGx5IHRoZSBwcm92aWRlZCBwcm9wL3ZhbHVlIChzdHlsZSBvciBjbGFzcykgZW50cnkgdG8gdGhlIGVsZW1lbnRcbiAqICAgICAgICAgICAoaWYgaXQgaXMgYG5vbiBudWxsYCkuXG4gKlxuICogLSBDYXNlIDI6IElmIHZhbHVlIGRvZXMgbm90IGdldCBhcHBsaWVkIChiZWNhdXNlIGl0cyBgbnVsbGAgb3IgYHVuZGVmaW5lZGApIHRoZW4gdGhlIGFsZ29yaXRobVxuICogICAgICAgICAgIHdpbGwgY2hlY2sgdG8gc2VlIGlmIGEgc3R5bGluZyBtYXAgdmFsdWUgd2FzIGFwcGxpZWQgdG8gdGhlIGVsZW1lbnQgYXMgd2VsbCBqdXN0XG4gKiAgICAgICAgICAgYmVmb3JlIHRoaXMgKHZpYSBgc3R5bGVNYXBgIG9yIGBjbGFzc01hcGApLiBJZiBhbmQgd2hlbiBhIG1hcCBpcyBwcmVzZW50IHRoZW4gdGhlXG4gICogICAgICAgICAgYWxnb3JpdGhtIHdpbGwgZmluZCB0aGUgbWF0Y2hpbmcgcHJvcGVydHkgaW4gdGhlIG1hcCBhbmQgYXBwbHkgaXRzIHZhbHVlLlxuICAqXG4gKiAtIENhc2UgMzogSWYgYSBtYXAgdmFsdWUgZmFpbHMgdG8gYmUgYXBwbGllZCB0aGVuIHRoZSBhbGdvcml0aG0gd2lsbCBjaGVjayB0byBzZWUgaWYgdGhlcmVcbiAqICAgICAgICAgICBhcmUgYW55IGluaXRpYWwgdmFsdWVzIHByZXNlbnQgYW5kIGF0dGVtcHQgdG8gYXBwbHkgYSBtYXRjaGluZyB2YWx1ZSBiYXNlZCBvblxuICogICAgICAgICAgIHRoZSB0YXJnZXQgcHJvcC5cbiAqXG4gKiAtIERlZmF1bHQgQ2FzZTogSWYgYSBtYXRjaGluZyBpbml0aWFsIHZhbHVlIGNhbm5vdCBiZSBhcHBsaWVkIHRoZW4gYSBkZWZhdWx0IHZhbHVlXG4gKiAgICAgICAgICAgICAgICAgb2YgYG51bGxgIHdpbGwgYmUgYXBwbGllZCAod2hpY2ggd2lsbCByZW1vdmUgdGhlIHN0eWxlL2NsYXNzIHZhbHVlXG4gKiAgICAgICAgICAgICAgICAgZnJvbSB0aGUgZWxlbWVudCkuXG4gKlxuICogU2VlIGBhbGxvd0RpcmVjdFN0eWxpbmdBcHBseWAgdG8gbGVhcm4gdGhlIGxvZ2ljIHVzZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgYW55IHN0eWxlL2NsYXNzXG4gKiBiaW5kaW5ncyBjYW4gYmUgZGlyZWN0bHkgYXBwbGllZC5cbiAqXG4gKiBAcmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgcHJvcC92YWx1ZSBzdHlsaW5nIHdhcyBhcHBsaWVkIHRvIHRoZSBlbGVtZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlTdHlsaW5nVmFsdWVEaXJlY3RseShcbiAgICByZW5kZXJlcjogYW55LCBjb250ZXh0OiBUU3R5bGluZ0NvbnRleHQsIHROb2RlOiBUU3R5bGluZ05vZGUsIGVsZW1lbnQ6IFJFbGVtZW50LFxuICAgIGRhdGE6IExTdHlsaW5nRGF0YSwgYmluZGluZ0luZGV4OiBudW1iZXIsIHByb3A6IHN0cmluZywgdmFsdWU6IGFueSwgaXNDbGFzc0Jhc2VkOiBib29sZWFuLFxuICAgIHNhbml0aXplcj86IFN0eWxlU2FuaXRpemVGbiB8IG51bGwpOiBib29sZWFuIHtcbiAgbGV0IGFwcGxpZWQgPSBmYWxzZTtcbiAgaWYgKGhhc1ZhbHVlQ2hhbmdlZChkYXRhW2JpbmRpbmdJbmRleF0sIHZhbHVlKSkge1xuICAgIHNldFZhbHVlKGRhdGEsIGJpbmRpbmdJbmRleCwgdmFsdWUpO1xuICAgIGNvbnN0IGFwcGx5Rm4gPSBpc0NsYXNzQmFzZWQgPyBzZXRDbGFzcyA6IHNldFN0eWxlO1xuXG4gICAgLy8gY2FzZSAxOiBhcHBseSB0aGUgcHJvdmlkZWQgdmFsdWUgKGlmIGl0IGV4aXN0cylcbiAgICBhcHBsaWVkID0gYXBwbHlTdHlsaW5nVmFsdWUocmVuZGVyZXIsIGVsZW1lbnQsIHByb3AsIHZhbHVlLCBhcHBseUZuLCBiaW5kaW5nSW5kZXgsIHNhbml0aXplcik7XG5cbiAgICAvLyBjYXNlIDI6IGZpbmQgdGhlIG1hdGNoaW5nIHByb3BlcnR5IGluIGEgc3R5bGluZyBtYXAgYW5kIGFwcGx5IHRoZSBkZXRlY3RlZCB2YWx1ZVxuICAgIGNvbnN0IG1hcEJpbmRpbmdzRmxhZyA9XG4gICAgICAgIGlzQ2xhc3NCYXNlZCA/IFROb2RlRmxhZ3MuaGFzQ2xhc3NNYXBCaW5kaW5ncyA6IFROb2RlRmxhZ3MuaGFzU3R5bGVNYXBCaW5kaW5ncztcbiAgICBpZiAoIWFwcGxpZWQgJiYgaGFzQ29uZmlnKHROb2RlLCBtYXBCaW5kaW5nc0ZsYWcpKSB7XG4gICAgICBjb25zdCBzdGF0ZSA9IGdldFN0eWxpbmdTdGF0ZShlbGVtZW50LCBURU1QTEFURV9ESVJFQ1RJVkVfSU5ERVgpO1xuICAgICAgY29uc3QgbWFwID0gaXNDbGFzc0Jhc2VkID8gc3RhdGUubGFzdERpcmVjdENsYXNzTWFwIDogc3RhdGUubGFzdERpcmVjdFN0eWxlTWFwO1xuICAgICAgYXBwbGllZCA9IG1hcCA/XG4gICAgICAgICAgZmluZEFuZEFwcGx5TWFwVmFsdWUocmVuZGVyZXIsIGVsZW1lbnQsIGFwcGx5Rm4sIG1hcCwgcHJvcCwgYmluZGluZ0luZGV4LCBzYW5pdGl6ZXIpIDpcbiAgICAgICAgICBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBjYXNlIDM6IGFwcGx5IHRoZSBpbml0aWFsIHZhbHVlIChpZiBpdCBleGlzdHMpXG4gICAgaWYgKCFhcHBsaWVkICYmIGhhc0NvbmZpZyh0Tm9kZSwgVE5vZGVGbGFncy5oYXNJbml0aWFsU3R5bGluZykpIHtcbiAgICAgIGNvbnN0IG1hcCA9IGdldFN0eWxpbmdNYXBBcnJheShjb250ZXh0KTtcbiAgICAgIGFwcGxpZWQgPVxuICAgICAgICAgIG1hcCA/IGZpbmRBbmRBcHBseU1hcFZhbHVlKHJlbmRlcmVyLCBlbGVtZW50LCBhcHBseUZuLCBtYXAsIHByb3AsIGJpbmRpbmdJbmRleCkgOiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBkZWZhdWx0IGNhc2U6IGFwcGx5IGBudWxsYCB0byByZW1vdmUgdGhlIHZhbHVlXG4gICAgaWYgKCFhcHBsaWVkKSB7XG4gICAgICBhcHBseUZuKHJlbmRlcmVyLCBlbGVtZW50LCBwcm9wLCBudWxsLCBiaW5kaW5nSW5kZXgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gYXBwbGllZDtcbn1cblxuZnVuY3Rpb24gYXBwbHlTdHlsaW5nVmFsdWUoXG4gICAgcmVuZGVyZXI6IGFueSwgZWxlbWVudDogUkVsZW1lbnQsIHByb3A6IHN0cmluZywgdmFsdWU6IGFueSwgYXBwbHlGbjogQXBwbHlTdHlsaW5nRm4sXG4gICAgYmluZGluZ0luZGV4OiBudW1iZXIsIHNhbml0aXplcj86IFN0eWxlU2FuaXRpemVGbiB8IG51bGwpOiBib29sZWFuIHtcbiAgbGV0IHZhbHVlVG9BcHBseTogc3RyaW5nfG51bGwgPSB1bndyYXBTYWZlVmFsdWUodmFsdWUpO1xuICBpZiAoaXNTdHlsaW5nVmFsdWVEZWZpbmVkKHZhbHVlVG9BcHBseSkpIHtcbiAgICB2YWx1ZVRvQXBwbHkgPVxuICAgICAgICBzYW5pdGl6ZXIgPyBzYW5pdGl6ZXIocHJvcCwgdmFsdWUsIFN0eWxlU2FuaXRpemVNb2RlLlZhbGlkYXRlQW5kU2FuaXRpemUpIDogdmFsdWVUb0FwcGx5O1xuICAgIGFwcGx5Rm4ocmVuZGVyZXIsIGVsZW1lbnQsIHByb3AsIHZhbHVlVG9BcHBseSwgYmluZGluZ0luZGV4KTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGZpbmRBbmRBcHBseU1hcFZhbHVlKFxuICAgIHJlbmRlcmVyOiBhbnksIGVsZW1lbnQ6IFJFbGVtZW50LCBhcHBseUZuOiBBcHBseVN0eWxpbmdGbiwgbWFwOiBTdHlsaW5nTWFwQXJyYXksIHByb3A6IHN0cmluZyxcbiAgICBiaW5kaW5nSW5kZXg6IG51bWJlciwgc2FuaXRpemVyPzogU3R5bGVTYW5pdGl6ZUZuIHwgbnVsbCkge1xuICBmb3IgKGxldCBpID0gU3R5bGluZ01hcEFycmF5SW5kZXguVmFsdWVzU3RhcnRQb3NpdGlvbjsgaSA8IG1hcC5sZW5ndGg7XG4gICAgICAgaSArPSBTdHlsaW5nTWFwQXJyYXlJbmRleC5UdXBsZVNpemUpIHtcbiAgICBjb25zdCBwID0gZ2V0TWFwUHJvcChtYXAsIGkpO1xuICAgIGlmIChwID09PSBwcm9wKSB7XG4gICAgICBsZXQgdmFsdWVUb0FwcGx5ID0gZ2V0TWFwVmFsdWUobWFwLCBpKTtcbiAgICAgIHZhbHVlVG9BcHBseSA9IHNhbml0aXplciA/XG4gICAgICAgICAgc2FuaXRpemVyKHByb3AsIHZhbHVlVG9BcHBseSwgU3R5bGVTYW5pdGl6ZU1vZGUuVmFsaWRhdGVBbmRTYW5pdGl6ZSkgOlxuICAgICAgICAgIHZhbHVlVG9BcHBseTtcbiAgICAgIGFwcGx5Rm4ocmVuZGVyZXIsIGVsZW1lbnQsIHByb3AsIHZhbHVlVG9BcHBseSwgYmluZGluZ0luZGV4KTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAocCA+IHByb3ApIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZUJpdE1hc2tWYWx1ZSh2YWx1ZTogbnVtYmVyIHwgYm9vbGVhbik6IG51bWJlciB7XG4gIC8vIGlmIHBhc3MgPT4gYXBwbHkgYWxsIHZhbHVlcyAoLTEgaW1wbGllcyB0aGF0IGFsbCBiaXRzIGFyZSBmbGlwcGVkIHRvIHRydWUpXG4gIGlmICh2YWx1ZSA9PT0gdHJ1ZSkgcmV0dXJuIC0xO1xuXG4gIC8vIGlmIHBhc3MgPT4gc2tpcCBhbGwgdmFsdWVzXG4gIGlmICh2YWx1ZSA9PT0gZmFsc2UpIHJldHVybiAwO1xuXG4gIC8vIHJldHVybiB0aGUgYml0IG1hc2sgdmFsdWUgYXMgaXNcbiAgcmV0dXJuIHZhbHVlO1xufVxuXG5sZXQgX2FjdGl2ZVN0eWxpbmdNYXBBcHBseUZuOiBTeW5jU3R5bGluZ01hcHNGbnxudWxsID0gbnVsbDtcbmV4cG9ydCBmdW5jdGlvbiBnZXRTdHlsaW5nTWFwc1N5bmNGbigpIHtcbiAgcmV0dXJuIF9hY3RpdmVTdHlsaW5nTWFwQXBwbHlGbjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldFN0eWxpbmdNYXBzU3luY0ZuKGZuOiBTeW5jU3R5bGluZ01hcHNGbikge1xuICBfYWN0aXZlU3R5bGluZ01hcEFwcGx5Rm4gPSBmbjtcbn1cblxuLyoqXG4gKiBBc3NpZ25zIGEgc3R5bGUgdmFsdWUgdG8gYSBzdHlsZSBwcm9wZXJ0eSBmb3IgdGhlIGdpdmVuIGVsZW1lbnQuXG4gKi9cbmV4cG9ydCBjb25zdCBzZXRTdHlsZTogQXBwbHlTdHlsaW5nRm4gPVxuICAgIChyZW5kZXJlcjogUmVuZGVyZXIzIHwgbnVsbCwgbmF0aXZlOiBSRWxlbWVudCwgcHJvcDogc3RyaW5nLCB2YWx1ZTogc3RyaW5nIHwgbnVsbCkgPT4ge1xuICAgICAgaWYgKHJlbmRlcmVyICE9PSBudWxsKSB7XG4gICAgICAgIC8vIFVzZSBgaXNTdHlsaW5nVmFsdWVEZWZpbmVkYCB0byBhY2NvdW50IGZvciBmYWxzeSB2YWx1ZXMgdGhhdCBzaG91bGQgYmUgYm91bmQgbGlrZSAwLlxuICAgICAgICBpZiAoaXNTdHlsaW5nVmFsdWVEZWZpbmVkKHZhbHVlKSkge1xuICAgICAgICAgIC8vIG9wYWNpdHksIHotaW5kZXggYW5kIGZsZXhib3ggYWxsIGhhdmUgbnVtYmVyIHZhbHVlc1xuICAgICAgICAgIC8vIGFuZCB0aGVzZSBuZWVkIHRvIGJlIGNvbnZlcnRlZCBpbnRvIHN0cmluZ3Mgc28gdGhhdFxuICAgICAgICAgIC8vIHRoZXkgY2FuIGJlIGFzc2lnbmVkIHByb3Blcmx5LlxuICAgICAgICAgIHZhbHVlID0gdmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgICBuZ0Rldk1vZGUgJiYgbmdEZXZNb2RlLnJlbmRlcmVyU2V0U3R5bGUrKztcbiAgICAgICAgICBpZiAoaXNQcm9jZWR1cmFsUmVuZGVyZXIocmVuZGVyZXIpKSB7XG4gICAgICAgICAgICByZW5kZXJlci5zZXRTdHlsZShuYXRpdmUsIHByb3AsIHZhbHVlLCBSZW5kZXJlclN0eWxlRmxhZ3MzLkRhc2hDYXNlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVGhlIHJlYXNvbiB3aHkgbmF0aXZlIHN0eWxlIG1heSBiZSBgbnVsbGAgaXMgZWl0aGVyIGJlY2F1c2VcbiAgICAgICAgICAgIC8vIGl0J3MgYSBjb250YWluZXIgZWxlbWVudCBvciBpdCdzIGEgcGFydCBvZiBhIHRlc3RcbiAgICAgICAgICAgIC8vIGVudmlyb25tZW50IHRoYXQgZG9lc24ndCBoYXZlIHN0eWxpbmcuIEluIGVpdGhlclxuICAgICAgICAgICAgLy8gY2FzZSBpdCdzIHNhZmUgbm90IHRvIGFwcGx5IHN0eWxpbmcgdG8gdGhlIGVsZW1lbnQuXG4gICAgICAgICAgICBjb25zdCBuYXRpdmVTdHlsZSA9IG5hdGl2ZS5zdHlsZTtcbiAgICAgICAgICAgIGlmIChuYXRpdmVTdHlsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgIG5hdGl2ZVN0eWxlLnNldFByb3BlcnR5KHByb3AsIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmdEZXZNb2RlICYmIG5nRGV2TW9kZS5yZW5kZXJlclJlbW92ZVN0eWxlKys7XG5cbiAgICAgICAgICBpZiAoaXNQcm9jZWR1cmFsUmVuZGVyZXIocmVuZGVyZXIpKSB7XG4gICAgICAgICAgICByZW5kZXJlci5yZW1vdmVTdHlsZShuYXRpdmUsIHByb3AsIFJlbmRlcmVyU3R5bGVGbGFnczMuRGFzaENhc2UpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBuYXRpdmVTdHlsZSA9IG5hdGl2ZS5zdHlsZTtcbiAgICAgICAgICAgIGlmIChuYXRpdmVTdHlsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgIG5hdGl2ZVN0eWxlLnJlbW92ZVByb3BlcnR5KHByb3ApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbi8qKlxuICogQWRkcy9yZW1vdmVzIHRoZSBwcm92aWRlZCBjbGFzc05hbWUgdmFsdWUgdG8gdGhlIHByb3ZpZGVkIGVsZW1lbnQuXG4gKi9cbmV4cG9ydCBjb25zdCBzZXRDbGFzczogQXBwbHlTdHlsaW5nRm4gPVxuICAgIChyZW5kZXJlcjogUmVuZGVyZXIzIHwgbnVsbCwgbmF0aXZlOiBSRWxlbWVudCwgY2xhc3NOYW1lOiBzdHJpbmcsIHZhbHVlOiBhbnkpID0+IHtcbiAgICAgIGlmIChyZW5kZXJlciAhPT0gbnVsbCAmJiBjbGFzc05hbWUgIT09ICcnKSB7XG4gICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgIG5nRGV2TW9kZSAmJiBuZ0Rldk1vZGUucmVuZGVyZXJBZGRDbGFzcysrO1xuICAgICAgICAgIGlmIChpc1Byb2NlZHVyYWxSZW5kZXJlcihyZW5kZXJlcikpIHtcbiAgICAgICAgICAgIHJlbmRlcmVyLmFkZENsYXNzKG5hdGl2ZSwgY2xhc3NOYW1lKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdGhlIHJlYXNvbiB3aHkgY2xhc3NMaXN0IG1heSBiZSBgbnVsbGAgaXMgZWl0aGVyIGJlY2F1c2VcbiAgICAgICAgICAgIC8vIGl0J3MgYSBjb250YWluZXIgZWxlbWVudCBvciBpdCdzIGEgcGFydCBvZiBhIHRlc3RcbiAgICAgICAgICAgIC8vIGVudmlyb25tZW50IHRoYXQgZG9lc24ndCBoYXZlIHN0eWxpbmcuIEluIGVpdGhlclxuICAgICAgICAgICAgLy8gY2FzZSBpdCdzIHNhZmUgbm90IHRvIGFwcGx5IHN0eWxpbmcgdG8gdGhlIGVsZW1lbnQuXG4gICAgICAgICAgICBjb25zdCBjbGFzc0xpc3QgPSBuYXRpdmUuY2xhc3NMaXN0O1xuICAgICAgICAgICAgaWYgKGNsYXNzTGlzdCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgIGNsYXNzTGlzdC5hZGQoY2xhc3NOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmdEZXZNb2RlICYmIG5nRGV2TW9kZS5yZW5kZXJlclJlbW92ZUNsYXNzKys7XG4gICAgICAgICAgaWYgKGlzUHJvY2VkdXJhbFJlbmRlcmVyKHJlbmRlcmVyKSkge1xuICAgICAgICAgICAgcmVuZGVyZXIucmVtb3ZlQ2xhc3MobmF0aXZlLCBjbGFzc05hbWUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc0xpc3QgPSBuYXRpdmUuY2xhc3NMaXN0O1xuICAgICAgICAgICAgaWYgKGNsYXNzTGlzdCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgIGNsYXNzTGlzdC5yZW1vdmUoY2xhc3NOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG5leHBvcnQgY29uc3Qgc2V0Q2xhc3NOYW1lID0gKHJlbmRlcmVyOiBSZW5kZXJlcjMgfCBudWxsLCBuYXRpdmU6IFJFbGVtZW50LCBjbGFzc05hbWU6IHN0cmluZykgPT4ge1xuICBpZiAocmVuZGVyZXIgIT09IG51bGwpIHtcbiAgICBpZiAoaXNQcm9jZWR1cmFsUmVuZGVyZXIocmVuZGVyZXIpKSB7XG4gICAgICByZW5kZXJlci5zZXRBdHRyaWJ1dGUobmF0aXZlLCAnY2xhc3MnLCBjbGFzc05hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuYXRpdmUuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHNldFN0eWxlQXR0ciA9IChyZW5kZXJlcjogUmVuZGVyZXIzIHwgbnVsbCwgbmF0aXZlOiBSRWxlbWVudCwgdmFsdWU6IHN0cmluZykgPT4ge1xuICBpZiAocmVuZGVyZXIgIT09IG51bGwpIHtcbiAgICBpZiAoaXNQcm9jZWR1cmFsUmVuZGVyZXIocmVuZGVyZXIpKSB7XG4gICAgICByZW5kZXJlci5zZXRBdHRyaWJ1dGUobmF0aXZlLCAnc3R5bGUnLCB2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5hdGl2ZS5zZXRBdHRyaWJ1dGUoJ3N0eWxlJywgdmFsdWUpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBJdGVyYXRlcyBvdmVyIGFsbCBwcm92aWRlZCBzdHlsaW5nIGVudHJpZXMgYW5kIHJlbmRlcnMgdGhlbSBvbiB0aGUgZWxlbWVudC5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgYWxvbmdzaWRlIGEgYFN0eWxpbmdNYXBBcnJheWAgZW50cnkuIFRoaXMgZW50cnkgaXMgbm90XG4gKiB0aGUgc2FtZSBhcyB0aGUgYFRTdHlsaW5nQ29udGV4dGAgYW5kIGlzIG9ubHkgcmVhbGx5IHVzZWQgd2hlbiBhbiBlbGVtZW50IGNvbnRhaW5zXG4gKiBpbml0aWFsIHN0eWxpbmcgdmFsdWVzIChlLmcuIGA8ZGl2IHN0eWxlPVwid2lkdGg6MjAwcHhcIj5gKSwgYnV0IG5vIHN0eWxlL2NsYXNzIGJpbmRpbmdzXG4gKiBhcmUgcHJlc2VudC4gSWYgYW5kIHdoZW4gdGhhdCBoYXBwZW5zIHRoZW4gdGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCB0byByZW5kZXIgYWxsXG4gKiBpbml0aWFsIHN0eWxpbmcgdmFsdWVzIG9uIGFuIGVsZW1lbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJTdHlsaW5nTWFwKFxuICAgIHJlbmRlcmVyOiBSZW5kZXJlcjMsIGVsZW1lbnQ6IFJFbGVtZW50LCBzdHlsaW5nVmFsdWVzOiBUU3R5bGluZ0NvbnRleHQgfCBTdHlsaW5nTWFwQXJyYXkgfCBudWxsLFxuICAgIGlzQ2xhc3NCYXNlZDogYm9vbGVhbik6IHZvaWQge1xuICBjb25zdCBzdHlsaW5nTWFwQXJyID0gZ2V0U3R5bGluZ01hcEFycmF5KHN0eWxpbmdWYWx1ZXMpO1xuICBpZiAoc3R5bGluZ01hcEFycikge1xuICAgIGZvciAobGV0IGkgPSBTdHlsaW5nTWFwQXJyYXlJbmRleC5WYWx1ZXNTdGFydFBvc2l0aW9uOyBpIDwgc3R5bGluZ01hcEFyci5sZW5ndGg7XG4gICAgICAgICBpICs9IFN0eWxpbmdNYXBBcnJheUluZGV4LlR1cGxlU2l6ZSkge1xuICAgICAgY29uc3QgcHJvcCA9IGdldE1hcFByb3Aoc3R5bGluZ01hcEFyciwgaSk7XG4gICAgICBjb25zdCB2YWx1ZSA9IGdldE1hcFZhbHVlKHN0eWxpbmdNYXBBcnIsIGkpO1xuICAgICAgaWYgKGlzQ2xhc3NCYXNlZCkge1xuICAgICAgICBzZXRDbGFzcyhyZW5kZXJlciwgZWxlbWVudCwgcHJvcCwgdmFsdWUsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2V0U3R5bGUocmVuZGVyZXIsIGVsZW1lbnQsIHByb3AsIHZhbHVlLCBudWxsKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gb2JqZWN0VG9DbGFzc05hbWUob2JqOiB7W2tleTogc3RyaW5nXTogYW55fSB8IG51bGwpOiBzdHJpbmcge1xuICBsZXQgc3RyID0gJyc7XG4gIGlmIChvYmopIHtcbiAgICBmb3IgKGxldCBrZXkgaW4gb2JqKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IG9ialtrZXldO1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHN0ciArPSAoc3RyLmxlbmd0aCA/ICcgJyA6ICcnKSArIGtleTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHN0cjtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmVzIHdoZXRoZXIgb3Igbm90IGFuIGVsZW1lbnQgc3R5bGUvY2xhc3NOYW1lIHZhbHVlIGhhcyBjaGFuZ2VkIHNpbmNlIHRoZSBsYXN0IHVwZGF0ZS5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGhlbHBzIEFuZ3VsYXIgZGV0ZXJtaW5lIGlmIGEgc3R5bGUgb3IgY2xhc3MgYXR0cmlidXRlIHZhbHVlIHdhc1xuICogbW9kaWZpZWQgYnkgYW4gZXh0ZXJuYWwgcGx1Z2luIG9yIEFQSSBvdXRzaWRlIG9mIHRoZSBzdHlsZSBiaW5kaW5nIGNvZGUuIFRoaXNcbiAqIG1lYW5zIGFueSBKUyBjb2RlIHRoYXQgYWRkcy9yZW1vdmVzIGNsYXNzL3N0eWxlIHZhbHVlcyBvbiBhbiBlbGVtZW50IG91dHNpZGVcbiAqIG9mIEFuZ3VsYXIncyBzdHlsaW5nIGJpbmRpbmcgYWxnb3JpdGhtLlxuICpcbiAqIEByZXR1cm5zIHRydWUgd2hlbiB0aGUgdmFsdWUgd2FzIG1vZGlmaWVkIGV4dGVybmFsbHkuXG4gKi9cbmZ1bmN0aW9uIGNoZWNrSWZFeHRlcm5hbGx5TW9kaWZpZWQoZWxlbWVudDogSFRNTEVsZW1lbnQsIGNhY2hlZFZhbHVlOiBhbnksIGlzQ2xhc3NCYXNlZDogYm9vbGVhbikge1xuICAvLyB0aGlzIG1lYW5zIGl0IHdhcyBjaGVja2VkIGJlZm9yZSBhbmQgdGhlcmUgaXMgbm8gcmVhc29uXG4gIC8vIHRvIGNvbXBhcmUgdGhlIHN0eWxlL2NsYXNzIHZhbHVlcyBhZ2Fpbi4gRWl0aGVyIHRoYXQgb3JcbiAgLy8gd2ViIHdvcmtlcnMgYXJlIGJlaW5nIHVzZWQuXG4gIGlmIChnbG9iYWwuTm9kZSA9PT0gJ3VuZGVmaW5lZCcgfHwgY2FjaGVkVmFsdWUgPT09IFZBTFVFX0lTX0VYVEVSTkFMTFlfTU9ESUZJRUQpIHJldHVybiB0cnVlO1xuXG4gIC8vIGNvbXBhcmluZyB0aGUgRE9NIHZhbHVlIGFnYWluc3QgdGhlIGNhY2hlZCB2YWx1ZSBpcyB0aGUgYmVzdCB3YXkgdG9cbiAgLy8gc2VlIGlmIHNvbWV0aGluZyBoYXMgY2hhbmdlZC5cbiAgY29uc3QgY3VycmVudFZhbHVlID1cbiAgICAgIChpc0NsYXNzQmFzZWQgPyBlbGVtZW50LmNsYXNzTmFtZSA6IChlbGVtZW50LnN0eWxlICYmIGVsZW1lbnQuc3R5bGUuY3NzVGV4dCkpIHx8ICcnO1xuICByZXR1cm4gY3VycmVudFZhbHVlICE9PSAoY2FjaGVkVmFsdWUgfHwgJycpO1xufVxuXG4vKipcbiAqIFJlbW92ZXMgcHJvdmlkZWQgc3R5bGluZyB2YWx1ZXMgZnJvbSB0aGUgZWxlbWVudFxuICovXG5mdW5jdGlvbiByZW1vdmVTdHlsaW5nVmFsdWVzKFxuICAgIHJlbmRlcmVyOiBhbnksIGVsZW1lbnQ6IFJFbGVtZW50LCB2YWx1ZXM6IHN0cmluZyB8IHtba2V5OiBzdHJpbmddOiBhbnl9IHwgU3R5bGluZ01hcEFycmF5LFxuICAgIGlzQ2xhc3NCYXNlZDogYm9vbGVhbikge1xuICBsZXQgYXJyOiBTdHlsaW5nTWFwQXJyYXk7XG4gIGlmIChpc1N0eWxpbmdNYXBBcnJheSh2YWx1ZXMpKSB7XG4gICAgYXJyID0gdmFsdWVzIGFzIFN0eWxpbmdNYXBBcnJheTtcbiAgfSBlbHNlIHtcbiAgICBhcnIgPSBub3JtYWxpemVJbnRvU3R5bGluZ01hcChudWxsLCB2YWx1ZXMsICFpc0NsYXNzQmFzZWQpO1xuICB9XG5cbiAgY29uc3QgYXBwbHlGbiA9IGlzQ2xhc3NCYXNlZCA/IHNldENsYXNzIDogc2V0U3R5bGU7XG4gIGZvciAobGV0IGkgPSBTdHlsaW5nTWFwQXJyYXlJbmRleC5WYWx1ZXNTdGFydFBvc2l0aW9uOyBpIDwgYXJyLmxlbmd0aDtcbiAgICAgICBpICs9IFN0eWxpbmdNYXBBcnJheUluZGV4LlR1cGxlU2l6ZSkge1xuICAgIGNvbnN0IHZhbHVlID0gZ2V0TWFwVmFsdWUoYXJyLCBpKTtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIGNvbnN0IHByb3AgPSBnZXRNYXBQcm9wKGFyciwgaSk7XG4gICAgICBhcHBseUZuKHJlbmRlcmVyLCBlbGVtZW50LCBwcm9wLCBudWxsKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==