@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,949 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Google Inc. All Rights Reserved.
4
- *
5
- * Use of this source code is governed by an MIT-style license that can be
6
- * found in the LICENSE file at https://angular.io/license
7
- */
8
- import { unwrapSafeValue } from '../../sanitization/bypass';
9
- import { global } from '../../util/global';
10
- import { RendererStyleFlags3, isProceduralRenderer } from '../interfaces/renderer';
11
- import { NO_CHANGE } from '../tokens';
12
- 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';
13
- import { getStylingState, resetStylingState } from './state';
14
- var VALUE_IS_EXTERNALLY_MODIFIED = {};
15
- /**
16
- * --------
17
- *
18
- * This file contains the core logic for styling in Angular.
19
- *
20
- * All styling bindings (i.e. `[style]`, `[style.prop]`, `[class]` and `[class.name]`)
21
- * will have their values be applied through the logic in this file.
22
- *
23
- * When a binding is encountered (e.g. `<div [style.width]="w">`) then
24
- * the binding data will be populated into a `TStylingContext` data-structure.
25
- * There is only one `TStylingContext` per `TStylingNode` and each element instance
26
- * will update its style/class binding values in concert with the styling
27
- * context.
28
- *
29
- * To learn more about the algorithm see `TStylingContext`.
30
- *
31
- * --------
32
- */
33
- /**
34
- * The guard/update mask bit index location for map-based bindings.
35
- *
36
- * All map-based bindings (i.e. `[style]` and `[class]` )
37
- */
38
- var STYLING_INDEX_FOR_MAP_BINDING = 0;
39
- /**
40
- * Visits a class-based binding and updates the new value (if changed).
41
- *
42
- * This function is called each time a class-based styling instruction
43
- * is executed. It's important that it's always called (even if the value
44
- * has not changed) so that the inner counter index value is incremented.
45
- * This way, each instruction is always guaranteed to get the same counter
46
- * state each time it's called (which then allows the `TStylingContext`
47
- * and the bit mask values to be in sync).
48
- */
49
- export function updateClassViaContext(context, tNode, data, element, directiveIndex, prop, bindingIndex, value, forceUpdate, firstUpdatePass) {
50
- var isMapBased = !prop;
51
- var state = getStylingState(element, directiveIndex);
52
- var countIndex = isMapBased ? STYLING_INDEX_FOR_MAP_BINDING : state.classesIndex++;
53
- // even if the initial value is a `NO_CHANGE` value (e.g. interpolation or [ngClass])
54
- // then we still need to register the binding within the context so that the context
55
- // is aware of the binding even if things change after the first update pass.
56
- if (firstUpdatePass || value !== NO_CHANGE) {
57
- var updated = updateBindingData(context, tNode, data, countIndex, state.sourceIndex, prop, bindingIndex, value, forceUpdate, false, firstUpdatePass, true);
58
- if (updated || forceUpdate) {
59
- // We flip the bit in the bitMask to reflect that the binding
60
- // at the `index` slot has changed. This identifies to the flushing
61
- // phase that the bindings for this particular CSS class need to be
62
- // applied again because on or more of the bindings for the CSS
63
- // class have changed.
64
- state.classesBitMask |= 1 << countIndex;
65
- return true;
66
- }
67
- }
68
- return false;
69
- }
70
- /**
71
- * Visits a style-based binding and updates the new value (if changed).
72
- *
73
- * This function is called each time a style-based styling instruction
74
- * is executed. It's important that it's always called (even if the value
75
- * has not changed) so that the inner counter index value is incremented.
76
- * This way, each instruction is always guaranteed to get the same counter
77
- * state each time it's called (which then allows the `TStylingContext`
78
- * and the bit mask values to be in sync).
79
- */
80
- export function updateStyleViaContext(context, tNode, data, element, directiveIndex, prop, bindingIndex, value, sanitizer, forceUpdate, firstUpdatePass) {
81
- var isMapBased = !prop;
82
- var state = getStylingState(element, directiveIndex);
83
- var countIndex = isMapBased ? STYLING_INDEX_FOR_MAP_BINDING : state.stylesIndex++;
84
- // even if the initial value is a `NO_CHANGE` value (e.g. interpolation or [ngStyle])
85
- // then we still need to register the binding within the context so that the context
86
- // is aware of the binding even if things change after the first update pass.
87
- if (firstUpdatePass || value !== NO_CHANGE) {
88
- var sanitizationRequired = isMapBased ?
89
- true :
90
- (sanitizer ? sanitizer(prop, null, 1 /* ValidateProperty */) : false);
91
- var updated = updateBindingData(context, tNode, data, countIndex, state.sourceIndex, prop, bindingIndex, value, forceUpdate, sanitizationRequired, firstUpdatePass, false);
92
- if (updated || forceUpdate) {
93
- // We flip the bit in the bitMask to reflect that the binding
94
- // at the `index` slot has changed. This identifies to the flushing
95
- // phase that the bindings for this particular property need to be
96
- // applied again because on or more of the bindings for the CSS
97
- // property have changed.
98
- state.stylesBitMask |= 1 << countIndex;
99
- return true;
100
- }
101
- }
102
- return false;
103
- }
104
- /**
105
- * Called each time a binding value has changed within the provided `TStylingContext`.
106
- *
107
- * This function is designed to be called from `updateStyleBinding` and `updateClassBinding`.
108
- * If called during the first update pass, the binding will be registered in the context.
109
- *
110
- * This function will also update binding slot in the provided `LStylingData` with the
111
- * new binding entry (if it has changed).
112
- *
113
- * @returns whether or not the binding value was updated in the `LStylingData`.
114
- */
115
- function updateBindingData(context, tNode, data, counterIndex, sourceIndex, prop, bindingIndex, value, forceUpdate, sanitizationRequired, firstUpdatePass, isClassBased) {
116
- var hostBindingsMode = isHostStylingActive(sourceIndex);
117
- var hostBindingsFlag = isClassBased ? 4096 /* hasHostClassBindings */ : 131072 /* hasHostStyleBindings */;
118
- if (firstUpdatePass) {
119
- // this will only happen during the first update pass of the
120
- // context. The reason why we can't use `tView.firstCreatePass`
121
- // here is because its not guaranteed to be true when the first
122
- // update pass is executed (remember that all styling instructions
123
- // are run in the update phase, and, as a result, are no more
124
- // styling instructions that are run in the creation phase).
125
- registerBinding(context, tNode, counterIndex, sourceIndex, prop, bindingIndex, sanitizationRequired, isClassBased);
126
- }
127
- var changed = forceUpdate || hasValueChanged(data[bindingIndex], value);
128
- if (changed) {
129
- setValue(data, bindingIndex, value);
130
- var doSetValuesAsStale = hasConfig(tNode, hostBindingsFlag) && !hostBindingsMode && (prop ? !value : true);
131
- if (doSetValuesAsStale) {
132
- renderHostBindingsAsStale(context, tNode, data, prop, isClassBased);
133
- }
134
- }
135
- return changed;
136
- }
137
- /**
138
- * Iterates over all host-binding values for the given `prop` value in the context and sets their
139
- * corresponding binding values to `null`.
140
- *
141
- * Whenever a template binding changes its value to `null`, all host-binding values should be
142
- * re-applied
143
- * to the element when the host bindings are evaluated. This may not always happen in the event
144
- * that none of the bindings changed within the host bindings code. For this reason this function
145
- * is expected to be called each time a template binding becomes falsy or when a map-based template
146
- * binding changes.
147
- */
148
- function renderHostBindingsAsStale(context, tNode, data, prop, isClassBased) {
149
- var valuesCount = getValuesCount(context);
150
- var hostBindingsFlag = isClassBased ? 4096 /* hasHostClassBindings */ : 131072 /* hasHostStyleBindings */;
151
- if (prop !== null && hasConfig(tNode, hostBindingsFlag)) {
152
- var itemsPerRow = 4 /* BindingsStartOffset */ + valuesCount;
153
- var i = 2 /* ValuesStartPosition */;
154
- var found = false;
155
- while (i < context.length) {
156
- if (getProp(context, i) === prop) {
157
- found = true;
158
- break;
159
- }
160
- i += itemsPerRow;
161
- }
162
- if (found) {
163
- var bindingsStart = i + 4 /* BindingsStartOffset */;
164
- var valuesStart = bindingsStart + 1; // the first column is template bindings
165
- var valuesEnd = bindingsStart + valuesCount - 1;
166
- for (var i_1 = valuesStart; i_1 < valuesEnd; i_1++) {
167
- var bindingIndex = context[i_1];
168
- if (bindingIndex !== 0) {
169
- setValue(data, bindingIndex, null);
170
- }
171
- }
172
- }
173
- }
174
- var mapBindingsFlag = isClassBased ? 512 /* hasClassMapBindings */ : 16384 /* hasStyleMapBindings */;
175
- if (hasConfig(tNode, mapBindingsFlag)) {
176
- var bindingsStart = 2 /* ValuesStartPosition */ + 4 /* BindingsStartOffset */;
177
- var valuesStart = bindingsStart + 1; // the first column is template bindings
178
- var valuesEnd = bindingsStart + valuesCount - 1;
179
- for (var i = valuesStart; i < valuesEnd; i++) {
180
- var stylingMap = getValue(data, context[i]);
181
- if (stylingMap) {
182
- setMapAsDirty(stylingMap);
183
- }
184
- }
185
- }
186
- }
187
- /**
188
- * Registers the provided binding (prop + bindingIndex) into the context.
189
- *
190
- * It is needed because it will either update or insert a styling property
191
- * into the context at the correct spot.
192
- *
193
- * When called, one of two things will happen:
194
- *
195
- * 1) If the property already exists in the context then it will just add
196
- * the provided `bindingValue` to the end of the binding sources region
197
- * for that particular property.
198
- *
199
- * - If the binding value is a number then it will be added as a new
200
- * binding index source next to the other binding sources for the property.
201
- *
202
- * - Otherwise, if the binding value is a string/boolean/null type then it will
203
- * replace the default value for the property if the default value is `null`.
204
- *
205
- * 2) If the property does not exist then it will be inserted into the context.
206
- * The styling context relies on all properties being stored in alphabetical
207
- * order, so it knows exactly where to store it.
208
- *
209
- * When inserted, a default `null` value is created for the property which exists
210
- * as the default value for the binding. If the bindingValue property is inserted
211
- * and it is either a string, number or null value then that will replace the default
212
- * value.
213
- *
214
- * Note that this function is also used for map-based styling bindings. They are treated
215
- * much the same as prop-based bindings, but, their property name value is set as `[MAP]`.
216
- */
217
- export function registerBinding(context, tNode, countId, sourceIndex, prop, bindingValue, sanitizationRequired, isClassBased) {
218
- var found = false;
219
- prop = prop || MAP_BASED_ENTRY_PROP_NAME;
220
- var totalSources = getTotalSources(context);
221
- // if a new source is detected then a new column needs to be allocated into
222
- // the styling context. The column is basically a new allocation of binding
223
- // sources that will be available to each property.
224
- while (totalSources <= sourceIndex) {
225
- addNewSourceColumn(context);
226
- totalSources++;
227
- }
228
- var collisionFlag = isClassBased ? 8192 /* hasDuplicateClassBindings */ : 262144 /* hasDuplicateStyleBindings */;
229
- var isBindingIndexValue = typeof bindingValue === 'number';
230
- var entriesPerRow = 4 /* BindingsStartOffset */ + getValuesCount(context);
231
- var i = 2 /* ValuesStartPosition */;
232
- // all style/class bindings are sorted by property name
233
- while (i < context.length) {
234
- var p = getProp(context, i);
235
- if (prop <= p) {
236
- if (prop < p) {
237
- allocateNewContextEntry(context, i, prop, sanitizationRequired);
238
- }
239
- else if (isBindingIndexValue) {
240
- patchConfig(tNode, collisionFlag);
241
- }
242
- addBindingIntoContext(context, i, bindingValue, countId, sourceIndex);
243
- found = true;
244
- break;
245
- }
246
- i += entriesPerRow;
247
- }
248
- if (!found) {
249
- allocateNewContextEntry(context, context.length, prop, sanitizationRequired);
250
- addBindingIntoContext(context, i, bindingValue, countId, sourceIndex);
251
- }
252
- }
253
- /**
254
- * Inserts a new row into the provided `TStylingContext` and assigns the provided `prop` value as
255
- * the property entry.
256
- */
257
- function allocateNewContextEntry(context, index, prop, sanitizationRequired) {
258
- var config = sanitizationRequired ? 1 /* SanitizationRequired */ :
259
- 0 /* Default */;
260
- context.splice(index, 0, config, // 1) config value
261
- DEFAULT_GUARD_MASK_VALUE, // 2) template bit mask
262
- DEFAULT_GUARD_MASK_VALUE, // 3) host bindings bit mask
263
- prop);
264
- index += 4; // the 4 values above
265
- // 5...) default binding index for the template value
266
- // depending on how many sources already exist in the context,
267
- // multiple default index entries may need to be inserted for
268
- // the new value in the context.
269
- var totalBindingsPerEntry = getTotalSources(context);
270
- for (var i = 0; i < totalBindingsPerEntry; i++) {
271
- context.splice(index, 0, DEFAULT_BINDING_INDEX);
272
- index++;
273
- }
274
- // 6) default binding value for the new entry
275
- context.splice(index, 0, DEFAULT_BINDING_VALUE);
276
- }
277
- /**
278
- * Inserts a new binding value into a styling property tuple in the `TStylingContext`.
279
- *
280
- * A bindingValue is inserted into a context during the first update pass
281
- * of a template or host bindings function. When this occurs, two things
282
- * happen:
283
- *
284
- * - If the bindingValue value is a number then it is treated as a bindingIndex
285
- * value (a index in the `LView`) and it will be inserted next to the other
286
- * binding index entries.
287
- *
288
- * - Otherwise the binding value will update the default value for the property
289
- * and this will only happen if the default value is `null`.
290
- */
291
- function addBindingIntoContext(context, index, bindingValue, bitIndex, sourceIndex) {
292
- if (typeof bindingValue === 'number') {
293
- var hostBindingsMode = isHostStylingActive(sourceIndex);
294
- var cellIndex = index + 4 /* BindingsStartOffset */ + sourceIndex;
295
- context[cellIndex] = bindingValue;
296
- var updatedBitMask = getGuardMask(context, index, hostBindingsMode) | (1 << bitIndex);
297
- setGuardMask(context, index, updatedBitMask, hostBindingsMode);
298
- }
299
- else if (bindingValue !== null && getDefaultValue(context, index) === null) {
300
- setDefaultValue(context, index, bindingValue);
301
- }
302
- }
303
- /**
304
- * Registers a new column into the provided `TStylingContext`.
305
- *
306
- * If and when a new source is detected then a new column needs to
307
- * be allocated into the styling context. The column is basically
308
- * a new allocation of binding sources that will be available to each
309
- * property.
310
- *
311
- * Each column that exists in the styling context resembles a styling
312
- * source. A styling source an either be the template or one or more
313
- * components or directives all containing styling host bindings.
314
- */
315
- function addNewSourceColumn(context) {
316
- // we use -1 here because we want to insert right before the last value (the default value)
317
- var insertOffset = 4 /* BindingsStartOffset */ + getValuesCount(context) - 1;
318
- var index = 2 /* ValuesStartPosition */;
319
- while (index < context.length) {
320
- index += insertOffset;
321
- context.splice(index++, 0, DEFAULT_BINDING_INDEX);
322
- // the value was inserted just before the default value, but the
323
- // next entry in the context starts just after it. Therefore++.
324
- index++;
325
- }
326
- context[0 /* TotalSourcesPosition */]++;
327
- }
328
- /**
329
- * Applies all pending style and class bindings to the provided element.
330
- *
331
- * This function will attempt to flush styling via the provided `classesContext`
332
- * and `stylesContext` context values. This function is designed to be run from
333
- * the internal `stylingApply` function (which is scheduled to run at the very
334
- * end of change detection for an element if one or more style/class bindings
335
- * were processed) and will rely on any state values that are set from when
336
- * any of the styling bindings executed.
337
- *
338
- * This function is designed to be called twice: one when change detection has
339
- * processed an element within the template bindings (i.e. just as `advance()`
340
- * is called) and when host bindings have been processed. In both cases the
341
- * styles and classes in both contexts will be applied to the element, but the
342
- * algorithm will selectively decide which bindings to run depending on the
343
- * columns in the context. The provided `directiveIndex` value will help the
344
- * algorithm determine which bindings to apply: either the template bindings or
345
- * the host bindings (see `applyStylingToElement` for more information).
346
- *
347
- * Note that once this function is called all temporary styling state data
348
- * (i.e. the `bitMask` and `counter` values for styles and classes will be cleared).
349
- */
350
- export function flushStyling(renderer, data, tNode, classesContext, stylesContext, element, directiveIndex, styleSanitizer, firstUpdatePass) {
351
- ngDevMode && ngDevMode.flushStyling++;
352
- var state = getStylingState(element, directiveIndex);
353
- var hostBindingsMode = isHostStylingActive(state.sourceIndex);
354
- if (stylesContext) {
355
- firstUpdatePass && syncContextInitialStyling(stylesContext, tNode, false);
356
- if (state.stylesBitMask !== 0) {
357
- applyStylingViaContext(stylesContext, tNode, renderer, element, data, state.stylesBitMask, setStyle, styleSanitizer, hostBindingsMode, false);
358
- }
359
- }
360
- if (classesContext) {
361
- firstUpdatePass && syncContextInitialStyling(classesContext, tNode, true);
362
- if (state.classesBitMask !== 0) {
363
- applyStylingViaContext(classesContext, tNode, renderer, element, data, state.classesBitMask, setClass, null, hostBindingsMode, true);
364
- }
365
- }
366
- resetStylingState();
367
- }
368
- /**
369
- * Registers all static styling values into the context as default values.
370
- *
371
- * Static styles are stored on the `tNode.styles` and `tNode.classes`
372
- * properties as instances of `StylingMapArray`. When an instance of
373
- * `TStylingContext` is assigned to `tNode.styles` and `tNode.classes`
374
- * then the existing initial styling values are copied into the the
375
- * `InitialStylingValuePosition` slot.
376
- *
377
- * Because all static styles/classes are collected and registered on
378
- * the initial styling array each time a directive is instantiated,
379
- * the context may not yet know about the static values. When this
380
- * function is called it will copy over all the static style/class
381
- * values from the initial styling array into the context as default
382
- * values for each of the matching entries in the context.
383
- *
384
- * Let's imagine the following example:
385
- *
386
- * ```html
387
- * <div style="color:red"
388
- * [style.color]="myColor"
389
- * dir-that-has-static-height>
390
- * ...
391
- * </div>
392
- * ```
393
- *
394
- * When the code above is processed, the underlying element/styling
395
- * instructions will create an instance of `TStylingContext` for
396
- * the `tNode.styles` property. Here's what that looks like:
397
- *
398
- * ```typescript
399
- * tNode.styles = [
400
- * // ...
401
- * // initial styles
402
- * ['color:red; height:200px', 'color', 'red', 'height', '200px'],
403
- *
404
- * 0, 0b1, 0b0, 'color', 20, null, // [style.color] binding
405
- * ]
406
- * ```
407
- *
408
- * After this function is called it will balance out the context with
409
- * the static `color` and `height` values and set them as defaults within
410
- * the context:
411
- *
412
- * ```typescript
413
- * tNode.styles = [
414
- * // ...
415
- * // initial styles
416
- * ['color:red; height:200px', 'color', 'red', 'height', '200px'],
417
- *
418
- * 0, 0b1, 0b0, 'color', 20, 'red',
419
- * 0, 0b0, 0b0, 'height', 0, '200px',
420
- * ]
421
- * ```
422
- */
423
- function syncContextInitialStyling(context, tNode, isClassBased) {
424
- // the TStylingContext always has initial style/class values which are
425
- // stored in styling array format.
426
- updateInitialStylingOnContext(context, tNode, getStylingMapArray(context), isClassBased);
427
- }
428
- /**
429
- * Registers all initial styling entries into the provided context.
430
- *
431
- * This function will iterate over all entries in the provided `initialStyling` ar}ray and register
432
- * them as default (initial) values in the provided context. Initial styling values in a context are
433
- * the default values that are to be applied unless overwritten by a binding.
434
- *
435
- * The reason why this function exists and isn't a part of the context construction is because
436
- * host binding is evaluated at a later stage after the element is created. This means that
437
- * if a directive or component contains any initial styling code (i.e. `<div class="foo">`)
438
- * then that initial styling data can only be applied once the styling for that element
439
- * is first applied (at the end of the update phase). Once that happens then the context will
440
- * update itself with the complete initial styling for the element.
441
- */
442
- function updateInitialStylingOnContext(context, tNode, initialStyling, isClassBased) {
443
- // `-1` is used here because all initial styling data is not a apart
444
- // of a binding (since it's static)
445
- var COUNT_ID_FOR_STYLING = -1;
446
- var hasInitialStyling = false;
447
- for (var i = 1 /* ValuesStartPosition */; i < initialStyling.length; i += 2 /* TupleSize */) {
448
- var value = getMapValue(initialStyling, i);
449
- if (value) {
450
- var prop = getMapProp(initialStyling, i);
451
- registerBinding(context, tNode, COUNT_ID_FOR_STYLING, 0, prop, value, false, isClassBased);
452
- hasInitialStyling = true;
453
- }
454
- }
455
- if (hasInitialStyling) {
456
- patchConfig(tNode, 256 /* hasInitialStyling */);
457
- }
458
- }
459
- /**
460
- * Runs through the provided styling context and applies each value to
461
- * the provided element (via the renderer) if one or more values are present.
462
- *
463
- * This function will iterate over all entries present in the provided
464
- * `TStylingContext` array (both prop-based and map-based bindings).-
465
- *
466
- * Each entry, within the `TStylingContext` array, is stored alphabetically
467
- * and this means that each prop/value entry will be applied in order
468
- * (so long as it is marked dirty in the provided `bitMask` value).
469
- *
470
- * If there are any map-based entries present (which are applied to the
471
- * element via the `[style]` and `[class]` bindings) then those entries
472
- * will be applied as well. However, the code for that is not a part of
473
- * this function. Instead, each time a property is visited, then the
474
- * code below will call an external function called `stylingMapsSyncFn`
475
- * and, if present, it will keep the application of styling values in
476
- * map-based bindings up to sync with the application of prop-based
477
- * bindings.
478
- *
479
- * Visit `styling/map_based_bindings.ts` to learn more about how the
480
- * algorithm works for map-based styling bindings.
481
- *
482
- * Note that this function is not designed to be called in isolation (use
483
- * the `flushStyling` function so that it can call this function for both
484
- * the styles and classes contexts).
485
- */
486
- export function applyStylingViaContext(context, tNode, renderer, element, bindingData, bitMaskValue, applyStylingFn, sanitizer, hostBindingsMode, isClassBased) {
487
- var bitMask = normalizeBitMaskValue(bitMaskValue);
488
- var stylingMapsSyncFn = null;
489
- var applyAllValues = false;
490
- var mapBindingsFlag = isClassBased ? 512 /* hasClassMapBindings */ : 16384 /* hasStyleMapBindings */;
491
- if (hasConfig(tNode, mapBindingsFlag)) {
492
- stylingMapsSyncFn = getStylingMapsSyncFn();
493
- var mapsGuardMask = getGuardMask(context, 2 /* ValuesStartPosition */, hostBindingsMode);
494
- applyAllValues = (bitMask & mapsGuardMask) !== 0;
495
- }
496
- var valuesCount = getValuesCount(context);
497
- var totalBindingsToVisit = 1;
498
- var mapsMode = applyAllValues ? 1 /* ApplyAllValues */ : 0 /* TraverseValues */;
499
- if (hostBindingsMode) {
500
- mapsMode |= 8 /* RecurseInnerMaps */;
501
- totalBindingsToVisit = valuesCount - 1;
502
- }
503
- var i = getPropValuesStartPosition(context, tNode, isClassBased);
504
- while (i < context.length) {
505
- var guardMask = getGuardMask(context, i, hostBindingsMode);
506
- if (bitMask & guardMask) {
507
- var valueApplied = false;
508
- var prop = getProp(context, i);
509
- var defaultValue = getDefaultValue(context, i);
510
- // Part 1: Visit the `[styling.prop]` value
511
- for (var j = 0; j < totalBindingsToVisit; j++) {
512
- var bindingIndex = getBindingValue(context, i, j);
513
- if (!valueApplied && bindingIndex !== 0) {
514
- var value = getValue(bindingData, bindingIndex);
515
- if (isStylingValueDefined(value)) {
516
- var checkValueOnly = hostBindingsMode && j === 0;
517
- if (!checkValueOnly) {
518
- var finalValue = sanitizer && isSanitizationRequired(context, i) ?
519
- sanitizer(prop, value, 2 /* SanitizeOnly */) :
520
- unwrapSafeValue(value);
521
- applyStylingFn(renderer, element, prop, finalValue, bindingIndex);
522
- }
523
- valueApplied = true;
524
- }
525
- }
526
- // Part 2: Visit the `[style]` or `[class]` map-based value
527
- if (stylingMapsSyncFn) {
528
- // determine whether or not to apply the target property or to skip it
529
- var mode = mapsMode | (valueApplied ? 4 /* SkipTargetProp */ :
530
- 2 /* ApplyTargetProp */);
531
- // the first column in the context (when `j == 0`) is special-cased for
532
- // template bindings. If and when host bindings are being processed then
533
- // the first column will still be iterated over, but the values will only
534
- // be checked against (not applied). If and when this happens we need to
535
- // notify the map-based syncing code to know not to apply the values it
536
- // comes across in the very first map-based binding (which is also located
537
- // in column zero).
538
- if (hostBindingsMode && j === 0) {
539
- mode |= 16 /* CheckValuesOnly */;
540
- }
541
- var valueAppliedWithinMap = stylingMapsSyncFn(context, renderer, element, bindingData, j, applyStylingFn, sanitizer, mode, prop, defaultValue);
542
- valueApplied = valueApplied || valueAppliedWithinMap;
543
- }
544
- }
545
- // Part 3: apply the default value (e.g. `<div style="width:200">` => `200px` gets applied)
546
- // if the value has not yet been applied then a truthy value does not exist in the
547
- // prop-based or map-based bindings code. If and when this happens, just apply the
548
- // default value (even if the default value is `null`).
549
- if (!valueApplied) {
550
- applyStylingFn(renderer, element, prop, defaultValue);
551
- }
552
- }
553
- i += 4 /* BindingsStartOffset */ + valuesCount;
554
- }
555
- // the map-based styling entries may have not applied all their
556
- // values. For this reason, one more call to the sync function
557
- // needs to be issued at the end.
558
- if (stylingMapsSyncFn) {
559
- if (hostBindingsMode) {
560
- mapsMode |= 16 /* CheckValuesOnly */;
561
- }
562
- stylingMapsSyncFn(context, renderer, element, bindingData, 0, applyStylingFn, sanitizer, mapsMode);
563
- }
564
- }
565
- /**
566
- * Applies the provided styling map to the element directly (without context resolution).
567
- *
568
- * This function is designed to be run from the styling instructions and will be called
569
- * automatically. This function is intended to be used for performance reasons in the
570
- * event that there is no need to apply styling via context resolution.
571
- *
572
- * This function has three different cases that can occur (for each item in the map):
573
- *
574
- * - Case 1: Attempt to apply the current value in the map to the element (if it's `non null`).
575
- *
576
- * - Case 2: If a map value fails to be applied then the algorithm will find a matching entry in
577
- * the initial values present in the context and attempt to apply that.
578
- *
579
- * - Default Case: If the initial value cannot be applied then a default value of `null` will be
580
- * applied (which will remove the style/class value from the element).
581
- *
582
- * See `allowDirectStylingApply` to learn the logic used to determine whether any style/class
583
- * bindings can be directly applied.
584
- *
585
- * @returns whether or not the styling map was applied to the element.
586
- */
587
- export function applyStylingMapDirectly(renderer, context, tNode, element, data, bindingIndex, value, isClassBased, sanitizer, forceUpdate, bindingValueContainsInitial) {
588
- var oldValue = getValue(data, bindingIndex);
589
- if (forceUpdate || hasValueChanged(oldValue, value)) {
590
- var hasInitial = hasConfig(tNode, 256 /* hasInitialStyling */);
591
- var initialValue = hasInitial && !bindingValueContainsInitial ? getInitialStylingValue(context) : null;
592
- setValue(data, bindingIndex, value);
593
- // the cached value is the last snapshot of the style or class
594
- // attribute value and is used in the if statement below to
595
- // keep track of internal/external changes.
596
- var cachedValueIndex = bindingIndex + 1;
597
- var cachedValue = getValue(data, cachedValueIndex);
598
- if (cachedValue === NO_CHANGE) {
599
- cachedValue = initialValue;
600
- }
601
- cachedValue = typeof cachedValue !== 'string' ? '' : cachedValue;
602
- // If a class/style value was modified externally then the styling
603
- // fast pass cannot guarantee that the external values are retained.
604
- // When this happens, the algorithm will bail out and not write to
605
- // the style or className attribute directly.
606
- var propBindingsFlag = isClassBased ? 1024 /* hasClassPropBindings */ : 32768 /* hasStylePropBindings */;
607
- var writeToAttrDirectly = !hasConfig(tNode, propBindingsFlag);
608
- if (writeToAttrDirectly &&
609
- checkIfExternallyModified(element, cachedValue, isClassBased)) {
610
- writeToAttrDirectly = false;
611
- if (oldValue !== VALUE_IS_EXTERNALLY_MODIFIED) {
612
- // direct styling will reset the attribute entirely each time,
613
- // and, for this reason, if the algorithm decides it cannot
614
- // write to the class/style attributes directly then it must
615
- // reset all the previous style/class values before it starts
616
- // to apply values in the non-direct way.
617
- removeStylingValues(renderer, element, oldValue, isClassBased);
618
- // this will instruct the algorithm not to apply class or style
619
- // values directly anymore.
620
- setValue(data, cachedValueIndex, VALUE_IS_EXTERNALLY_MODIFIED);
621
- }
622
- }
623
- if (writeToAttrDirectly) {
624
- var initialValue_1 = hasInitial && !bindingValueContainsInitial ? getInitialStylingValue(context) : null;
625
- var valueToApply = writeStylingValueDirectly(renderer, element, value, isClassBased, initialValue_1);
626
- setValue(data, cachedValueIndex, valueToApply || null);
627
- }
628
- else {
629
- var applyFn = isClassBased ? setClass : setStyle;
630
- var map = normalizeIntoStylingMap(oldValue, value, !isClassBased);
631
- var initialStyles = hasInitial ? getStylingMapArray(context) : null;
632
- for (var i = 1 /* ValuesStartPosition */; i < map.length; i += 2 /* TupleSize */) {
633
- var prop = getMapProp(map, i);
634
- var value_1 = getMapValue(map, i);
635
- // case 1: apply the map value (if it exists)
636
- var applied = applyStylingValue(renderer, element, prop, value_1, applyFn, bindingIndex, sanitizer);
637
- // case 2: apply the initial value (if it exists)
638
- if (!applied && initialStyles) {
639
- applied = findAndApplyMapValue(renderer, element, applyFn, initialStyles, prop, bindingIndex, sanitizer);
640
- }
641
- // default case: apply `null` to remove the value
642
- if (!applied) {
643
- applyFn(renderer, element, prop, null, bindingIndex);
644
- }
645
- }
646
- var state = getStylingState(element, TEMPLATE_DIRECTIVE_INDEX);
647
- if (isClassBased) {
648
- state.lastDirectClassMap = map;
649
- }
650
- else {
651
- state.lastDirectStyleMap = map;
652
- }
653
- }
654
- }
655
- }
656
- export function writeStylingValueDirectly(renderer, element, value, isClassBased, initialValue) {
657
- var valueToApply;
658
- if (isClassBased) {
659
- valueToApply = typeof value === 'string' ? value : objectToClassName(value);
660
- if (initialValue !== null) {
661
- valueToApply = concatString(initialValue, valueToApply, ' ');
662
- }
663
- setClassName(renderer, element, valueToApply);
664
- }
665
- else {
666
- valueToApply = forceStylesAsString(value, true);
667
- if (initialValue !== null) {
668
- valueToApply = initialValue + ';' + valueToApply;
669
- }
670
- setStyleAttr(renderer, element, valueToApply);
671
- }
672
- return valueToApply;
673
- }
674
- /**
675
- * Applies the provided styling prop/value to the element directly (without context resolution).
676
- *
677
- * This function is designed to be run from the styling instructions and will be called
678
- * automatically. This function is intended to be used for performance reasons in the
679
- * event that there is no need to apply styling via context resolution.
680
- *
681
- * This function has four different cases that can occur:
682
- *
683
- * - Case 1: Apply the provided prop/value (style or class) entry to the element
684
- * (if it is `non null`).
685
- *
686
- * - Case 2: If value does not get applied (because its `null` or `undefined`) then the algorithm
687
- * will check to see if a styling map value was applied to the element as well just
688
- * before this (via `styleMap` or `classMap`). If and when a map is present then the
689
- * algorithm will find the matching property in the map and apply its value.
690
- *
691
- * - Case 3: If a map value fails to be applied then the algorithm will check to see if there
692
- * are any initial values present and attempt to apply a matching value based on
693
- * the target prop.
694
- *
695
- * - Default Case: If a matching initial value cannot be applied then a default value
696
- * of `null` will be applied (which will remove the style/class value
697
- * from the element).
698
- *
699
- * See `allowDirectStylingApply` to learn the logic used to determine whether any style/class
700
- * bindings can be directly applied.
701
- *
702
- * @returns whether or not the prop/value styling was applied to the element.
703
- */
704
- export function applyStylingValueDirectly(renderer, context, tNode, element, data, bindingIndex, prop, value, isClassBased, sanitizer) {
705
- var applied = false;
706
- if (hasValueChanged(data[bindingIndex], value)) {
707
- setValue(data, bindingIndex, value);
708
- var applyFn = isClassBased ? setClass : setStyle;
709
- // case 1: apply the provided value (if it exists)
710
- applied = applyStylingValue(renderer, element, prop, value, applyFn, bindingIndex, sanitizer);
711
- // case 2: find the matching property in a styling map and apply the detected value
712
- var mapBindingsFlag = isClassBased ? 512 /* hasClassMapBindings */ : 16384 /* hasStyleMapBindings */;
713
- if (!applied && hasConfig(tNode, mapBindingsFlag)) {
714
- var state = getStylingState(element, TEMPLATE_DIRECTIVE_INDEX);
715
- var map = isClassBased ? state.lastDirectClassMap : state.lastDirectStyleMap;
716
- applied = map ?
717
- findAndApplyMapValue(renderer, element, applyFn, map, prop, bindingIndex, sanitizer) :
718
- false;
719
- }
720
- // case 3: apply the initial value (if it exists)
721
- if (!applied && hasConfig(tNode, 256 /* hasInitialStyling */)) {
722
- var map = getStylingMapArray(context);
723
- applied =
724
- map ? findAndApplyMapValue(renderer, element, applyFn, map, prop, bindingIndex) : false;
725
- }
726
- // default case: apply `null` to remove the value
727
- if (!applied) {
728
- applyFn(renderer, element, prop, null, bindingIndex);
729
- }
730
- }
731
- return applied;
732
- }
733
- function applyStylingValue(renderer, element, prop, value, applyFn, bindingIndex, sanitizer) {
734
- var valueToApply = unwrapSafeValue(value);
735
- if (isStylingValueDefined(valueToApply)) {
736
- valueToApply =
737
- sanitizer ? sanitizer(prop, value, 3 /* ValidateAndSanitize */) : valueToApply;
738
- applyFn(renderer, element, prop, valueToApply, bindingIndex);
739
- return true;
740
- }
741
- return false;
742
- }
743
- function findAndApplyMapValue(renderer, element, applyFn, map, prop, bindingIndex, sanitizer) {
744
- for (var i = 1 /* ValuesStartPosition */; i < map.length; i += 2 /* TupleSize */) {
745
- var p = getMapProp(map, i);
746
- if (p === prop) {
747
- var valueToApply = getMapValue(map, i);
748
- valueToApply = sanitizer ?
749
- sanitizer(prop, valueToApply, 3 /* ValidateAndSanitize */) :
750
- valueToApply;
751
- applyFn(renderer, element, prop, valueToApply, bindingIndex);
752
- return true;
753
- }
754
- if (p > prop) {
755
- break;
756
- }
757
- }
758
- return false;
759
- }
760
- function normalizeBitMaskValue(value) {
761
- // if pass => apply all values (-1 implies that all bits are flipped to true)
762
- if (value === true)
763
- return -1;
764
- // if pass => skip all values
765
- if (value === false)
766
- return 0;
767
- // return the bit mask value as is
768
- return value;
769
- }
770
- var _activeStylingMapApplyFn = null;
771
- export function getStylingMapsSyncFn() {
772
- return _activeStylingMapApplyFn;
773
- }
774
- export function setStylingMapsSyncFn(fn) {
775
- _activeStylingMapApplyFn = fn;
776
- }
777
- /**
778
- * Assigns a style value to a style property for the given element.
779
- */
780
- export var setStyle = function (renderer, native, prop, value) {
781
- if (renderer !== null) {
782
- // Use `isStylingValueDefined` to account for falsy values that should be bound like 0.
783
- if (isStylingValueDefined(value)) {
784
- // opacity, z-index and flexbox all have number values
785
- // and these need to be converted into strings so that
786
- // they can be assigned properly.
787
- value = value.toString();
788
- ngDevMode && ngDevMode.rendererSetStyle++;
789
- if (isProceduralRenderer(renderer)) {
790
- renderer.setStyle(native, prop, value, RendererStyleFlags3.DashCase);
791
- }
792
- else {
793
- // The reason why native style may be `null` is either because
794
- // it's a container element or it's a part of a test
795
- // environment that doesn't have styling. In either
796
- // case it's safe not to apply styling to the element.
797
- var nativeStyle = native.style;
798
- if (nativeStyle != null) {
799
- nativeStyle.setProperty(prop, value);
800
- }
801
- }
802
- }
803
- else {
804
- ngDevMode && ngDevMode.rendererRemoveStyle++;
805
- if (isProceduralRenderer(renderer)) {
806
- renderer.removeStyle(native, prop, RendererStyleFlags3.DashCase);
807
- }
808
- else {
809
- var nativeStyle = native.style;
810
- if (nativeStyle != null) {
811
- nativeStyle.removeProperty(prop);
812
- }
813
- }
814
- }
815
- }
816
- };
817
- /**
818
- * Adds/removes the provided className value to the provided element.
819
- */
820
- export var setClass = function (renderer, native, className, value) {
821
- if (renderer !== null && className !== '') {
822
- if (value) {
823
- ngDevMode && ngDevMode.rendererAddClass++;
824
- if (isProceduralRenderer(renderer)) {
825
- renderer.addClass(native, className);
826
- }
827
- else {
828
- // the reason why classList may be `null` is either because
829
- // it's a container element or it's a part of a test
830
- // environment that doesn't have styling. In either
831
- // case it's safe not to apply styling to the element.
832
- var classList = native.classList;
833
- if (classList != null) {
834
- classList.add(className);
835
- }
836
- }
837
- }
838
- else {
839
- ngDevMode && ngDevMode.rendererRemoveClass++;
840
- if (isProceduralRenderer(renderer)) {
841
- renderer.removeClass(native, className);
842
- }
843
- else {
844
- var classList = native.classList;
845
- if (classList != null) {
846
- classList.remove(className);
847
- }
848
- }
849
- }
850
- }
851
- };
852
- export var setClassName = function (renderer, native, className) {
853
- if (renderer !== null) {
854
- if (isProceduralRenderer(renderer)) {
855
- renderer.setAttribute(native, 'class', className);
856
- }
857
- else {
858
- native.className = className;
859
- }
860
- }
861
- };
862
- export var setStyleAttr = function (renderer, native, value) {
863
- if (renderer !== null) {
864
- if (isProceduralRenderer(renderer)) {
865
- renderer.setAttribute(native, 'style', value);
866
- }
867
- else {
868
- native.setAttribute('style', value);
869
- }
870
- }
871
- };
872
- /**
873
- * Iterates over all provided styling entries and renders them on the element.
874
- *
875
- * This function is used alongside a `StylingMapArray` entry. This entry is not
876
- * the same as the `TStylingContext` and is only really used when an element contains
877
- * initial styling values (e.g. `<div style="width:200px">`), but no style/class bindings
878
- * are present. If and when that happens then this function will be called to render all
879
- * initial styling values on an element.
880
- */
881
- export function renderStylingMap(renderer, element, stylingValues, isClassBased) {
882
- var stylingMapArr = getStylingMapArray(stylingValues);
883
- if (stylingMapArr) {
884
- for (var i = 1 /* ValuesStartPosition */; i < stylingMapArr.length; i += 2 /* TupleSize */) {
885
- var prop = getMapProp(stylingMapArr, i);
886
- var value = getMapValue(stylingMapArr, i);
887
- if (isClassBased) {
888
- setClass(renderer, element, prop, value, null);
889
- }
890
- else {
891
- setStyle(renderer, element, prop, value, null);
892
- }
893
- }
894
- }
895
- }
896
- function objectToClassName(obj) {
897
- var str = '';
898
- if (obj) {
899
- for (var key in obj) {
900
- var value = obj[key];
901
- if (value) {
902
- str += (str.length ? ' ' : '') + key;
903
- }
904
- }
905
- }
906
- return str;
907
- }
908
- /**
909
- * Determines whether or not an element style/className value has changed since the last update.
910
- *
911
- * This function helps Angular determine if a style or class attribute value was
912
- * modified by an external plugin or API outside of the style binding code. This
913
- * means any JS code that adds/removes class/style values on an element outside
914
- * of Angular's styling binding algorithm.
915
- *
916
- * @returns true when the value was modified externally.
917
- */
918
- function checkIfExternallyModified(element, cachedValue, isClassBased) {
919
- // this means it was checked before and there is no reason
920
- // to compare the style/class values again. Either that or
921
- // web workers are being used.
922
- if (global.Node === 'undefined' || cachedValue === VALUE_IS_EXTERNALLY_MODIFIED)
923
- return true;
924
- // comparing the DOM value against the cached value is the best way to
925
- // see if something has changed.
926
- var currentValue = (isClassBased ? element.className : (element.style && element.style.cssText)) || '';
927
- return currentValue !== (cachedValue || '');
928
- }
929
- /**
930
- * Removes provided styling values from the element
931
- */
932
- function removeStylingValues(renderer, element, values, isClassBased) {
933
- var arr;
934
- if (isStylingMapArray(values)) {
935
- arr = values;
936
- }
937
- else {
938
- arr = normalizeIntoStylingMap(null, values, !isClassBased);
939
- }
940
- var applyFn = isClassBased ? setClass : setStyle;
941
- for (var i = 1 /* ValuesStartPosition */; i < arr.length; i += 2 /* TupleSize */) {
942
- var value = getMapValue(arr, i);
943
- if (value) {
944
- var prop = getMapProp(arr, i);
945
- applyFn(renderer, element, prop, null);
946
- }
947
- }
948
- }
949
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmluZGluZ3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb3JlL3NyYy9yZW5kZXIzL3N0eWxpbmcvYmluZGluZ3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztFQU1FO0FBQ0YsT0FBTyxFQUFZLGVBQWUsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBRXJFLE9BQU8sRUFBQyxNQUFNLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUV6QyxPQUFPLEVBQTJDLG1CQUFtQixFQUFFLG9CQUFvQixFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFFM0gsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUMscUJBQXFCLEVBQUUscUJBQXFCLEVBQUUsd0JBQXdCLEVBQUUseUJBQXlCLEVBQUUsd0JBQXdCLEVBQUUsWUFBWSxFQUFFLG1CQUFtQixFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsWUFBWSxFQUFFLHNCQUFzQixFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLGtCQUFrQixFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsbUJBQW1CLEVBQUUsc0JBQXNCLEVBQUUsaUJBQWlCLEVBQUUscUJBQXFCLEVBQUUsdUJBQXVCLEVBQUUsV0FBVyxFQUFFLGVBQWUsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLFFBQVEsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBRTNsQixPQUFPLEVBQUMsZUFBZSxFQUFFLGlCQUFpQixFQUFDLE1BQU0sU0FBUyxDQUFDO0FBRTNELElBQU0sNEJBQTRCLEdBQUcsRUFBRSxDQUFDO0FBRXhDOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUVIOzs7O0dBSUc7QUFDSCxJQUFNLDZCQUE2QixHQUFHLENBQUMsQ0FBQztBQUV4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QUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3hGLE9BQU8sWUFBWSxLQUFLLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsbUJBQW1CLENBQ3hCLFFBQWEsRUFBRSxPQUFpQixFQUFFLE1BQXVELEVBQ3pGLFlBQXFCO0lBQ3ZCLElBQUksR0FBb0IsQ0FBQztJQUN6QixJQUFJLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxFQUFFO1FBQzdCLEdBQUcsR0FBRyxNQUF5QixDQUFDO0tBQ2pDO1NBQU07UUFDTCxHQUFHLEdBQUcsdUJBQXVCLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDO0tBQzVEO0lBRUQsSUFBTSxPQUFPLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztJQUNuRCxLQUFLLElBQUksQ0FBQyw4QkFBMkMsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFDaEUsQ0FBQyxxQkFBa0MsRUFBRTtRQUN4QyxJQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLElBQUksS0FBSyxFQUFFO1lBQ1QsSUFBTSxJQUFJLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNoQyxPQUFPLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDeEM7S0FDRjtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiogQGxpY2Vuc2VcbiogQ29weXJpZ2h0IEdvb2dsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4qXG4qIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4qIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiovXG5pbXBvcnQge1NhZmVWYWx1ZSwgdW53cmFwU2FmZVZhbHVlfSBmcm9tICcuLi8uLi9zYW5pdGl6YXRpb24vYnlwYXNzJztcbmltcG9ydCB7U3R5bGVTYW5pdGl6ZUZuLCBTdHlsZVNhbml0aXplTW9kZX0gZnJvbSAnLi4vLi4vc2FuaXRpemF0aW9uL3N0eWxlX3Nhbml0aXplcic7XG5pbXBvcnQge2dsb2JhbH0gZnJvbSAnLi4vLi4vdXRpbC9nbG9iYWwnO1xuaW1wb3J0IHtUTm9kZUZsYWdzfSBmcm9tICcuLi9pbnRlcmZhY2VzL25vZGUnO1xuaW1wb3J0IHtQcm9jZWR1cmFsUmVuZGVyZXIzLCBSRWxlbWVudCwgUmVuZGVyZXIzLCBSZW5kZXJlclN0eWxlRmxhZ3MzLCBpc1Byb2NlZHVyYWxSZW5kZXJlcn0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZW5kZXJlcic7XG5pbXBvcnQge0FwcGx5U3R5bGluZ0ZuLCBMU3R5bGluZ0RhdGEsIFN0eWxpbmdNYXBBcnJheSwgU3R5bGluZ01hcEFycmF5SW5kZXgsIFN0eWxpbmdNYXBzU3luY01vZGUsIFN5bmNTdHlsaW5nTWFwc0ZuLCBUU3R5bGluZ0NvbnRleHQsIFRTdHlsaW5nQ29udGV4dEluZGV4LCBUU3R5bGluZ0NvbnRleHRQcm9wQ29uZmlnRmxhZ3MsIFRTdHlsaW5nTm9kZX0gZnJvbSAnLi4vaW50ZXJmYWNlcy9zdHlsaW5nJztcbmltcG9ydCB7Tk9fQ0hBTkdFfSBmcm9tICcuLi90b2tlbnMnO1xuaW1wb3J0IHtERUZBVUxUX0JJTkRJTkdfSU5ERVgsIERFRkFVTFRfQklORElOR19WQUxVRSwgREVGQVVMVF9HVUFSRF9NQVNLX1ZBTFVFLCBNQVBfQkFTRURfRU5UUllfUFJPUF9OQU1FLCBURU1QTEFURV9ESVJFQ1RJVkVfSU5ERVgsIGNvbmNhdFN0cmluZywgZm9yY2VTdHlsZXNBc1N0cmluZywgZ2V0QmluZGluZ1ZhbHVlLCBnZXREZWZhdWx0VmFsdWUsIGdldEd1YXJkTWFzaywgZ2V0SW5pdGlhbFN0eWxpbmdWYWx1ZSwgZ2V0TWFwUHJvcCwgZ2V0TWFwVmFsdWUsIGdldFByb3AsIGdldFByb3BWYWx1ZXNTdGFydFBvc2l0aW9uLCBnZXRTdHlsaW5nTWFwQXJyYXksIGdldFRvdGFsU291cmNlcywgZ2V0VmFsdWUsIGdldFZhbHVlc0NvdW50LCBoYXNDb25maWcsIGhhc1ZhbHVlQ2hhbmdlZCwgaXNIb3N0U3R5bGluZ0FjdGl2ZSwgaXNTYW5pdGl6YXRpb25SZXF1aXJlZCwgaXNTdHlsaW5nTWFwQXJyYXksIGlzU3R5bGluZ1ZhbHVlRGVmaW5lZCwgbm9ybWFsaXplSW50b1N0eWxpbmdNYXAsIHBhdGNoQ29uZmlnLCBzZXREZWZhdWx0VmFsdWUsIHNldEd1YXJkTWFzaywgc2V0TWFwQXNEaXJ0eSwgc2V0VmFsdWV9IGZyb20gJy4uL3V0aWwvc3R5bGluZ191dGlscyc7XG5cbmltcG9ydCB7Z2V0U3R5bGluZ1N0YXRlLCByZXNldFN0eWxpbmdTdGF0ZX0gZnJvbSAnLi9zdGF0ZSc7XG5cbmNvbnN0IFZBTFVFX0lTX0VYVEVSTkFMTFlfTU9ESUZJRUQgPSB7fTtcblxuLyoqXG4gKiAtLS0tLS0tLVxuICpcbiAqIFRoaXMgZmlsZSBjb250YWlucyB0aGUgY29yZSBsb2dpYyBmb3Igc3R5bGluZyBpbiBBbmd1bGFyLlxuICpcbiAqIEFsbCBzdHlsaW5nIGJpbmRpbmdzIChpLmUuIGBbc3R5bGVdYCwgYFtzdHlsZS5wcm9wXWAsIGBbY2xhc3NdYCBhbmQgYFtjbGFzcy5uYW1lXWApXG4gKiB3aWxsIGhhdmUgdGhlaXIgdmFsdWVzIGJlIGFwcGxpZWQgdGhyb3VnaCB0aGUgbG9naWMgaW4gdGhpcyBmaWxlLlxuICpcbiAqIFdoZW4gYSBiaW5kaW5nIGlzIGVuY291bnRlcmVkIChlLmcuIGA8ZGl2IFtzdHlsZS53aWR0aF09XCJ3XCI+YCkgdGhlblxuICogdGhlIGJpbmRpbmcgZGF0YSB3aWxsIGJlIHBvcHVsYXRlZCBpbnRvIGEgYFRTdHlsaW5nQ29udGV4dGAgZGF0YS1zdHJ1Y3R1cmUuXG4gKiBUaGVyZSBpcyBvbmx5IG9uZSBgVFN0eWxpbmdDb250ZXh0YCBwZXIgYFRTdHlsaW5nTm9kZWAgYW5kIGVhY2ggZWxlbWVudCBpbnN0YW5jZVxuICogd2lsbCB1cGRhdGUgaXRzIHN0eWxlL2NsYXNzIGJpbmRpbmcgdmFsdWVzIGluIGNvbmNlcnQgd2l0aCB0aGUgc3R5bGluZ1xuICogY29udGV4dC5cbiAqXG4gKiBUbyBsZWFybiBtb3JlIGFib3V0IHRoZSBhbGdvcml0aG0gc2VlIGBUU3R5bGluZ0NvbnRleHRgLlxuICpcbiAqIC0tLS0tLS0tXG4gKi9cblxuLyoqXG4gKiBUaGUgZ3VhcmQvdXBkYXRlIG1hc2sgYml0IGluZGV4IGxvY2F0aW9uIGZvciBtYXAtYmFzZWQgYmluZGluZ3MuXG4gKlxuICogQWxsIG1hcC1iYXNlZCBiaW5kaW5ncyAoaS5lLiBgW3N0eWxlXWAgYW5kIGBbY2xhc3NdYCApXG4gKi9cbmNvbnN0IFNUWUxJTkdfSU5ERVhfRk9SX01BUF9CSU5ESU5HID0gMDtcblxuLyoqXG4gKiBWaXNpdHMgYSBjbGFzcy1iYXNlZCBiaW5kaW5nIGFuZCB1cGRhdGVzIHRoZSBuZXcgdmFsdWUgKGlmIGNoYW5nZWQpLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGVhY2ggdGltZSBhIGNsYXNzLWJhc2VkIHN0eWxpbmcgaW5zdHJ1Y3Rpb25cbiAqIGlzIGV4ZWN1dGVkLiBJdCdzIGltcG9ydGFudCB0aGF0IGl0J3MgYWx3YXlzIGNhbGxlZCAoZXZlbiBpZiB0aGUgdmFsdWVcbiAqIGhhcyBub3QgY2hhbmdlZCkgc28gdGhhdCB0aGUgaW5uZXIgY291bnRlciBpbmRleCB2YWx1ZSBpcyBpbmNyZW1lbnRlZC5cbiAqIFRoaXMgd2F5LCBlYWNoIGluc3RydWN0aW9uIGlzIGFsd2F5cyBndWFyYW50ZWVkIHRvIGdldCB0aGUgc2FtZSBjb3VudGVyXG4gKiBzdGF0ZSBlYWNoIHRpbWUgaXQncyBjYWxsZWQgKHdoaWNoIHRoZW4gYWxsb3dzIHRoZSBgVFN0eWxpbmdDb250ZXh0YFxuICogYW5kIHRoZSBiaXQgbWFzayB2YWx1ZXMgdG8gYmUgaW4gc3luYykuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVDbGFzc1ZpYUNvbnRleHQoXG4gICAgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LCB0Tm9kZTogVFN0eWxpbmdOb2RlLCBkYXRhOiBMU3R5bGluZ0RhdGEsIGVsZW1lbnQ6IFJFbGVtZW50LFxuICAgIGRpcmVjdGl2ZUluZGV4OiBudW1iZXIsIHByb3A6IHN0cmluZyB8IG51bGwsIGJpbmRpbmdJbmRleDogbnVtYmVyLFxuICAgIHZhbHVlOiBib29sZWFuIHwgc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCB8IFN0eWxpbmdNYXBBcnJheSB8IE5PX0NIQU5HRSwgZm9yY2VVcGRhdGU6IGJvb2xlYW4sXG4gICAgZmlyc3RVcGRhdGVQYXNzOiBib29sZWFuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGlzTWFwQmFzZWQgPSAhcHJvcDtcbiAgY29uc3Qgc3RhdGUgPSBnZXRTdHlsaW5nU3RhdGUoZWxlbWVudCwgZGlyZWN0aXZlSW5kZXgpO1xuICBjb25zdCBjb3VudEluZGV4ID0gaXNNYXBCYXNlZCA/IFNUWUxJTkdfSU5ERVhfRk9SX01BUF9CSU5ESU5HIDogc3RhdGUuY2xhc3Nlc0luZGV4Kys7XG5cbiAgLy8gZXZlbiBpZiB0aGUgaW5pdGlhbCB2YWx1ZSBpcyBhIGBOT19DSEFOR0VgIHZhbHVlIChlLmcuIGludGVycG9sYXRpb24gb3IgW25nQ2xhc3NdKVxuICAvLyB0aGVuIHdlIHN0aWxsIG5lZWQgdG8gcmVnaXN0ZXIgdGhlIGJpbmRpbmcgd2l0aGluIHRoZSBjb250ZXh0IHNvIHRoYXQgdGhlIGNvbnRleHRcbiAgLy8gaXMgYXdhcmUgb2YgdGhlIGJpbmRpbmcgZXZlbiBpZiB0aGluZ3MgY2hhbmdlIGFmdGVyIHRoZSBmaXJzdCB1cGRhdGUgcGFzcy5cbiAgaWYgKGZpcnN0VXBkYXRlUGFzcyB8fCB2YWx1ZSAhPT0gTk9fQ0hBTkdFKSB7XG4gICAgY29uc3QgdXBkYXRlZCA9IHVwZGF0ZUJpbmRpbmdEYXRhKFxuICAgICAgICBjb250ZXh0LCB0Tm9kZSwgZGF0YSwgY291bnRJbmRleCwgc3RhdGUuc291cmNlSW5kZXgsIHByb3AsIGJpbmRpbmdJbmRleCwgdmFsdWUsIGZvcmNlVXBkYXRlLFxuICAgICAgICBmYWxzZSwgZmlyc3RVcGRhdGVQYXNzLCB0cnVlKTtcbiAgICBpZiAodXBkYXRlZCB8fCBmb3JjZVVwZGF0ZSkge1xuICAgICAgLy8gV2UgZmxpcCB0aGUgYml0IGluIHRoZSBiaXRNYXNrIHRvIHJlZmxlY3QgdGhhdCB0aGUgYmluZGluZ1xuICAgICAgLy8gYXQgdGhlIGBpbmRleGAgc2xvdCBoYXMgY2hhbmdlZC4gVGhpcyBpZGVudGlmaWVzIHRvIHRoZSBmbHVzaGluZ1xuICAgICAgLy8gcGhhc2UgdGhhdCB0aGUgYmluZGluZ3MgZm9yIHRoaXMgcGFydGljdWxhciBDU1MgY2xhc3MgbmVlZCB0byBiZVxuICAgICAgLy8gYXBwbGllZCBhZ2FpbiBiZWNhdXNlIG9uIG9yIG1vcmUgb2YgdGhlIGJpbmRpbmdzIGZvciB0aGUgQ1NTXG4gICAgICAvLyBjbGFzcyBoYXZlIGNoYW5nZWQuXG4gICAgICBzdGF0ZS5jbGFzc2VzQml0TWFzayB8PSAxIDw8IGNvdW50SW5kZXg7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIFZpc2l0cyBhIHN0eWxlLWJhc2VkIGJpbmRpbmcgYW5kIHVwZGF0ZXMgdGhlIG5ldyB2YWx1ZSAoaWYgY2hhbmdlZCkuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgZWFjaCB0aW1lIGEgc3R5bGUtYmFzZWQgc3R5bGluZyBpbnN0cnVjdGlvblxuICogaXMgZXhlY3V0ZWQuIEl0J3MgaW1wb3J0YW50IHRoYXQgaXQncyBhbHdheXMgY2FsbGVkIChldmVuIGlmIHRoZSB2YWx1ZVxuICogaGFzIG5vdCBjaGFuZ2VkKSBzbyB0aGF0IHRoZSBpbm5lciBjb3VudGVyIGluZGV4IHZhbHVlIGlzIGluY3JlbWVudGVkLlxuICogVGhpcyB3YXksIGVhY2ggaW5zdHJ1Y3Rpb24gaXMgYWx3YXlzIGd1YXJhbnRlZWQgdG8gZ2V0IHRoZSBzYW1lIGNvdW50ZXJcbiAqIHN0YXRlIGVhY2ggdGltZSBpdCdzIGNhbGxlZCAod2hpY2ggdGhlbiBhbGxvd3MgdGhlIGBUU3R5bGluZ0NvbnRleHRgXG4gKiBhbmQgdGhlIGJpdCBtYXNrIHZhbHVlcyB0byBiZSBpbiBzeW5jKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVN0eWxlVmlhQ29udGV4dChcbiAgICBjb250ZXh0OiBUU3R5bGluZ0NvbnRleHQsIHROb2RlOiBUU3R5bGluZ05vZGUsIGRhdGE6IExTdHlsaW5nRGF0YSwgZWxlbWVudDogUkVsZW1lbnQsXG4gICAgZGlyZWN0aXZlSW5kZXg6IG51bWJlciwgcHJvcDogc3RyaW5nIHwgbnVsbCwgYmluZGluZ0luZGV4OiBudW1iZXIsXG4gICAgdmFsdWU6IHN0cmluZyB8IG51bWJlciB8IFNhZmVWYWx1ZSB8IG51bGwgfCB1bmRlZmluZWQgfCBTdHlsaW5nTWFwQXJyYXkgfCBOT19DSEFOR0UsXG4gICAgc2FuaXRpemVyOiBTdHlsZVNhbml0aXplRm4gfCBudWxsLCBmb3JjZVVwZGF0ZTogYm9vbGVhbiwgZmlyc3RVcGRhdGVQYXNzOiBib29sZWFuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGlzTWFwQmFzZWQgPSAhcHJvcDtcbiAgY29uc3Qgc3RhdGUgPSBnZXRTdHlsaW5nU3RhdGUoZWxlbWVudCwgZGlyZWN0aXZlSW5kZXgpO1xuICBjb25zdCBjb3VudEluZGV4ID0gaXNNYXBCYXNlZCA/IFNUWUxJTkdfSU5ERVhfRk9SX01BUF9CSU5ESU5HIDogc3RhdGUuc3R5bGVzSW5kZXgrKztcblxuICAvLyBldmVuIGlmIHRoZSBpbml0aWFsIHZhbHVlIGlzIGEgYE5PX0NIQU5HRWAgdmFsdWUgKGUuZy4gaW50ZXJwb2xhdGlvbiBvciBbbmdTdHlsZV0pXG4gIC8vIHRoZW4gd2Ugc3RpbGwgbmVlZCB0byByZWdpc3RlciB0aGUgYmluZGluZyB3aXRoaW4gdGhlIGNvbnRleHQgc28gdGhhdCB0aGUgY29udGV4dFxuICAvLyBpcyBhd2FyZSBvZiB0aGUgYmluZGluZyBldmVuIGlmIHRoaW5ncyBjaGFuZ2UgYWZ0ZXIgdGhlIGZpcnN0IHVwZGF0ZSBwYXNzLlxuICBpZiAoZmlyc3RVcGRhdGVQYXNzIHx8IHZhbHVlICE9PSBOT19DSEFOR0UpIHtcbiAgICBjb25zdCBzYW5pdGl6YXRpb25SZXF1aXJlZCA9IGlzTWFwQmFzZWQgP1xuICAgICAgICB0cnVlIDpcbiAgICAgICAgKHNhbml0aXplciA/IHNhbml0aXplcihwcm9wICEsIG51bGwsIFN0eWxlU2FuaXRpemVNb2RlLlZhbGlkYXRlUHJvcGVydHkpIDogZmFsc2UpO1xuICAgIGNvbnN0IHVwZGF0ZWQgPSB1cGRhdGVCaW5kaW5nRGF0YShcbiAgICAgICAgY29udGV4dCwgdE5vZGUsIGRhdGEsIGNvdW50SW5kZXgsIHN0YXRlLnNvdXJjZUluZGV4LCBwcm9wLCBiaW5kaW5nSW5kZXgsIHZhbHVlLCBmb3JjZVVwZGF0ZSxcbiAgICAgICAgc2FuaXRpemF0aW9uUmVxdWlyZWQsIGZpcnN0VXBkYXRlUGFzcywgZmFsc2UpO1xuICAgIGlmICh1cGRhdGVkIHx8IGZvcmNlVXBkYXRlKSB7XG4gICAgICAvLyBXZSBmbGlwIHRoZSBiaXQgaW4gdGhlIGJpdE1hc2sgdG8gcmVmbGVjdCB0aGF0IHRoZSBiaW5kaW5nXG4gICAgICAvLyBhdCB0aGUgYGluZGV4YCBzbG90IGhhcyBjaGFuZ2VkLiBUaGlzIGlkZW50aWZpZXMgdG8gdGhlIGZsdXNoaW5nXG4gICAgICAvLyBwaGFzZSB0aGF0IHRoZSBiaW5kaW5ncyBmb3IgdGhpcyBwYXJ0aWN1bGFyIHByb3BlcnR5IG5lZWQgdG8gYmVcbiAgICAgIC8vIGFwcGxpZWQgYWdhaW4gYmVjYXVzZSBvbiBvciBtb3JlIG9mIHRoZSBiaW5kaW5ncyBmb3IgdGhlIENTU1xuICAgICAgLy8gcHJvcGVydHkgaGF2ZSBjaGFuZ2VkLlxuICAgICAgc3RhdGUuc3R5bGVzQml0TWFzayB8PSAxIDw8IGNvdW50SW5kZXg7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIENhbGxlZCBlYWNoIHRpbWUgYSBiaW5kaW5nIHZhbHVlIGhhcyBjaGFuZ2VkIHdpdGhpbiB0aGUgcHJvdmlkZWQgYFRTdHlsaW5nQ29udGV4dGAuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpcyBkZXNpZ25lZCB0byBiZSBjYWxsZWQgZnJvbSBgdXBkYXRlU3R5bGVCaW5kaW5nYCBhbmQgYHVwZGF0ZUNsYXNzQmluZGluZ2AuXG4gKiBJZiBjYWxsZWQgZHVyaW5nIHRoZSBmaXJzdCB1cGRhdGUgcGFzcywgdGhlIGJpbmRpbmcgd2lsbCBiZSByZWdpc3RlcmVkIGluIHRoZSBjb250ZXh0LlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBhbHNvIHVwZGF0ZSBiaW5kaW5nIHNsb3QgaW4gdGhlIHByb3ZpZGVkIGBMU3R5bGluZ0RhdGFgIHdpdGggdGhlXG4gKiBuZXcgYmluZGluZyBlbnRyeSAoaWYgaXQgaGFzIGNoYW5nZWQpLlxuICpcbiAqIEByZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBiaW5kaW5nIHZhbHVlIHdhcyB1cGRhdGVkIGluIHRoZSBgTFN0eWxpbmdEYXRhYC5cbiAqL1xuZnVuY3Rpb24gdXBkYXRlQmluZGluZ0RhdGEoXG4gICAgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LCB0Tm9kZTogVFN0eWxpbmdOb2RlLCBkYXRhOiBMU3R5bGluZ0RhdGEsIGNvdW50ZXJJbmRleDogbnVtYmVyLFxuICAgIHNvdXJjZUluZGV4OiBudW1iZXIsIHByb3A6IHN0cmluZyB8IG51bGwsIGJpbmRpbmdJbmRleDogbnVtYmVyLFxuICAgIHZhbHVlOiBzdHJpbmcgfCBTYWZlVmFsdWUgfCBudW1iZXIgfCBib29sZWFuIHwgbnVsbCB8IHVuZGVmaW5lZCB8IFN0eWxpbmdNYXBBcnJheSxcbiAgICBmb3JjZVVwZGF0ZTogYm9vbGVhbiwgc2FuaXRpemF0aW9uUmVxdWlyZWQ6IGJvb2xlYW4sIGZpcnN0VXBkYXRlUGFzczogYm9vbGVhbixcbiAgICBpc0NsYXNzQmFzZWQ6IGJvb2xlYW4pOiBib29sZWFuIHtcbiAgY29uc3QgaG9zdEJpbmRpbmdzTW9kZSA9IGlzSG9zdFN0eWxpbmdBY3RpdmUoc291cmNlSW5kZXgpO1xuICBjb25zdCBob3N0QmluZGluZ3NGbGFnID1cbiAgICAgIGlzQ2xhc3NCYXNlZCA/IFROb2RlRmxhZ3MuaGFzSG9zdENsYXNzQmluZGluZ3MgOiBUTm9kZUZsYWdzLmhhc0hvc3RTdHlsZUJpbmRpbmdzO1xuICBpZiAoZmlyc3RVcGRhdGVQYXNzKSB7XG4gICAgLy8gdGhpcyB3aWxsIG9ubHkgaGFwcGVuIGR1cmluZyB0aGUgZmlyc3QgdXBkYXRlIHBhc3Mgb2YgdGhlXG4gICAgLy8gY29udGV4dC4gVGhlIHJlYXNvbiB3aHkgd2UgY2FuJ3QgdXNlIGB0Vmlldy5maXJzdENyZWF0ZVBhc3NgXG4gICAgLy8gaGVyZSBpcyBiZWNhdXNlIGl0cyBub3QgZ3VhcmFudGVlZCB0byBiZSB0cnVlIHdoZW4gdGhlIGZpcnN0XG4gICAgLy8gdXBkYXRlIHBhc3MgaXMgZXhlY3V0ZWQgKHJlbWVtYmVyIHRoYXQgYWxsIHN0eWxpbmcgaW5zdHJ1Y3Rpb25zXG4gICAgLy8gYXJlIHJ1biBpbiB0aGUgdXBkYXRlIHBoYXNlLCBhbmQsIGFzIGEgcmVzdWx0LCBhcmUgbm8gbW9yZVxuICAgIC8vIHN0eWxpbmcgaW5zdHJ1Y3Rpb25zIHRoYXQgYXJlIHJ1biBpbiB0aGUgY3JlYXRpb24gcGhhc2UpLlxuICAgIHJlZ2lzdGVyQmluZGluZyhcbiAgICAgICAgY29udGV4dCwgdE5vZGUsIGNvdW50ZXJJbmRleCwgc291cmNlSW5kZXgsIHByb3AsIGJpbmRpbmdJbmRleCwgc2FuaXRpemF0aW9uUmVxdWlyZWQsXG4gICAgICAgIGlzQ2xhc3NCYXNlZCk7XG4gIH1cblxuICBjb25zdCBjaGFuZ2VkID0gZm9yY2VVcGRhdGUgfHwgaGFzVmFsdWVDaGFuZ2VkKGRhdGFbYmluZGluZ0luZGV4XSwgdmFsdWUpO1xuICBpZiAoY2hhbmdlZCkge1xuICAgIHNldFZhbHVlKGRhdGEsIGJpbmRpbmdJbmRleCwgdmFsdWUpO1xuICAgIGNvbnN0IGRvU2V0VmFsdWVzQXNTdGFsZSA9XG4gICAgICAgIGhhc0NvbmZpZyh0Tm9kZSwgaG9zdEJpbmRpbmdzRmxhZykgJiYgIWhvc3RCaW5kaW5nc01vZGUgJiYgKHByb3AgPyAhdmFsdWUgOiB0cnVlKTtcbiAgICBpZiAoZG9TZXRWYWx1ZXNBc1N0YWxlKSB7XG4gICAgICByZW5kZXJIb3N0QmluZGluZ3NBc1N0YWxlKGNvbnRleHQsIHROb2RlLCBkYXRhLCBwcm9wLCBpc0NsYXNzQmFzZWQpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gY2hhbmdlZDtcbn1cblxuLyoqXG4gKiBJdGVyYXRlcyBvdmVyIGFsbCBob3N0LWJpbmRpbmcgdmFsdWVzIGZvciB0aGUgZ2l2ZW4gYHByb3BgIHZhbHVlIGluIHRoZSBjb250ZXh0IGFuZCBzZXRzIHRoZWlyXG4gKiBjb3JyZXNwb25kaW5nIGJpbmRpbmcgdmFsdWVzIHRvIGBudWxsYC5cbiAqXG4gKiBXaGVuZXZlciBhIHRlbXBsYXRlIGJpbmRpbmcgY2hhbmdlcyBpdHMgdmFsdWUgdG8gYG51bGxgLCBhbGwgaG9zdC1iaW5kaW5nIHZhbHVlcyBzaG91bGQgYmVcbiAqIHJlLWFwcGxpZWRcbiAqIHRvIHRoZSBlbGVtZW50IHdoZW4gdGhlIGhvc3QgYmluZGluZ3MgYXJlIGV2YWx1YXRlZC4gVGhpcyBtYXkgbm90IGFsd2F5cyBoYXBwZW4gaW4gdGhlIGV2ZW50XG4gKiB0aGF0IG5vbmUgb2YgdGhlIGJpbmRpbmdzIGNoYW5nZWQgd2l0aGluIHRoZSBob3N0IGJpbmRpbmdzIGNvZGUuIEZvciB0aGlzIHJlYXNvbiB0aGlzIGZ1bmN0aW9uXG4gKiBpcyBleHBlY3RlZCB0byBiZSBjYWxsZWQgZWFjaCB0aW1lIGEgdGVtcGxhdGUgYmluZGluZyBiZWNvbWVzIGZhbHN5IG9yIHdoZW4gYSBtYXAtYmFzZWQgdGVtcGxhdGVcbiAqIGJpbmRpbmcgY2hhbmdlcy5cbiAqL1xuZnVuY3Rpb24gcmVuZGVySG9zdEJpbmRpbmdzQXNTdGFsZShcbiAgICBjb250ZXh0OiBUU3R5bGluZ0NvbnRleHQsIHROb2RlOiBUU3R5bGluZ05vZGUsIGRhdGE6IExTdHlsaW5nRGF0YSwgcHJvcDogc3RyaW5nIHwgbnVsbCxcbiAgICBpc0NsYXNzQmFzZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgY29uc3QgdmFsdWVzQ291bnQgPSBnZXRWYWx1ZXNDb3VudChjb250ZXh0KTtcblxuICBjb25zdCBob3N0QmluZGluZ3NGbGFnID1cbiAgICAgIGlzQ2xhc3NCYXNlZCA/IFROb2RlRmxhZ3MuaGFzSG9zdENsYXNzQmluZGluZ3MgOiBUTm9kZUZsYWdzLmhhc0hvc3RTdHlsZUJpbmRpbmdzO1xuICBpZiAocHJvcCAhPT0gbnVsbCAmJiBoYXNDb25maWcodE5vZGUsIGhvc3RCaW5kaW5nc0ZsYWcpKSB7XG4gICAgY29uc3QgaXRlbXNQZXJSb3cgPSBUU3R5bGluZ0NvbnRleHRJbmRleC5CaW5kaW5nc1N0YXJ0T2Zmc2V0ICsgdmFsdWVzQ291bnQ7XG5cbiAgICBsZXQgaSA9IFRTdHlsaW5nQ29udGV4dEluZGV4LlZhbHVlc1N0YXJ0UG9zaXRpb247XG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgd2hpbGUgKGkgPCBjb250ZXh0Lmxlbmd0aCkge1xuICAgICAgaWYgKGdldFByb3AoY29udGV4dCwgaSkgPT09IHByb3ApIHtcbiAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGkgKz0gaXRlbXNQZXJSb3c7XG4gICAgfVxuXG4gICAgaWYgKGZvdW5kKSB7XG4gICAgICBjb25zdCBiaW5kaW5nc1N0YXJ0ID0gaSArIFRTdHlsaW5nQ29udGV4dEluZGV4LkJpbmRpbmdzU3RhcnRPZmZzZXQ7XG4gICAgICBjb25zdCB2YWx1ZXNTdGFydCA9IGJpbmRpbmdzU3RhcnQgKyAxOyAgLy8gdGhlIGZpcnN0IGNvbHVtbiBpcyB0ZW1wbGF0ZSBiaW5kaW5nc1xuICAgICAgY29uc3QgdmFsdWVzRW5kID0gYmluZGluZ3NTdGFydCArIHZhbHVlc0NvdW50IC0gMTtcblxuICAgICAgZm9yIChsZXQgaSA9IHZhbHVlc1N0YXJ0OyBpIDwgdmFsdWVzRW5kOyBpKyspIHtcbiAgICAgICAgY29uc3QgYmluZGluZ0luZGV4ID0gY29udGV4dFtpXSBhcyBudW1iZXI7XG4gICAgICAgIGlmIChiaW5kaW5nSW5kZXggIT09IDApIHtcbiAgICAgICAgICBzZXRWYWx1ZShkYXRhLCBiaW5kaW5nSW5kZXgsIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgbWFwQmluZGluZ3NGbGFnID1cbiAgICAgIGlzQ2xhc3NCYXNlZCA/IFROb2RlRmxhZ3MuaGFzQ2xhc3NNYXBCaW5kaW5ncyA6IFROb2RlRmxhZ3MuaGFzU3R5bGVNYXBCaW5kaW5ncztcbiAgaWYgKGhhc0NvbmZpZyh0Tm9kZSwgbWFwQmluZGluZ3NGbGFnKSkge1xuICAgIGNvbnN0IGJpbmRpbmdzU3RhcnQgPVxuICAgICAgICBUU3R5bGluZ0NvbnRleHRJbmRleC5WYWx1ZXNTdGFydFBvc2l0aW9uICsgVFN0eWxpbmdDb250ZXh0SW5kZXguQmluZGluZ3NTdGFydE9mZnNldDtcbiAgICBjb25zdCB2YWx1ZXNTdGFydCA9IGJpbmRpbmdzU3RhcnQgKyAxOyAgLy8gdGhlIGZpcnN0IGNvbHVtbiBpcyB0ZW1wbGF0ZSBiaW5kaW5nc1xuICAgIGNvbnN0IHZhbHVlc0VuZCA9IGJpbmRpbmdzU3RhcnQgKyB2YWx1ZXNDb3VudCAtIDE7XG4gICAgZm9yIChsZXQgaSA9IHZhbHVlc1N0YXJ0OyBpIDwgdmFsdWVzRW5kOyBpKyspIHtcbiAgICAgIGNvbnN0IHN0eWxpbmdNYXAgPSBnZXRWYWx1ZTxTdHlsaW5nTWFwQXJyYXk+KGRhdGEsIGNvbnRleHRbaV0gYXMgbnVtYmVyKTtcbiAgICAgIGlmIChzdHlsaW5nTWFwKSB7XG4gICAgICAgIHNldE1hcEFzRGlydHkoc3R5bGluZ01hcCk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIHRoZSBwcm92aWRlZCBiaW5kaW5nIChwcm9wICsgYmluZGluZ0luZGV4KSBpbnRvIHRoZSBjb250ZXh0LlxuICpcbiAqIEl0IGlzIG5lZWRlZCBiZWNhdXNlIGl0IHdpbGwgZWl0aGVyIHVwZGF0ZSBvciBpbnNlcnQgYSBzdHlsaW5nIHByb3BlcnR5XG4gKiBpbnRvIHRoZSBjb250ZXh0IGF0IHRoZSBjb3JyZWN0IHNwb3QuXG4gKlxuICogV2hlbiBjYWxsZWQsIG9uZSBvZiB0d28gdGhpbmdzIHdpbGwgaGFwcGVuOlxuICpcbiAqIDEpIElmIHRoZSBwcm9wZXJ0eSBhbHJlYWR5IGV4aXN0cyBpbiB0aGUgY29udGV4dCB0aGVuIGl0IHdpbGwganVzdCBhZGRcbiAqICAgIHRoZSBwcm92aWRlZCBgYmluZGluZ1ZhbHVlYCB0byB0aGUgZW5kIG9mIHRoZSBiaW5kaW5nIHNvdXJjZXMgcmVnaW9uXG4gKiAgICBmb3IgdGhhdCBwYXJ0aWN1bGFyIHByb3BlcnR5LlxuICpcbiAqICAgIC0gSWYgdGhlIGJpbmRpbmcgdmFsdWUgaXMgYSBudW1iZXIgdGhlbiBpdCB3aWxsIGJlIGFkZGVkIGFzIGEgbmV3XG4gKiAgICAgIGJpbmRpbmcgaW5kZXggc291cmNlIG5leHQgdG8gdGhlIG90aGVyIGJpbmRpbmcgc291cmNlcyBmb3IgdGhlIHByb3BlcnR5LlxuICpcbiAqICAgIC0gT3RoZXJ3aXNlLCBpZiB0aGUgYmluZGluZyB2YWx1ZSBpcyBhIHN0cmluZy9ib29sZWFuL251bGwgdHlwZSB0aGVuIGl0IHdpbGxcbiAqICAgICAgcmVwbGFjZSB0aGUgZGVmYXVsdCB2YWx1ZSBmb3IgdGhlIHByb3BlcnR5IGlmIHRoZSBkZWZhdWx0IHZhbHVlIGlzIGBudWxsYC5cbiAqXG4gKiAyKSBJZiB0aGUgcHJvcGVydHkgZG9lcyBub3QgZXhpc3QgdGhlbiBpdCB3aWxsIGJlIGluc2VydGVkIGludG8gdGhlIGNvbnRleHQuXG4gKiAgICBUaGUgc3R5bGluZyBjb250ZXh0IHJlbGllcyBvbiBhbGwgcHJvcGVydGllcyBiZWluZyBzdG9yZWQgaW4gYWxwaGFiZXRpY2FsXG4gKiAgICBvcmRlciwgc28gaXQga25vd3MgZXhhY3RseSB3aGVyZSB0byBzdG9yZSBpdC5cbiAqXG4gKiAgICBXaGVuIGluc2VydGVkLCBhIGRlZmF1bHQgYG51bGxgIHZhbHVlIGlzIGNyZWF0ZWQgZm9yIHRoZSBwcm9wZXJ0eSB3aGljaCBleGlzdHNcbiAqICAgIGFzIHRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgYmluZGluZy4gSWYgdGhlIGJpbmRpbmdWYWx1ZSBwcm9wZXJ0eSBpcyBpbnNlcnRlZFxuICogICAgYW5kIGl0IGlzIGVpdGhlciBhIHN0cmluZywgbnVtYmVyIG9yIG51bGwgdmFsdWUgdGhlbiB0aGF0IHdpbGwgcmVwbGFjZSB0aGUgZGVmYXVsdFxuICogICAgdmFsdWUuXG4gKlxuICogTm90ZSB0aGF0IHRoaXMgZnVuY3Rpb24gaXMgYWxzbyB1c2VkIGZvciBtYXAtYmFzZWQgc3R5bGluZyBiaW5kaW5ncy4gVGhleSBhcmUgdHJlYXRlZFxuICogbXVjaCB0aGUgc2FtZSBhcyBwcm9wLWJhc2VkIGJpbmRpbmdzLCBidXQsIHRoZWlyIHByb3BlcnR5IG5hbWUgdmFsdWUgaXMgc2V0IGFzIGBbTUFQXWAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckJpbmRpbmcoXG4gICAgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LCB0Tm9kZTogVFN0eWxpbmdOb2RlLCBjb3VudElkOiBudW1iZXIsIHNvdXJjZUluZGV4OiBudW1iZXIsXG4gICAgcHJvcDogc3RyaW5nIHwgbnVsbCwgYmluZGluZ1ZhbHVlOiBudW1iZXIgfCBudWxsIHwgc3RyaW5nIHwgYm9vbGVhbixcbiAgICBzYW5pdGl6YXRpb25SZXF1aXJlZDogYm9vbGVhbiwgaXNDbGFzc0Jhc2VkOiBib29sZWFuKTogdm9pZCB7XG4gIGxldCBmb3VuZCA9IGZhbHNlO1xuICBwcm9wID0gcHJvcCB8fCBNQVBfQkFTRURfRU5UUllfUFJPUF9OQU1FO1xuXG4gIGxldCB0b3RhbFNvdXJjZXMgPSBnZXRUb3RhbFNvdXJjZXMoY29udGV4dCk7XG5cbiAgLy8gaWYgYSBuZXcgc291cmNlIGlzIGRldGVjdGVkIHRoZW4gYSBuZXcgY29sdW1uIG5lZWRzIHRvIGJlIGFsbG9jYXRlZCBpbnRvXG4gIC8vIHRoZSBzdHlsaW5nIGNvbnRleHQuIFRoZSBjb2x1bW4gaXMgYmFzaWNhbGx5IGEgbmV3IGFsbG9jYXRpb24gb2YgYmluZGluZ1xuICAvLyBzb3VyY2VzIHRoYXQgd2lsbCBiZSBhdmFpbGFibGUgdG8gZWFjaCBwcm9wZXJ0eS5cbiAgd2hpbGUgKHRvdGFsU291cmNlcyA8PSBzb3VyY2VJbmRleCkge1xuICAgIGFkZE5ld1NvdXJjZUNvbHVtbihjb250ZXh0KTtcbiAgICB0b3RhbFNvdXJjZXMrKztcbiAgfVxuXG4gIGNvbnN0IGNvbGxpc2lvbkZsYWcgPVxuICAgICAgaXNDbGFzc0Jhc2VkID8gVE5vZGVGbGFncy5oYXNEdXBsaWNhdGVDbGFzc0JpbmRpbmdzIDogVE5vZGVGbGFncy5oYXNEdXBsaWNhdGVTdHlsZUJpbmRpbmdzO1xuICBjb25zdCBpc0JpbmRpbmdJbmRleFZhbHVlID0gdHlwZW9mIGJpbmRpbmdWYWx1ZSA9PT0gJ251bWJlcic7XG4gIGNvbnN0IGVudHJpZXNQZXJSb3cgPSBUU3R5bGluZ0NvbnRleHRJbmRleC5CaW5kaW5nc1N0YXJ0T2Zmc2V0ICsgZ2V0VmFsdWVzQ291bnQoY29udGV4dCk7XG4gIGxldCBpID0gVFN0eWxpbmdDb250ZXh0SW5kZXguVmFsdWVzU3RhcnRQb3NpdGlvbjtcblxuICAvLyBhbGwgc3R5bGUvY2xhc3MgYmluZGluZ3MgYXJlIHNvcnRlZCBieSBwcm9wZXJ0eSBuYW1lXG4gIHdoaWxlIChpIDwgY29udGV4dC5sZW5ndGgpIHtcbiAgICBjb25zdCBwID0gZ2V0UHJvcChjb250ZXh0LCBpKTtcbiAgICBpZiAocHJvcCA8PSBwKSB7XG4gICAgICBpZiAocHJvcCA8IHApIHtcbiAgICAgICAgYWxsb2NhdGVOZXdDb250ZXh0RW50cnkoY29udGV4dCwgaSwgcHJvcCwgc2FuaXRpemF0aW9uUmVxdWlyZWQpO1xuICAgICAgfSBlbHNlIGlmIChpc0JpbmRpbmdJbmRleFZhbHVlKSB7XG4gICAgICAgIHBhdGNoQ29uZmlnKHROb2RlLCBjb2xsaXNpb25GbGFnKTtcbiAgICAgIH1cbiAgICAgIGFkZEJpbmRpbmdJbnRvQ29udGV4dChjb250ZXh0LCBpLCBiaW5kaW5nVmFsdWUsIGNvdW50SWQsIHNvdXJjZUluZGV4KTtcbiAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBpICs9IGVudHJpZXNQZXJSb3c7XG4gIH1cblxuICBpZiAoIWZvdW5kKSB7XG4gICAgYWxsb2NhdGVOZXdDb250ZXh0RW50cnkoY29udGV4dCwgY29udGV4dC5sZW5ndGgsIHByb3AsIHNhbml0aXphdGlvblJlcXVpcmVkKTtcbiAgICBhZGRCaW5kaW5nSW50b0NvbnRleHQoY29udGV4dCwgaSwgYmluZGluZ1ZhbHVlLCBjb3VudElkLCBzb3VyY2VJbmRleCk7XG4gIH1cbn1cblxuLyoqXG4gKiBJbnNlcnRzIGEgbmV3IHJvdyBpbnRvIHRoZSBwcm92aWRlZCBgVFN0eWxpbmdDb250ZXh0YCBhbmQgYXNzaWducyB0aGUgcHJvdmlkZWQgYHByb3BgIHZhbHVlIGFzXG4gKiB0aGUgcHJvcGVydHkgZW50cnkuXG4gKi9cbmZ1bmN0aW9uIGFsbG9jYXRlTmV3Q29udGV4dEVudHJ5KFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgaW5kZXg6IG51bWJlciwgcHJvcDogc3RyaW5nLCBzYW5pdGl6YXRpb25SZXF1aXJlZD86IGJvb2xlYW4pOiB2b2lkIHtcbiAgY29uc3QgY29uZmlnID0gc2FuaXRpemF0aW9uUmVxdWlyZWQgPyBUU3R5bGluZ0NvbnRleHRQcm9wQ29uZmlnRmxhZ3MuU2FuaXRpemF0aW9uUmVxdWlyZWQgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRTdHlsaW5nQ29udGV4dFByb3BDb25maWdGbGFncy5EZWZhdWx0O1xuICBjb250ZXh0LnNwbGljZShcbiAgICAgIGluZGV4LCAwLFxuICAgICAgY29uZmlnLCAgICAgICAgICAgICAgICAgICAgLy8gMSkgY29uZmlnIHZhbHVlXG4gICAgICBERUZBVUxUX0dVQVJEX01BU0tfVkFMVUUsICAvLyAyKSB0ZW1wbGF0ZSBiaXQgbWFza1xuICAgICAgREVGQVVMVF9HVUFSRF9NQVNLX1ZBTFVFLCAgLy8gMykgaG9zdCBiaW5kaW5ncyBiaXQgbWFza1xuICAgICAgcHJvcCwgICAgICAgICAgICAgICAgICAgICAgLy8gNCkgcHJvcCB2YWx1ZSAoZS5nLiBgd2lkdGhgLCBgbXlDbGFzc2AsIGV0Yy4uLilcbiAgICAgICk7XG5cbiAgaW5kZXggKz0gNDsgIC8vIHRoZSA0IHZhbHVlcyBhYm92ZVxuXG4gIC8vIDUuLi4pIGRlZmF1bHQgYmluZGluZyBpbmRleCBmb3IgdGhlIHRlbXBsYXRlIHZhbHVlXG4gIC8vIGRlcGVuZGluZyBvbiBob3cgbWFueSBzb3VyY2VzIGFscmVhZHkgZXhpc3QgaW4gdGhlIGNvbnRleHQsXG4gIC8vIG11bHRpcGxlIGRlZmF1bHQgaW5kZXggZW50cmllcyBtYXkgbmVlZCB0byBiZSBpbnNlcnRlZCBmb3JcbiAgLy8gdGhlIG5ldyB2YWx1ZSBpbiB0aGUgY29udGV4dC5cbiAgY29uc3QgdG90YWxCaW5kaW5nc1BlckVudHJ5ID0gZ2V0VG90YWxTb3VyY2VzKGNvbnRleHQpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHRvdGFsQmluZGluZ3NQZXJFbnRyeTsgaSsrKSB7XG4gICAgY29udGV4dC5zcGxpY2UoaW5kZXgsIDAsIERFRkFVTFRfQklORElOR19JTkRFWCk7XG4gICAgaW5kZXgrKztcbiAgfVxuXG4gIC8vIDYpIGRlZmF1bHQgYmluZGluZyB2YWx1ZSBmb3IgdGhlIG5ldyBlbnRyeVxuICBjb250ZXh0LnNwbGljZShpbmRleCwgMCwgREVGQVVMVF9CSU5ESU5HX1ZBTFVFKTtcbn1cblxuLyoqXG4gKiBJbnNlcnRzIGEgbmV3IGJpbmRpbmcgdmFsdWUgaW50byBhIHN0eWxpbmcgcHJvcGVydHkgdHVwbGUgaW4gdGhlIGBUU3R5bGluZ0NvbnRleHRgLlxuICpcbiAqIEEgYmluZGluZ1ZhbHVlIGlzIGluc2VydGVkIGludG8gYSBjb250ZXh0IGR1cmluZyB0aGUgZmlyc3QgdXBkYXRlIHBhc3NcbiAqIG9mIGEgdGVtcGxhdGUgb3IgaG9zdCBiaW5kaW5ncyBmdW5jdGlvbi4gV2hlbiB0aGlzIG9jY3VycywgdHdvIHRoaW5nc1xuICogaGFwcGVuOlxuICpcbiAqIC0gSWYgdGhlIGJpbmRpbmdWYWx1ZSB2YWx1ZSBpcyBhIG51bWJlciB0aGVuIGl0IGlzIHRyZWF0ZWQgYXMgYSBiaW5kaW5nSW5kZXhcbiAqICAgdmFsdWUgKGEgaW5kZXggaW4gdGhlIGBMVmlld2ApIGFuZCBpdCB3aWxsIGJlIGluc2VydGVkIG5leHQgdG8gdGhlIG90aGVyXG4gKiAgIGJpbmRpbmcgaW5kZXggZW50cmllcy5cbiAqXG4gKiAtIE90aGVyd2lzZSB0aGUgYmluZGluZyB2YWx1ZSB3aWxsIHVwZGF0ZSB0aGUgZGVmYXVsdCB2YWx1ZSBmb3IgdGhlIHByb3BlcnR5XG4gKiAgIGFuZCB0aGlzIHdpbGwgb25seSBoYXBwZW4gaWYgdGhlIGRlZmF1bHQgdmFsdWUgaXMgYG51bGxgLlxuICovXG5mdW5jdGlvbiBhZGRCaW5kaW5nSW50b0NvbnRleHQoXG4gICAgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LCBpbmRleDogbnVtYmVyLCBiaW5kaW5nVmFsdWU6IG51bWJlciB8IHN0cmluZyB8IGJvb2xlYW4gfCBudWxsLFxuICAgIGJpdEluZGV4OiBudW1iZXIsIHNvdXJjZUluZGV4OiBudW1iZXIpIHtcbiAgaWYgKHR5cGVvZiBiaW5kaW5nVmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgY29uc3QgaG9zdEJpbmRpbmdzTW9kZSA9IGlzSG9zdFN0eWxpbmdBY3RpdmUoc291cmNlSW5kZXgpO1xuICAgIGNvbnN0IGNlbGxJbmRleCA9IGluZGV4ICsgVFN0eWxpbmdDb250ZXh0SW5kZXguQmluZGluZ3NTdGFydE9mZnNldCArIHNvdXJjZUluZGV4O1xuICAgIGNvbnRleHRbY2VsbEluZGV4XSA9IGJpbmRpbmdWYWx1ZTtcbiAgICBjb25zdCB1cGRhdGVkQml0TWFzayA9IGdldEd1YXJkTWFzayhjb250ZXh0LCBpbmRleCwgaG9zdEJpbmRpbmdzTW9kZSkgfCAoMSA8PCBiaXRJbmRleCk7XG4gICAgc2V0R3VhcmRNYXNrKGNvbnRleHQsIGluZGV4LCB1cGRhdGVkQml0TWFzaywgaG9zdEJpbmRpbmdzTW9kZSk7XG4gIH0gZWxzZSBpZiAoYmluZGluZ1ZhbHVlICE9PSBudWxsICYmIGdldERlZmF1bHRWYWx1ZShjb250ZXh0LCBpbmRleCkgPT09IG51bGwpIHtcbiAgICBzZXREZWZhdWx0VmFsdWUoY29udGV4dCwgaW5kZXgsIGJpbmRpbmdWYWx1ZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBuZXcgY29sdW1uIGludG8gdGhlIHByb3ZpZGVkIGBUU3R5bGluZ0NvbnRleHRgLlxuICpcbiAqIElmIGFuZCB3aGVuIGEgbmV3IHNvdXJjZSBpcyBkZXRlY3RlZCB0aGVuIGEgbmV3IGNvbHVtbiBuZWVkcyB0b1xuICogYmUgYWxsb2NhdGVkIGludG8gdGhlIHN0eWxpbmcgY29udGV4dC4gVGhlIGNvbHVtbiBpcyBiYXNpY2FsbHlcbiAqIGEgbmV3IGFsbG9jYXRpb24gb2YgYmluZGluZyBzb3VyY2VzIHRoYXQgd2lsbCBiZSBhdmFpbGFibGUgdG8gZWFjaFxuICogcHJvcGVydHkuXG4gKlxuICogRWFjaCBjb2x1bW4gdGhhdCBleGlzdHMgaW4gdGhlIHN0eWxpbmcgY29udGV4dCByZXNlbWJsZXMgYSBzdHlsaW5nXG4gKiBzb3VyY2UuIEEgc3R5bGluZyBzb3VyY2UgYW4gZWl0aGVyIGJlIHRoZSB0ZW1wbGF0ZSBvciBvbmUgb3IgbW9yZVxuICogY29tcG9uZW50cyBvciBkaXJlY3RpdmVzIGFsbCBjb250YWluaW5nIHN0eWxpbmcgaG9zdCBiaW5kaW5ncy5cbiAqL1xuZnVuY3Rpb24gYWRkTmV3U291cmNlQ29sdW1uKGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCk6IHZvaWQge1xuICAvLyB3ZSB1c2UgLTEgaGVyZSBiZWNhdXNlIHdlIHdhbnQgdG8gaW5zZXJ0IHJpZ2h0IGJlZm9yZSB0aGUgbGFzdCB2YWx1ZSAodGhlIGRlZmF1bHQgdmFsdWUpXG4gIGNvbnN0IGluc2VydE9mZnNldCA9IFRTdHlsaW5nQ29udGV4dEluZGV4LkJpbmRpbmdzU3RhcnRPZmZzZXQgKyBnZXRWYWx1ZXNDb3VudChjb250ZXh0KSAtIDE7XG5cbiAgbGV0IGluZGV4ID0gVFN0eWxpbmdDb250ZXh0SW5kZXguVmFsdWVzU3RhcnRQb3NpdGlvbjtcbiAgd2hpbGUgKGluZGV4IDwgY29udGV4dC5sZW5ndGgpIHtcbiAgICBpbmRleCArPSBpbnNlcnRPZmZzZXQ7XG4gICAgY29udGV4dC5zcGxpY2UoaW5kZXgrKywgMCwgREVGQVVMVF9CSU5ESU5HX0lOREVYKTtcblxuICAgIC8vIHRoZSB2YWx1ZSB3YXMgaW5zZXJ0ZWQganVzdCBiZWZvcmUgdGhlIGRlZmF1bHQgdmFsdWUsIGJ1dCB0aGVcbiAgICAvLyBuZXh0IGVudHJ5IGluIHRoZSBjb250ZXh0IHN0YXJ0cyBqdXN0IGFmdGVyIGl0LiBUaGVyZWZvcmUrKy5cbiAgICBpbmRleCsrO1xuICB9XG4gIGNvbnRleHRbVFN0eWxpbmdDb250ZXh0SW5kZXguVG90YWxTb3VyY2VzUG9zaXRpb25dKys7XG59XG5cbi8qKlxuICogQXBwbGllcyBhbGwgcGVuZGluZyBzdHlsZSBhbmQgY2xhc3MgYmluZGluZ3MgdG8gdGhlIHByb3ZpZGVkIGVsZW1lbnQuXG4gKlxuICogVGhpcyBmdW5jdGlvbiB3aWxsIGF0dGVtcHQgdG8gZmx1c2ggc3R5bGluZyB2aWEgdGhlIHByb3ZpZGVkIGBjbGFzc2VzQ29udGV4dGBcbiAqIGFuZCBgc3R5bGVzQ29udGV4dGAgY29udGV4dCB2YWx1ZXMuIFRoaXMgZnVuY3Rpb24gaXMgZGVzaWduZWQgdG8gYmUgcnVuIGZyb21cbiAqIHRoZSBpbnRlcm5hbCBgc3R5bGluZ0FwcGx5YCBmdW5jdGlvbiAod2hpY2ggaXMgc2NoZWR1bGVkIHRvIHJ1biBhdCB0aGUgdmVyeVxuICogZW5kIG9mIGNoYW5nZSBkZXRlY3Rpb24gZm9yIGFuIGVsZW1lbnQgaWYgb25lIG9yIG1vcmUgc3R5bGUvY2xhc3MgYmluZGluZ3NcbiAqIHdlcmUgcHJvY2Vzc2VkKSBhbmQgd2lsbCByZWx5IG9uIGFueSBzdGF0ZSB2YWx1ZXMgdGhhdCBhcmUgc2V0IGZyb20gd2hlblxuICogYW55IG9mIHRoZSBzdHlsaW5nIGJpbmRpbmdzIGV4ZWN1dGVkLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgZGVzaWduZWQgdG8gYmUgY2FsbGVkIHR3aWNlOiBvbmUgd2hlbiBjaGFuZ2UgZGV0ZWN0aW9uIGhhc1xuICogcHJvY2Vzc2VkIGFuIGVsZW1lbnQgd2l0aGluIHRoZSB0ZW1wbGF0ZSBiaW5kaW5ncyAoaS5lLiBqdXN0IGFzIGBhZHZhbmNlKClgXG4gKiBpcyBjYWxsZWQpIGFuZCB3aGVuIGhvc3QgYmluZGluZ3MgaGF2ZSBiZWVuIHByb2Nlc3NlZC4gSW4gYm90aCBjYXNlcyB0aGVcbiAqIHN0eWxlcyBhbmQgY2xhc3NlcyBpbiBib3RoIGNvbnRleHRzIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgZWxlbWVudCwgYnV0IHRoZVxuICogYWxnb3JpdGhtIHdpbGwgc2VsZWN0aXZlbHkgZGVjaWRlIHdoaWNoIGJpbmRpbmdzIHRvIHJ1biBkZXBlbmRpbmcgb24gdGhlXG4gKiBjb2x1bW5zIGluIHRoZSBjb250ZXh0LiBUaGUgcHJvdmlkZWQgYGRpcmVjdGl2ZUluZGV4YCB2YWx1ZSB3aWxsIGhlbHAgdGhlXG4gKiBhbGdvcml0aG0gZGV0ZXJtaW5lIHdoaWNoIGJpbmRpbmdzIHRvIGFwcGx5OiBlaXRoZXIgdGhlIHRlbXBsYXRlIGJpbmRpbmdzIG9yXG4gKiB0aGUgaG9zdCBiaW5kaW5ncyAoc2VlIGBhcHBseVN0eWxpbmdUb0VsZW1lbnRgIGZvciBtb3JlIGluZm9ybWF0aW9uKS5cbiAqXG4gKiBOb3RlIHRoYXQgb25jZSB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBhbGwgdGVtcG9yYXJ5IHN0eWxpbmcgc3RhdGUgZGF0YVxuICogKGkuZS4gdGhlIGBiaXRNYXNrYCBhbmQgYGNvdW50ZXJgIHZhbHVlcyBmb3Igc3R5bGVzIGFuZCBjbGFzc2VzIHdpbGwgYmUgY2xlYXJlZCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbHVzaFN0eWxpbmcoXG4gICAgcmVuZGVyZXI6IFJlbmRlcmVyMyB8IFByb2NlZHVyYWxSZW5kZXJlcjMgfCBudWxsLCBkYXRhOiBMU3R5bGluZ0RhdGEsIHROb2RlOiBUU3R5bGluZ05vZGUsXG4gICAgY2xhc3Nlc0NvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCB8IG51bGwsIHN0eWxlc0NvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCB8IG51bGwsXG4gICAgZWxlbWVudDogUkVsZW1lbnQsIGRpcmVjdGl2ZUluZGV4OiBudW1iZXIsIHN0eWxlU2FuaXRpemVyOiBTdHlsZVNhbml0aXplRm4gfCBudWxsLFxuICAgIGZpcnN0VXBkYXRlUGFzczogYm9vbGVhbik6IHZvaWQge1xuICBuZ0Rldk1vZGUgJiYgbmdEZXZNb2RlLmZsdXNoU3R5bGluZysrO1xuXG4gIGNvbnN0IHN0YXRlID0gZ2V0U3R5bGluZ1N0YXRlKGVsZW1lbnQsIGRpcmVjdGl2ZUluZGV4KTtcbiAgY29uc3QgaG9zdEJpbmRpbmdzTW9kZSA9IGlzSG9zdFN0eWxpbmdBY3RpdmUoc3RhdGUuc291cmNlSW5kZXgpO1xuXG4gIGlmIChzdHlsZXNDb250ZXh0KSB7XG4gICAgZmlyc3RVcGRhdGVQYXNzICYmIHN5bmNDb250ZXh0SW5pdGlhbFN0eWxpbmcoc3R5bGVzQ29udGV4dCwgdE5vZGUsIGZhbHNlKTtcblxuICAgIGlmIChzdGF0ZS5zdHlsZXNCaXRNYXNrICE9PSAwKSB7XG4gICAgICBhcHBseVN0eWxpbmdWaWFDb250ZXh0KFxuICAgICAgICAgIHN0eWxlc0NvbnRleHQsIHROb2RlLCByZW5kZXJlciwgZWxlbWVudCwgZGF0YSwgc3RhdGUuc3R5bGVzQml0TWFzaywgc2V0U3R5bGUsXG4gICAgICAgICAgc3R5bGVTYW5pdGl6ZXIsIGhvc3RCaW5kaW5nc01vZGUsIGZhbHNlKTtcbiAgICB9XG4gIH1cblxuICBpZiAoY2xhc3Nlc0NvbnRleHQpIHtcbiAgICBmaXJzdFVwZGF0ZVBhc3MgJiYgc3luY0NvbnRleHRJbml0aWFsU3R5bGluZyhjbGFzc2VzQ29udGV4dCwgdE5vZGUsIHRydWUpO1xuXG4gICAgaWYgKHN0YXRlLmNsYXNzZXNCaXRNYXNrICE9PSAwKSB7XG4gICAgICBhcHBseVN0eWxpbmdWaWFDb250ZXh0KFxuICAgICAgICAgIGNsYXNzZXNDb250ZXh0LCB0Tm9kZSwgcmVuZGVyZXIsIGVsZW1lbnQsIGRhdGEsIHN0YXRlLmNsYXNzZXNCaXRNYXNrLCBzZXRDbGFzcywgbnVsbCxcbiAgICAgICAgICBob3N0QmluZGluZ3NNb2RlLCB0cnVlKTtcbiAgICB9XG4gIH1cblxuICByZXNldFN0eWxpbmdTdGF0ZSgpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbGwgc3RhdGljIHN0eWxpbmcgdmFsdWVzIGludG8gdGhlIGNvbnRleHQgYXMgZGVmYXVsdCB2YWx1ZXMuXG4gKlxuICogU3RhdGljIHN0eWxlcyBhcmUgc3RvcmVkIG9uIHRoZSBgdE5vZGUuc3R5bGVzYCBhbmQgYHROb2RlLmNsYXNzZXNgXG4gKiBwcm9wZXJ0aWVzIGFzIGluc3RhbmNlcyBvZiBgU3R5bGluZ01hcEFycmF5YC4gV2hlbiBhbiBpbnN0YW5jZSBvZlxuICogYFRTdHlsaW5nQ29udGV4dGAgaXMgYXNzaWduZWQgdG8gYHROb2RlLnN0eWxlc2AgYW5kIGB0Tm9kZS5jbGFzc2VzYFxuICogdGhlbiB0aGUgZXhpc3RpbmcgaW5pdGlhbCBzdHlsaW5nIHZhbHVlcyBhcmUgY29waWVkIGludG8gdGhlIHRoZVxuICogYEluaXRpYWxTdHlsaW5nVmFsdWVQb3NpdGlvbmAgc2xvdC5cbiAqXG4gKiBCZWNhdXNlIGFsbCBzdGF0aWMgc3R5bGVzL2NsYXNzZXMgYXJlIGNvbGxlY3RlZCBhbmQgcmVnaXN0ZXJlZCBvblxuICogdGhlIGluaXRpYWwgc3R5bGluZyBhcnJheSBlYWNoIHRpbWUgYSBkaXJlY3RpdmUgaXMgaW5zdGFudGlhdGVkLFxuICogdGhlIGNvbnRleHQgbWF5IG5vdCB5ZXQga25vdyBhYm91dCB0aGUgc3RhdGljIHZhbHVlcy4gV2hlbiB0aGlzXG4gKiBmdW5jdGlvbiBpcyBjYWxsZWQgaXQgd2lsbCBjb3B5IG92ZXIgYWxsIHRoZSBzdGF0aWMgc3R5bGUvY2xhc3NcbiAqIHZhbHVlcyBmcm9tIHRoZSBpbml0aWFsIHN0eWxpbmcgYXJyYXkgaW50byB0aGUgY29udGV4dCBhcyBkZWZhdWx0XG4gKiB2YWx1ZXMgZm9yIGVhY2ggb2YgdGhlIG1hdGNoaW5nIGVudHJpZXMgaW4gdGhlIGNvbnRleHQuXG4gKlxuICogTGV0J3MgaW1hZ2luZSB0aGUgZm9sbG93aW5nIGV4YW1wbGU6XG4gKlxuICogYGBgaHRtbFxuICogPGRpdiBzdHlsZT1cImNvbG9yOnJlZFwiXG4gKiAgICAgW3N0eWxlLmNvbG9yXT1cIm15Q29sb3JcIlxuICogICAgIGRpci10aGF0LWhhcy1zdGF0aWMtaGVpZ2h0PlxuICogICAuLi5cbiAqIDwvZGl2PlxuICogYGBgXG4gKlxuICogV2hlbiB0aGUgY29kZSBhYm92ZSBpcyBwcm9jZXNzZWQsIHRoZSB1bmRlcmx5aW5nIGVsZW1lbnQvc3R5bGluZ1xuICogaW5zdHJ1Y3Rpb25zIHdpbGwgY3JlYXRlIGFuIGluc3RhbmNlIG9mIGBUU3R5bGluZ0NvbnRleHRgIGZvclxuICogdGhlIGB0Tm9kZS5zdHlsZXNgIHByb3BlcnR5LiBIZXJlJ3Mgd2hhdCB0aGF0IGxvb2tzIGxpa2U6XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogdE5vZGUuc3R5bGVzID0gW1xuICogICAvLyAuLi5cbiAqICAgLy8gaW5pdGlhbCBzdHlsZXNcbiAqICAgWydjb2xvcjpyZWQ7IGhlaWdodDoyMDBweCcsICdjb2xvcicsICdyZWQnLCAnaGVpZ2h0JywgJzIwMHB4J10sXG4gKlxuICogICAwLCAwYjEsIDBiMCwgJ2NvbG9yJywgMjAsIG51bGwsIC8vIFtzdHlsZS5jb2xvcl0gYmluZGluZ1xuICogXVxuICogYGBgXG4gKlxuICogQWZ0ZXIgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgaXQgd2lsbCBiYWxhbmNlIG91dCB0aGUgY29udGV4dCB3aXRoXG4gKiB0aGUgc3RhdGljIGBjb2xvcmAgYW5kIGBoZWlnaHRgIHZhbHVlcyBhbmQgc2V0IHRoZW0gYXMgZGVmYXVsdHMgd2l0aGluXG4gKiB0aGUgY29udGV4dDpcbiAqXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiB0Tm9kZS5zdHlsZXMgPSBbXG4gKiAgIC8vIC4uLlxuICogICAvLyBpbml0aWFsIHN0eWxlc1xuICogICBbJ2NvbG9yOnJlZDsgaGVpZ2h0OjIwMHB4JywgJ2NvbG9yJywgJ3JlZCcsICdoZWlnaHQnLCAnMjAwcHgnXSxcbiAqXG4gKiAgIDAsIDBiMSwgMGIwLCAnY29sb3InLCAyMCwgJ3JlZCcsXG4gKiAgIDAsIDBiMCwgMGIwLCAnaGVpZ2h0JywgMCwgJzIwMHB4JyxcbiAqIF1cbiAqIGBgYFxuICovXG5mdW5jdGlvbiBzeW5jQ29udGV4dEluaXRpYWxTdHlsaW5nKFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgdE5vZGU6IFRTdHlsaW5nTm9kZSwgaXNDbGFzc0Jhc2VkOiBib29sZWFuKTogdm9pZCB7XG4gIC8vIHRoZSBUU3R5bGluZ0NvbnRleHQgYWx3YXlzIGhhcyBpbml0aWFsIHN0eWxlL2NsYXNzIHZhbHVlcyB3aGljaCBhcmVcbiAgLy8gc3RvcmVkIGluIHN0eWxpbmcgYXJyYXkgZm9ybWF0LlxuICB1cGRhdGVJbml0aWFsU3R5bGluZ09uQ29udGV4dChjb250ZXh0LCB0Tm9kZSwgZ2V0U3R5bGluZ01hcEFycmF5KGNvbnRleHQpICEsIGlzQ2xhc3NCYXNlZCk7XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIGFsbCBpbml0aWFsIHN0eWxpbmcgZW50cmllcyBpbnRvIHRoZSBwcm92aWRlZCBjb250ZXh0LlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBpdGVyYXRlIG92ZXIgYWxsIGVudHJpZXMgaW4gdGhlIHByb3ZpZGVkIGBpbml0aWFsU3R5bGluZ2AgYXJ9cmF5IGFuZCByZWdpc3RlclxuICogdGhlbSBhcyBkZWZhdWx0IChpbml0aWFsKSB2YWx1ZXMgaW4gdGhlIHByb3ZpZGVkIGNvbnRleHQuIEluaXRpYWwgc3R5bGluZyB2YWx1ZXMgaW4gYSBjb250ZXh0IGFyZVxuICogdGhlIGRlZmF1bHQgdmFsdWVzIHRoYXQgYXJlIHRvIGJlIGFwcGxpZWQgdW5sZXNzIG92ZXJ3cml0dGVuIGJ5IGEgYmluZGluZy5cbiAqXG4gKiBUaGUgcmVhc29uIHdoeSB0aGlzIGZ1bmN0aW9uIGV4aXN0cyBhbmQgaXNuJ3QgYSBwYXJ0IG9mIHRoZSBjb250ZXh0IGNvbnN0cnVjdGlvbiBpcyBiZWNhdXNlXG4gKiBob3N0IGJpbmRpbmcgaXMgZXZhbHVhdGVkIGF0IGEgbGF0ZXIgc3RhZ2UgYWZ0ZXIgdGhlIGVsZW1lbnQgaXMgY3JlYXRlZC4gVGhpcyBtZWFucyB0aGF0XG4gKiBpZiBhIGRpcmVjdGl2ZSBvciBjb21wb25lbnQgY29udGFpbnMgYW55IGluaXRpYWwgc3R5bGluZyBjb2RlIChpLmUuIGA8ZGl2IGNsYXNzPVwiZm9vXCI+YClcbiAqIHRoZW4gdGhhdCBpbml0aWFsIHN0eWxpbmcgZGF0YSBjYW4gb25seSBiZSBhcHBsaWVkIG9uY2UgdGhlIHN0eWxpbmcgZm9yIHRoYXQgZWxlbWVudFxuICogaXMgZmlyc3QgYXBwbGllZCAoYXQgdGhlIGVuZCBvZiB0aGUgdXBkYXRlIHBoYXNlKS4gT25jZSB0aGF0IGhhcHBlbnMgdGhlbiB0aGUgY29udGV4dCB3aWxsXG4gKiB1cGRhdGUgaXRzZWxmIHdpdGggdGhlIGNvbXBsZXRlIGluaXRpYWwgc3R5bGluZyBmb3IgdGhlIGVsZW1lbnQuXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZUluaXRpYWxTdHlsaW5nT25Db250ZXh0KFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgdE5vZGU6IFRTdHlsaW5nTm9kZSwgaW5pdGlhbFN0eWxpbmc6IFN0eWxpbmdNYXBBcnJheSxcbiAgICBpc0NsYXNzQmFzZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgLy8gYC0xYCBpcyB1c2VkIGhlcmUgYmVjYXVzZSBhbGwgaW5pdGlhbCBzdHlsaW5nIGRhdGEgaXMgbm90IGEgYXBhcnRcbiAgLy8gb2YgYSBiaW5kaW5nIChzaW5jZSBpdCdzIHN0YXRpYylcbiAgY29uc3QgQ09VTlRfSURfRk9SX1NUWUxJTkcgPSAtMTtcblxuICBsZXQgaGFzSW5pdGlhbFN0eWxpbmcgPSBmYWxzZTtcbiAgZm9yIChsZXQgaSA9IFN0eWxpbmdNYXBBcnJheUluZGV4LlZhbHVlc1N0YXJ0UG9zaXRpb247IGkgPCBpbml0aWFsU3R5bGluZy5sZW5ndGg7XG4gICAgICAgaSArPSBTdHlsaW5nTWFwQXJyYXlJbmRleC5UdXBsZVNpemUpIHtcbiAgICBjb25zdCB2YWx1ZSA9IGdldE1hcFZhbHVlKGluaXRpYWxTdHlsaW5nLCBpKTtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIGNvbnN0IHByb3AgPSBnZXRNYXBQcm9wKGluaXRpYWxTdHlsaW5nLCBpKTtcbiAgICAgIHJlZ2lzdGVyQmluZGluZyhjb250ZXh0LCB0Tm9kZSwgQ09VTlRfSURfRk9SX1NUWUxJTkcsIDAsIHByb3AsIHZhbHVlLCBmYWxzZSwgaXNDbGFzc0Jhc2VkKTtcbiAgICAgIGhhc0luaXRpYWxTdHlsaW5nID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoaGFzSW5pdGlhbFN0eWxpbmcpIHtcbiAgICBwYXRjaENvbmZpZyh0Tm9kZSwgVE5vZGVGbGFncy5oYXNJbml0aWFsU3R5bGluZyk7XG4gIH1cbn1cblxuLyoqXG4gKiBSdW5zIHRocm91Z2ggdGhlIHByb3ZpZGVkIHN0eWxpbmcgY29udGV4dCBhbmQgYXBwbGllcyBlYWNoIHZhbHVlIHRvXG4gKiB0aGUgcHJvdmlkZWQgZWxlbWVudCAodmlhIHRoZSByZW5kZXJlcikgaWYgb25lIG9yIG1vcmUgdmFsdWVzIGFyZSBwcmVzZW50LlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBpdGVyYXRlIG92ZXIgYWxsIGVudHJpZXMgcHJlc2VudCBpbiB0aGUgcHJvdmlkZWRcbiAqIGBUU3R5bGluZ0NvbnRleHRgIGFycmF5IChib3RoIHByb3AtYmFzZWQgYW5kIG1hcC1iYXNlZCBiaW5kaW5ncykuLVxuICpcbiAqIEVhY2ggZW50cnksIHdpdGhpbiB0aGUgYFRTdHlsaW5nQ29udGV4dGAgYXJyYXksIGlzIHN0b3JlZCBhbHBoYWJldGljYWxseVxuICogYW5kIHRoaXMgbWVhbnMgdGhhdCBlYWNoIHByb3AvdmFsdWUgZW50cnkgd2lsbCBiZSBhcHBsaWVkIGluIG9yZGVyXG4gKiAoc28gbG9uZyBhcyBpdCBpcyBtYXJrZWQgZGlydHkgaW4gdGhlIHByb3ZpZGVkIGBiaXRNYXNrYCB2YWx1ZSkuXG4gKlxuICogSWYgdGhlcmUgYXJlIGFueSBtYXAtYmFzZWQgZW50cmllcyBwcmVzZW50ICh3aGljaCBhcmUgYXBwbGllZCB0byB0aGVcbiAqIGVsZW1lbnQgdmlhIHRoZSBgW3N0eWxlXWAgYW5kIGBbY2xhc3NdYCBiaW5kaW5ncykgdGhlbiB0aG9zZSBlbnRyaWVzXG4gKiB3aWxsIGJlIGFwcGxpZWQgYXMgd2VsbC4gSG93ZXZlciwgdGhlIGNvZGUgZm9yIHRoYXQgaXMgbm90IGEgcGFydCBvZlxuICogdGhpcyBmdW5jdGlvbi4gSW5zdGVhZCwgZWFjaCB0aW1lIGEgcHJvcGVydHkgaXMgdmlzaXRlZCwgdGhlbiB0aGVcbiAqIGNvZGUgYmVsb3cgd2lsbCBjYWxsIGFuIGV4dGVybmFsIGZ1bmN0aW9uIGNhbGxlZCBgc3R5bGluZ01hcHNTeW5jRm5gXG4gKiBhbmQsIGlmIHByZXNlbnQsIGl0IHdpbGwga2VlcCB0aGUgYXBwbGljYXRpb24gb2Ygc3R5bGluZyB2YWx1ZXMgaW5cbiAqIG1hcC1iYXNlZCBiaW5kaW5ncyB1cCB0byBzeW5jIHdpdGggdGhlIGFwcGxpY2F0aW9uIG9mIHByb3AtYmFzZWRcbiAqIGJpbmRpbmdzLlxuICpcbiAqIFZpc2l0IGBzdHlsaW5nL21hcF9iYXNlZF9iaW5kaW5ncy50c2AgdG8gbGVhcm4gbW9yZSBhYm91dCBob3cgdGhlXG4gKiBhbGdvcml0aG0gd29ya3MgZm9yIG1hcC1iYXNlZCBzdHlsaW5nIGJpbmRpbmdzLlxuICpcbiAqIE5vdGUgdGhhdCB0aGlzIGZ1bmN0aW9uIGlzIG5vdCBkZXNpZ25lZCB0byBiZSBjYWxsZWQgaW4gaXNvbGF0aW9uICh1c2VcbiAqIHRoZSBgZmx1c2hTdHlsaW5nYCBmdW5jdGlvbiBzbyB0aGF0IGl0IGNhbiBjYWxsIHRoaXMgZnVuY3Rpb24gZm9yIGJvdGhcbiAqIHRoZSBzdHlsZXMgYW5kIGNsYXNzZXMgY29udGV4dHMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlTdHlsaW5nVmlhQ29udGV4dChcbiAgICBjb250ZXh0OiBUU3R5bGluZ0NvbnRleHQsIHROb2RlOiBUU3R5bGluZ05vZGUsIHJlbmRlcmVyOiBSZW5kZXJlcjMgfCBQcm9jZWR1cmFsUmVuZGVyZXIzIHwgbnVsbCxcbiAgICBlbGVtZW50OiBSRWxlbWVudCwgYmluZGluZ0RhdGE6IExTdHlsaW5nRGF0YSwgYml0TWFza1ZhbHVlOiBudW1iZXIgfCBib29sZWFuLFxuICAgIGFwcGx5U3R5bGluZ0ZuOiBBcHBseVN0eWxpbmdGbiwgc2FuaXRpemVyOiBTdHlsZVNhbml0aXplRm4gfCBudWxsLCBob3N0QmluZGluZ3NNb2RlOiBib29sZWFuLFxuICAgIGlzQ2xhc3NCYXNlZDogYm9vbGVhbik6IHZvaWQge1xuICBjb25zdCBiaXRNYXNrID0gbm9ybWFsaXplQml0TWFza1ZhbHVlKGJpdE1hc2tWYWx1ZSk7XG5cbiAgbGV0IHN0eWxpbmdNYXBzU3luY0ZuOiBTeW5jU3R5bGluZ01hcHNGbnxudWxsID0gbnVsbDtcbiAgbGV0IGFwcGx5QWxsVmFsdWVzID0gZmFsc2U7XG4gIGNvbnN0IG1hcEJpbmRpbmdzRmxhZyA9XG4gICAgICBpc0NsYXNzQmFzZWQgPyBUTm9kZUZsYWdzLmhhc0NsYXNzTWFwQmluZGluZ3MgOiBUTm9kZUZsYWdzLmhhc1N0eWxlTWFwQmluZGluZ3M7XG4gIGlmIChoYXNDb25maWcodE5vZGUsIG1hcEJpbmRpbmdzRmxhZykpIHtcbiAgICBzdHlsaW5nTWFwc1N5bmNGbiA9IGdldFN0eWxpbmdNYXBzU3luY0ZuKCk7XG4gICAgY29uc3QgbWFwc0d1YXJkTWFzayA9XG4gICAgICAgIGdldEd1YXJkTWFzayhjb250ZXh0LCBUU3R5bGluZ0NvbnRleHRJbmRleC5WYWx1ZXNTdGFydFBvc2l0aW9uLCBob3N0QmluZGluZ3NNb2RlKTtcbiAgICBhcHBseUFsbFZhbHVlcyA9IChiaXRNYXNrICYgbWFwc0d1YXJkTWFzaykgIT09IDA7XG4gIH1cblxuICBjb25zdCB2YWx1ZXNDb3VudCA9IGdldFZhbHVlc0NvdW50KGNvbnRleHQpO1xuICBsZXQgdG90YWxCaW5kaW5nc1RvVmlzaXQgPSAxO1xuICBsZXQgbWFwc01vZGUgPVxuICAgICAgYXBwbHlBbGxWYWx1ZXMgPyBTdHlsaW5nTWFwc1N5bmNNb2RlLkFwcGx5QWxsVmFsdWVzIDogU3R5bGluZ01hcHNTeW5jTW9kZS5UcmF2ZXJzZVZhbHVlcztcbiAgaWYgKGhvc3RCaW5kaW5nc01vZGUpIHtcbiAgICBtYXBzTW9kZSB8PSBTdHlsaW5nTWFwc1N5bmNNb2RlLlJlY3Vyc2VJbm5lck1hcHM7XG4gICAgdG90YWxCaW5kaW5nc1RvVmlzaXQgPSB2YWx1ZXNDb3VudCAtIDE7XG4gIH1cblxuICBsZXQgaSA9IGdldFByb3BWYWx1ZXNTdGFydFBvc2l0aW9uKGNvbnRleHQsIHROb2RlLCBpc0NsYXNzQmFzZWQpO1xuICB3aGlsZSAoaSA8IGNvbnRleHQubGVuZ3RoKSB7XG4gICAgY29uc3QgZ3VhcmRNYXNrID0gZ2V0R3VhcmRNYXNrKGNvbnRleHQsIGksIGhvc3RCaW5kaW5nc01vZGUpO1xuICAgIGlmIChiaXRNYXNrICYgZ3VhcmRNYXNrKSB7XG4gICAgICBsZXQgdmFsdWVBcHBsaWVkID0gZmFsc2U7XG4gICAgICBjb25zdCBwcm9wID0gZ2V0UHJvcChjb250ZXh0LCBpKTtcbiAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IGdldERlZmF1bHRWYWx1ZShjb250ZXh0LCBpKTtcblxuICAgICAgLy8gUGFydCAxOiBWaXNpdCB0aGUgYFtzdHlsaW5nLnByb3BdYCB2YWx1ZVxuICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0b3RhbEJpbmRpbmdzVG9WaXNpdDsgaisrKSB7XG4gICAgICAgIGNvbnN0IGJpbmRpbmdJbmRleCA9IGdldEJpbmRpbmdWYWx1ZShjb250ZXh0LCBpLCBqKSBhcyBudW1iZXI7XG4gICAgICAgIGlmICghdmFsdWVBcHBsaWVkICYmIGJpbmRpbmdJbmRleCAhPT0gMCkge1xuICAgICAgICAgIGNvbnN0IHZhbHVlID0gZ2V0VmFsdWUoYmluZGluZ0RhdGEsIGJpbmRpbmdJbmRleCk7XG4gICAgICAgICAgaWYgKGlzU3R5bGluZ1ZhbHVlRGVmaW5lZCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGNoZWNrVmFsdWVPbmx5ID0gaG9zdEJpbmRpbmdzTW9kZSAmJiBqID09PSAwO1xuICAgICAgICAgICAgaWYgKCFjaGVja1ZhbHVlT25seSkge1xuICAgICAgICAgICAgICBjb25zdCBmaW5hbFZhbHVlID0gc2FuaXRpemVyICYmIGlzU2FuaXRpemF0aW9uUmVxdWlyZWQoY29udGV4dCwgaSkgP1xuICAgICAgICAgICAgICAgICAgc2FuaXRpemVyKHByb3AsIHZhbHVlLCBTdHlsZVNhbml0aXplTW9kZS5TYW5pdGl6ZU9ubHkpIDpcbiAgICAgICAgICAgICAgICAgIHVud3JhcFNhZmVWYWx1ZSh2YWx1ZSk7XG4gICAgICAgICAgICAgIGFwcGx5U3R5bGluZ0ZuKHJlbmRlcmVyLCBlbGVtZW50LCBwcm9wLCBmaW5hbFZhbHVlLCBiaW5kaW5nSW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFsdWVBcHBsaWVkID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQYXJ0IDI6IFZpc2l0IHRoZSBgW3N0eWxlXWAgb3IgYFtjbGFzc11gIG1hcC1iYXNlZCB2YWx1ZVxuICAgICAgICBpZiAoc3R5bGluZ01hcHNTeW5jRm4pIHtcbiAgICAgICAgICAvLyBkZXRlcm1pbmUgd2hldGhlciBvciBub3QgdG8gYXBwbHkgdGhlIHRhcmdldCBwcm9wZXJ0eSBvciB0byBza2lwIGl0XG4gICAgICAgICAgbGV0IG1vZGUgPSBtYXBzTW9kZSB8ICh2YWx1ZUFwcGxpZWQgPyBTdHlsaW5nTWFwc1N5bmNNb2RlLlNraXBUYXJnZXRQcm9wIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0eWxpbmdNYXBzU3luY01vZGUuQXBwbHlUYXJnZXRQcm9wKTtcblxuICAgICAgICAgIC8vIHRoZSBmaXJzdCBjb2x1bW4gaW4gdGhlIGNvbnRleHQgKHdoZW4gYGogPT0gMGApIGlzIHNwZWNpYWwtY2FzZWQgZm9yXG4gICAgICAgICAgLy8gdGVtcGxhdGUgYmluZGluZ3MuIElmIGFuZCB3aGVuIGhvc3QgYmluZGluZ3MgYXJlIGJlaW5nIHByb2Nlc3NlZCB0aGVuXG4gICAgICAgICAgLy8gdGhlIGZpcnN0IGNvbHVtbiB3aWxsIHN0aWxsIGJlIGl0ZXJhdGVkIG92ZXIsIGJ1dCB0aGUgdmFsdWVzIHdpbGwgb25seVxuICAgICAgICAgIC8vIGJlIGNoZWNrZWQgYWdhaW5zdCAobm90IGFwcGxpZWQpLiBJZiBhbmQgd2hlbiB0aGlzIGhhcHBlbnMgd2UgbmVlZCB0b1xuICAgICAgICAgIC8vIG5vdGlmeSB0aGUgbWFwLWJhc2VkIHN5bmNpbmcgY29kZSB0byBrbm93IG5vdCB0byBhcHBseSB0aGUgdmFsdWVzIGl0XG4gICAgICAgICAgLy8gY29tZXMgYWNyb3NzIGluIHRoZSB2ZXJ5IGZpcnN0IG1hcC1iYXNlZCBiaW5kaW5nICh3aGljaCBpcyBhbHNvIGxvY2F0ZWRcbiAgICAgICAgICAvLyBpbiBjb2x1bW4gemVybykuXG4gICAgICAgICAgaWYgKGhvc3RCaW5kaW5nc01vZGUgJiYgaiA9PT0gMCkge1xuICAgICAgICAgICAgbW9kZSB8PSBTdHlsaW5nTWFwc1N5bmNNb2RlLkNoZWNrVmFsdWVzT25seTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCB2YWx1ZUFwcGxpZWRXaXRoaW5NYXAgPSBzdHlsaW5nTWFwc1N5bmNGbihcbiAgICAgICAgICAgICAgY29udGV4dCwgcmVuZGVyZXIsIGVsZW1lbnQsIGJpbmRpbmdEYXRhLCBqLCBhcHBseVN0eWxpbmdGbiwgc2FuaXRpemVyLCBtb2RlLCBwcm9wLFxuICAgICAgICAgICAgICBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgIHZhbHVlQXBwbGllZCA9IHZhbHVlQXBwbGllZCB8fCB2YWx1ZUFwcGxpZWRXaXRoaW5NYXA7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gUGFydCAzOiBhcHBseSB0aGUgZGVmYXVsdCB2YWx1ZSAoZS5nLiBgPGRpdiBzdHlsZT1cIndpZHRoOjIwMFwiPmAgPT4gYDIwMHB4YCBnZXRzIGFwcGxpZWQpXG4gICAgICAvLyBpZiB0aGUgdmFsdWUgaGFzIG5vdCB5ZXQgYmVlbiBhcHBsaWVkIHRoZW4gYSB0cnV0aHkgdmFsdWUgZG9lcyBub3QgZXhpc3QgaW4gdGhlXG4gICAgICAvLyBwcm9wLWJhc2VkIG9yIG1hcC1iYXNlZCBiaW5kaW5ncyBjb2RlLiBJZiBhbmQgd2hlbiB0aGlzIGhhcHBlbnMsIGp1c3QgYXBwbHkgdGhlXG4gICAgICAvLyBkZWZhdWx0IHZhbHVlIChldmVuIGlmIHRoZSBkZWZhdWx0IHZhbHVlIGlzIGBudWxsYCkuXG4gICAgICBpZiAoIXZhbHVlQXBwbGllZCkge1xuICAgICAgICBhcHBseVN0eWxpbmdGbihyZW5kZXJlciwgZWxlbWVudCwgcHJvcCwgZGVmYXVsdFZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpICs9IFRTdHlsaW5nQ29udGV4dEluZGV4LkJpbmRpbmdzU3RhcnRPZmZzZXQgKyB2YWx1ZXNDb3VudDtcbiAgfVxuXG4gIC8vIHRoZSBtYXAtYmFzZWQgc3R5bGluZyBlbnRyaWVzIG1heSBoYXZlIG5vdCBhcHBsaWVkIGFsbCB0aGVpclxuICAvLyB2YWx1ZXMuIEZvciB0aGlzIHJlYXNvbiwgb25lIG1vcmUgY2FsbCB0byB0aGUgc3luYyBmdW5jdGlvblxuICAvLyBuZWVkcyB0byBiZSBpc3N1ZWQgYXQgdGhlIGVuZC5cbiAgaWYgKHN0eWxpbmdNYXBzU3luY0ZuKSB7XG4gICAgaWYgKGhvc3RCaW5kaW5nc01vZGUpIHtcbiAgICAgIG1hcHNNb2RlIHw9IFN0eWxpbmdNYXBzU3luY01vZGUuQ2hlY2tWYWx1ZXNPbmx5O1xuICAgIH1cbiAgICBzdHlsaW5nTWFwc1N5bmNGbihcbiAgICAgICAgY29udGV4dCwgcmVuZGVyZXIsIGVsZW1lbnQsIGJpbmRpbmdEYXRhLCAwLCBhcHBseVN0eWxpbmdGbiwgc2FuaXRpemVyLCBtYXBzTW9kZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBBcHBsaWVzIHRoZSBwcm92aWRlZCBzdHlsaW5nIG1hcCB0byB0aGUgZWxlbWVudCBkaXJlY3RseSAod2l0aG91dCBjb250ZXh0IHJlc29sdXRpb24pLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgZGVzaWduZWQgdG8gYmUgcnVuIGZyb20gdGhlIHN0eWxpbmcgaW5zdHJ1Y3Rpb25zIGFuZCB3aWxsIGJlIGNhbGxlZFxuICogYXV0b21hdGljYWxseS4gVGhpcyBmdW5jdGlvbiBpcyBpbnRlbmRlZCB0byBiZSB1c2VkIGZvciBwZXJmb3JtYW5jZSByZWFzb25zIGluIHRoZVxuICogZXZlbnQgdGhhdCB0aGVyZSBpcyBubyBuZWVkIHRvIGFwcGx5IHN0eWxpbmcgdmlhIGNvbnRleHQgcmVzb2x1dGlvbi5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGhhcyB0aHJlZSBkaWZmZXJlbnQgY2FzZXMgdGhhdCBjYW4gb2NjdXIgKGZvciBlYWNoIGl0ZW0gaW4gdGhlIG1hcCk6XG4gKlxuICogLSBDYXNlIDE6IEF0dGVtcHQgdG8gYXBwbHkgdGhlIGN1cnJlbnQgdmFsdWUgaW4gdGhlIG1hcCB0byB0aGUgZWxlbWVudCAoaWYgaXQncyBgbm9uIG51bGxgKS5cbiAqXG4gKiAtIENhc2UgMjogSWYgYSBtYXAgdmFsdWUgZmFpbHMgdG8gYmUgYXBwbGllZCB0aGVuIHRoZSBhbGdvcml0aG0gd2lsbCBmaW5kIGEgbWF0Y2hpbmcgZW50cnkgaW5cbiAqICAgICAgICAgICB0aGUgaW5pdGlhbCB2YWx1ZXMgcHJlc2VudCBpbiB0aGUgY29udGV4dCBhbmQgYXR0ZW1wdCB0byBhcHBseSB0aGF0LlxuICpcbiAqIC0gRGVmYXVsdCBDYXNlOiBJZiB0aGUgaW5pdGlhbCB2YWx1ZSBjYW5ub3QgYmUgYXBwbGllZCB0aGVuIGEgZGVmYXVsdCB2YWx1ZSBvZiBgbnVsbGAgd2lsbCBiZVxuICogICAgICAgICAgICAgICAgIGFwcGxpZWQgKHdoaWNoIHdpbGwgcmVtb3ZlIHRoZSBzdHlsZS9jbGFzcyB2YWx1ZSBmcm9tIHRoZSBlbGVtZW50KS5cbiAqXG4gKiBTZWUgYGFsbG93RGlyZWN0U3R5bGluZ0FwcGx5YCB0byBsZWFybiB0aGUgbG9naWMgdXNlZCB0byBkZXRlcm1pbmUgd2hldGhlciBhbnkgc3R5bGUvY2xhc3NcbiAqIGJpbmRpbmdzIGNhbiBiZSBkaXJlY3RseSBhcHBsaWVkLlxuICpcbiAqIEByZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzdHlsaW5nIG1hcCB3YXMgYXBwbGllZCB0byB0aGUgZWxlbWVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5U3R5bGluZ01hcERpcmVjdGx5KFxuICAgIHJlbmRlcmVyOiBhbnksIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgdE5vZGU6IFRTdHlsaW5nTm9kZSwgZWxlbWVudDogUkVsZW1lbnQsXG4gICAgZGF0YTogTFN0eWxpbmdEYXRhLCBiaW5kaW5nSW5kZXg6IG51bWJlciwgdmFsdWU6IHtba2V5OiBzdHJpbmddOiBhbnl9IHwgc3RyaW5nIHwgbnVsbCxcbiAgICBpc0NsYXNzQmFzZWQ6IGJvb2xlYW4sIHNhbml0aXplcjogU3R5bGVTYW5pdGl6ZUZuIHwgbnVsbCwgZm9yY2VVcGRhdGU6IGJvb2xlYW4sXG4gICAgYmluZGluZ1ZhbHVlQ29udGFpbnNJbml0aWFsOiBib29sZWFuKTogdm9pZCB7XG4gIGNvbnN0IG9sZFZhbHVlID0gZ2V0VmFsdWUoZGF0YSwgYmluZGluZ0luZGV4KTtcbiAgaWYgKGZvcmNlVXBkYXRlIHx8IGhhc1ZhbHVlQ2hhbmdlZChvbGRWYWx1ZSwgdmFsdWUpKSB7XG4gICAgY29uc3QgaGFzSW5pdGlhbCA9IGhhc0NvbmZpZyh0Tm9kZSwgVE5vZGVGbGFncy5oYXNJbml0aWFsU3R5bGluZyk7XG4gICAgY29uc3QgaW5pdGlhbFZhbHVlID1cbiAgICAgICAgaGFzSW5pdGlhbCAmJiAhYmluZGluZ1ZhbHVlQ29udGFpbnNJbml0aWFsID8gZ2V0SW5pdGlhbFN0eWxpbmdWYWx1ZShjb250ZXh0KSA6IG51bGw7XG4gICAgc2V0VmFsdWUoZGF0YSwgYmluZGluZ0luZGV4LCB2YWx1ZSk7XG5cbiAgICAvLyB0aGUgY2FjaGVkIHZhbHVlIGlzIHRoZSBsYXN0IHNuYXBzaG90IG9mIHRoZSBzdHlsZSBvciBjbGFzc1xuICAgIC8vIGF0dHJpYnV0ZSB2YWx1ZSBhbmQgaXMgdXNlZCBpbiB0aGUgaWYgc3RhdGVtZW50IGJlbG93IHRvXG4gICAgLy8ga2VlcCB0cmFjayBvZiBpbnRlcm5hbC9leHRlcm5hbCBjaGFuZ2VzLlxuICAgIGNvbnN0IGNhY2hlZFZhbHVlSW5kZXggPSBiaW5kaW5nSW5kZXggKyAxO1xuICAgIGxldCBjYWNoZWRWYWx1ZSA9IGdldFZhbHVlKGRhdGEsIGNhY2hlZFZhbHVlSW5kZXgpO1xuICAgIGlmIChjYWNoZWRWYWx1ZSA9PT0gTk9fQ0hBTkdFKSB7XG4gICAgICBjYWNoZWRWYWx1ZSA9IGluaXRpYWxWYWx1ZTtcbiAgICB9XG4gICAgY2FjaGVkVmFsdWUgPSB0eXBlb2YgY2FjaGVkVmFsdWUgIT09ICdzdHJpbmcnID8gJycgOiBjYWNoZWRWYWx1ZTtcblxuICAgIC8vIElmIGEgY2xhc3Mvc3R5bGUgdmFsdWUgd2FzIG1vZGlmaWVkIGV4dGVybmFsbHkgdGhlbiB0aGUgc3R5bGluZ1xuICAgIC8vIGZhc3QgcGFzcyBjYW5ub3QgZ3VhcmFudGVlIHRoYXQgdGhlIGV4dGVybmFsIHZhbHVlcyBhcmUgcmV0YWluZWQuXG4gICAgLy8gV2hlbiB0aGlzIGhhcHBlbnMsIHRoZSBhbGdvcml0aG0gd2lsbCBiYWlsIG91dCBhbmQgbm90IHdyaXRlIHRvXG4gICAgLy8gdGhlIHN0eWxlIG9yIGNsYXNzTmFtZSBhdHRyaWJ1dGUgZGlyZWN0bHkuXG4gICAgY29uc3QgcHJvcEJpbmRpbmdzRmxhZyA9XG4gICAgICAgIGlzQ2xhc3NCYXNlZCA/IFROb2RlRmxhZ3MuaGFzQ2xhc3NQcm9wQmluZGluZ3MgOiBUTm9kZUZsYWdzLmhhc1N0eWxlUHJvcEJpbmRpbmdzO1xuICAgIGxldCB3cml0ZVRvQXR0ckRpcmVjdGx5ID0gIWhhc0NvbmZpZyh0Tm9kZSwgcHJvcEJpbmRpbmdzRmxhZyk7XG4gICAgaWYgKHdyaXRlVG9BdHRyRGlyZWN0bHkgJiZcbiAgICAgICAgY2hlY2tJZkV4dGVybmFsbHlNb2RpZmllZChlbGVtZW50IGFzIEhUTUxFbGVtZW50LCBjYWNoZWRWYWx1ZSwgaXNDbGFzc0Jhc2VkKSkge1xuICAgICAgd3JpdGVUb0F0dHJEaXJlY3RseSA9IGZhbHNlO1xuICAgICAgaWYgKG9sZFZhbHVlICE9PSBWQUxVRV9JU19FWFRFUk5BTExZX01PRElGSUVEKSB7XG4gICAgICAgIC8vIGRpcmVjdCBzdHlsaW5nIHdpbGwgcmVzZXQgdGhlIGF0dHJpYnV0ZSBlbnRpcmVseSBlYWNoIHRpbWUsXG4gICAgICAgIC8vIGFuZCwgZm9yIHRoaXMgcmVhc29uLCBpZiB0aGUgYWxnb3JpdGhtIGRlY2lkZXMgaXQgY2Fubm90XG4gICAgICAgIC8vIHdyaXRlIHRvIHRoZSBjbGFzcy9zdHlsZSBhdHRyaWJ1dGVzIGRpcmVjdGx5IHRoZW4gaXQgbXVzdFxuICAgICAgICAvLyByZXNldCBhbGwgdGhlIHByZXZpb3VzIHN0eWxlL2NsYXNzIHZhbHVlcyBiZWZvcmUgaXQgc3RhcnRzXG4gICAgICAgIC8vIHRvIGFwcGx5IHZhbHVlcyBpbiB0aGUgbm9uLWRpcmVjdCB3YXkuXG4gICAgICAgIHJlbW92ZVN0eWxpbmdWYWx1ZXMocmVuZGVyZXIsIGVsZW1lbnQsIG9sZFZhbHVlLCBpc0NsYXNzQmFzZWQpO1xuXG4gICAgICAgIC8vIHRoaXMgd2lsbCBpbnN0cnVjdCB0aGUgYWxnb3JpdGhtIG5vdCB0byBhcHBseSBjbGFzcyBvciBzdHlsZVxuICAgICAgICAvLyB2YWx1ZXMgZGlyZWN0bHkgYW55bW9yZS5cbiAgICAgICAgc2V0VmFsdWUoZGF0YSwgY2FjaGVkVmFsdWVJbmRleCwgVkFMVUVfSVNfRVhURVJOQUxMWV9NT0RJRklFRCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHdyaXRlVG9BdHRyRGlyZWN0bHkpIHtcbiAgICAgIGNvbnN0IGluaXRpYWxWYWx1ZSA9XG4gICAgICAgICAgaGFzSW5pdGlhbCAmJiAhYmluZGluZ1ZhbHVlQ29udGFpbnNJbml0aWFsID8gZ2V0SW5pdGlhbFN0eWxpbmdWYWx1ZShjb250ZXh0KSA6IG51bGw7XG4gICAgICBjb25zdCB2YWx1ZVRvQXBwbHkgPVxuICAgICAgICAgIHdyaXRlU3R5bGluZ1ZhbHVlRGlyZWN0bHkocmVuZGVyZXIsIGVsZW1lbnQsIHZhbHVlLCBpc0NsYXNzQmFzZWQsIGluaXRpYWxWYWx1ZSk7XG4gICAgICBzZXRWYWx1ZShkYXRhLCBjYWNoZWRWYWx1ZUluZGV4LCB2YWx1ZVRvQXBwbHkgfHwgbnVsbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGFwcGx5Rm4gPSBpc0NsYXNzQmFzZWQgPyBzZXRDbGFzcyA6IHNldFN0eWxlO1xuICAgICAgY29uc3QgbWFwID0gbm9ybWFsaXplSW50b1N0eWxpbmdNYXAob2xkVmFsdWUsIHZhbHVlLCAhaXNDbGFzc0Jhc2VkKTtcbiAgICAgIGNvbnN0IGluaXRpYWxTdHlsZXMgPSBoYXNJbml0aWFsID8gZ2V0U3R5bGluZ01hcEFycmF5KGNvbnRleHQpIDogbnVsbDtcblxuICAgICAgZm9yIChsZXQgaSA9IFN0eWxpbmdNYXBBcnJheUluZGV4LlZhbHVlc1N0YXJ0UG9zaXRpb247IGkgPCBtYXAubGVuZ3RoO1xuICAgICAgICAgICBpICs9IFN0eWxpbmdNYXBBcnJheUluZGV4LlR1cGxlU2l6ZSkge1xuICAgICAgICBjb25zdCBwcm9wID0gZ2V0TWFwUHJvcChtYXAsIGkpO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGdldE1hcFZhbHVlKG1hcCwgaSk7XG5cbiAgICAgICAgLy8gY2FzZSAxOiBhcHBseSB0aGUgbWFwIHZhbHVlIChpZiBpdCBleGlzdHMpXG4gICAgICAgIGxldCBhcHBsaWVkID1cbiAgICAgICAgICAgIGFwcGx5U3R5bGluZ1ZhbHVlKHJlbmRlcmVyLCBlbGVtZW50LCBwcm9wLCB2YWx1ZSwgYXBwbHlGbiwgYmluZGluZ0luZGV4LCBzYW5pdGl6ZXIpO1xuXG4gICAgICAgIC8vIGNhc2UgMjogYXBwbHkgdGhlIGluaXRpYWwgdmFsdWUgKGlmIGl0IGV4aXN0cylcbiAgICAgICAgaWYgKCFhcHBsaWVkICYmIGluaXRpYWxTdHlsZXMpIHtcbiAgICAgICAgICBhcHBsaWVkID0gZmluZEFuZEFwcGx5TWFwVmFsdWUoXG4gICAgICAgICAgICAgIHJlbmRlcmVyLCBlbGVtZW50LCBhcHBseUZuLCBpbml0aWFsU3R5bGVzLCBwcm9wLCBiaW5kaW5nSW5kZXgsIHNhbml0aXplcik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBkZWZhdWx0IGNhc2U6IGFwcGx5IGBudWxsYCB0byByZW1vdmUgdGhlIHZhbHVlXG4gICAgICAgIGlmICghYXBwbGllZCkge1xuICAgICAgICAgIGFwcGx5Rm4ocmVuZGVyZXIsIGVsZW1lbnQsIHByb3AsIG51bGwsIGJpbmRpbmdJbmRleCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RhdGUgPSBnZXRTdHlsaW5nU3RhdGUoZWxlbWVudCwgVEVNUExBVEVfRElSRUNUSVZFX0lOREVYKTtcbiAgICAgIGlmIChpc0NsYXNzQmFzZWQpIHtcbiAgICAgICAgc3RhdGUubGFzdERpcmVjdENsYXNzTWFwID0gbWFwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RhdGUubGFzdERpcmVjdFN0eWxlTWFwID0gbWFwO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVTdHlsaW5nVmFsdWVEaXJlY3RseShcbiAgICByZW5kZXJlcjogYW55LCBlbGVtZW50OiBSRWxlbWVudCwgdmFsdWU6IHtba2V5OiBzdHJpbmddOiBhbnl9IHwgc3RyaW5nIHwgbnVsbCxcbiAgICBpc0NsYXNzQmFzZWQ6IGJvb2xlYW4sIGluaXRpYWxWYWx1ZTogc3RyaW5nIHwgbnVsbCk6IHN0cmluZyB7XG4gIGxldCB2YWx1ZVRvQXBwbHk6IHN0cmluZztcbiAgaWYgKGlzQ2xhc3NCYXNlZCkge1xuICAgIHZhbHVlVG9BcHBseSA9IHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgPyB2YWx1ZSA6IG9iamVjdFRvQ2xhc3NOYW1lKHZhbHVlKTtcbiAgICBpZiAoaW5pdGlhbFZhbHVlICE9PSBudWxsKSB7XG4gICAgICB2YWx1ZVRvQXBwbHkgPSBjb25jYXRTdHJpbmcoaW5pdGlhbFZhbHVlLCB2YWx1ZVRvQXBwbHksICcgJyk7XG4gICAgfVxuICAgIHNldENsYXNzTmFtZShyZW5kZXJlciwgZWxlbWVudCwgdmFsdWVUb0FwcGx5KTtcbiAgfSBlbHNlIHtcbiAgICB2YWx1ZVRvQXBwbHkgPSBmb3JjZVN0eWxlc0FzU3RyaW5nKHZhbHVlLCB0cnVlKTtcbiAgICBpZiAoaW5pdGlhbFZhbHVlICE9PSBudWxsKSB7XG4gICAgICB2YWx1ZVRvQXBwbHkgPSBpbml0aWFsVmFsdWUgKyAnOycgKyB2YWx1ZVRvQXBwbHk7XG4gICAgfVxuICAgIHNldFN0eWxlQXR0cihyZW5kZXJlciwgZWxlbWVudCwgdmFsdWVUb0FwcGx5KTtcbiAgfVxuICByZXR1cm4gdmFsdWVUb0FwcGx5O1xufVxuXG4vKipcbiAqIEFwcGxpZXMgdGhlIHByb3ZpZGVkIHN0eWxpbmcgcHJvcC92YWx1ZSB0byB0aGUgZWxlbWVudCBkaXJlY3RseSAod2l0aG91dCBjb250ZXh0IHJlc29sdXRpb24pLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgZGVzaWduZWQgdG8gYmUgcnVuIGZyb20gdGhlIHN0eWxpbmcgaW5zdHJ1Y3Rpb25zIGFuZCB3aWxsIGJlIGNhbGxlZFxuICogYXV0b21hdGljYWxseS4gVGhpcyBmdW5jdGlvbiBpcyBpbnRlbmRlZCB0byBiZSB1c2VkIGZvciBwZXJmb3JtYW5jZSByZWFzb25zIGluIHRoZVxuICogZXZlbnQgdGhhdCB0aGVyZSBpcyBubyBuZWVkIHRvIGFwcGx5IHN0eWxpbmcgdmlhIGNvbnRleHQgcmVzb2x1dGlvbi5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGhhcyBmb3VyIGRpZmZlcmVudCBjYXNlcyB0aGF0IGNhbiBvY2N1cjpcbiAqXG4gKiAtIENhc2UgMTogQXBwbHkgdGhlIHByb3ZpZGVkIHByb3AvdmFsdWUgKHN0eWxlIG9yIGNsYXNzKSBlbnRyeSB0byB0aGUgZWxlbWVudFxuICogICAgICAgICAgIChpZiBpdCBpcyBgbm9uIG51bGxgKS5cbiAqXG4gKiAtIENhc2UgMjogSWYgdmFsdWUgZG9lcyBub3QgZ2V0IGFwcGxpZWQgKGJlY2F1c2UgaXRzIGBudWxsYCBvciBgdW5kZWZpbmVkYCkgdGhlbiB0aGUgYWxnb3JpdGhtXG4gKiAgICAgICAgICAgd2lsbCBjaGVjayB0byBzZWUgaWYgYSBzdHlsaW5nIG1hcCB2YWx1ZSB3YXMgYXBwbGllZCB0byB0aGUgZWxlbWVudCBhcyB3ZWxsIGp1c3RcbiAqICAgICAgICAgICBiZWZvcmUgdGhpcyAodmlhIGBzdHlsZU1hcGAgb3IgYGNsYXNzTWFwYCkuIElmIGFuZCB3aGVuIGEgbWFwIGlzIHByZXNlbnQgdGhlbiB0aGVcbiAgKiAgICAgICAgICBhbGdvcml0aG0gd2lsbCBmaW5kIHRoZSBtYXRjaGluZyBwcm9wZXJ0eSBpbiB0aGUgbWFwIGFuZCBhcHBseSBpdHMgdmFsdWUuXG4gICpcbiAqIC0gQ2FzZSAzOiBJZiBhIG1hcCB2YWx1ZSBmYWlscyB0byBiZSBhcHBsaWVkIHRoZW4gdGhlIGFsZ29yaXRobSB3aWxsIGNoZWNrIHRvIHNlZSBpZiB0aGVyZVxuICogICAgICAgICAgIGFyZSBhbnkgaW5pdGlhbCB2YWx1ZXMgcHJlc2VudCBhbmQgYXR0ZW1wdCB0byBhcHBseSBhIG1hdGNoaW5nIHZhbHVlIGJhc2VkIG9uXG4gKiAgICAgICAgICAgdGhlIHRhcmdldCBwcm9wLlxuICpcbiAqIC0gRGVmYXVsdCBDYXNlOiBJZiBhIG1hdGNoaW5nIGluaXRpYWwgdmFsdWUgY2Fubm90IGJlIGFwcGxpZWQgdGhlbiBhIGRlZmF1bHQgdmFsdWVcbiAqICAgICAgICAgICAgICAgICBvZiBgbnVsbGAgd2lsbCBiZSBhcHBsaWVkICh3aGljaCB3aWxsIHJlbW92ZSB0aGUgc3R5bGUvY2xhc3MgdmFsdWVcbiAqICAgICAgICAgICAgICAgICBmcm9tIHRoZSBlbGVtZW50KS5cbiAqXG4gKiBTZWUgYGFsbG93RGlyZWN0U3R5bGluZ0FwcGx5YCB0byBsZWFybiB0aGUgbG9naWMgdXNlZCB0byBkZXRlcm1pbmUgd2hldGhlciBhbnkgc3R5bGUvY2xhc3NcbiAqIGJpbmRpbmdzIGNhbiBiZSBkaXJlY3RseSBhcHBsaWVkLlxuICpcbiAqIEByZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBwcm9wL3ZhbHVlIHN0eWxpbmcgd2FzIGFwcGxpZWQgdG8gdGhlIGVsZW1lbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVN0eWxpbmdWYWx1ZURpcmVjdGx5KFxuICAgIHJlbmRlcmVyOiBhbnksIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgdE5vZGU6IFRTdHlsaW5nTm9kZSwgZWxlbWVudDogUkVsZW1lbnQsXG4gICAgZGF0YTogTFN0eWxpbmdEYXRhLCBiaW5kaW5nSW5kZXg6IG51bWJlciwgcHJvcDogc3RyaW5nLCB2YWx1ZTogYW55LCBpc0NsYXNzQmFzZWQ6IGJvb2xlYW4sXG4gICAgc2FuaXRpemVyPzogU3R5bGVTYW5pdGl6ZUZuIHwgbnVsbCk6IGJvb2xlYW4ge1xuICBsZXQgYXBwbGllZCA9IGZhbHNlO1xuICBpZiAoaGFzVmFsdWVDaGFuZ2VkKGRhdGFbYmluZGluZ0luZGV4XSwgdmFsdWUpKSB7XG4gICAgc2V0VmFsdWUoZGF0YSwgYmluZGluZ0luZGV4LCB2YWx1ZSk7XG4gICAgY29uc3QgYXBwbHlGbiA9IGlzQ2xhc3NCYXNlZCA/IHNldENsYXNzIDogc2V0U3R5bGU7XG5cbiAgICAvLyBjYXNlIDE6IGFwcGx5IHRoZSBwcm92aWRlZCB2YWx1ZSAoaWYgaXQgZXhpc3RzKVxuICAgIGFwcGxpZWQgPSBhcHBseVN0eWxpbmdWYWx1ZShyZW5kZXJlciwgZWxlbWVudCwgcHJvcCwgdmFsdWUsIGFwcGx5Rm4sIGJpbmRpbmdJbmRleCwgc2FuaXRpemVyKTtcblxuICAgIC8vIGNhc2UgMjogZmluZCB0aGUgbWF0Y2hpbmcgcHJvcGVydHkgaW4gYSBzdHlsaW5nIG1hcCBhbmQgYXBwbHkgdGhlIGRldGVjdGVkIHZhbHVlXG4gICAgY29uc3QgbWFwQmluZGluZ3NGbGFnID1cbiAgICAgICAgaXNDbGFzc0Jhc2VkID8gVE5vZGVGbGFncy5oYXNDbGFzc01hcEJpbmRpbmdzIDogVE5vZGVGbGFncy5oYXNTdHlsZU1hcEJpbmRpbmdzO1xuICAgIGlmICghYXBwbGllZCAmJiBoYXNDb25maWcodE5vZGUsIG1hcEJpbmRpbmdzRmxhZykpIHtcbiAgICAgIGNvbnN0IHN0YXRlID0gZ2V0U3R5bGluZ1N0YXRlKGVsZW1lbnQsIFRFTVBMQVRFX0RJUkVDVElWRV9JTkRFWCk7XG4gICAgICBjb25zdCBtYXAgPSBpc0NsYXNzQmFzZWQgPyBzdGF0ZS5sYXN0RGlyZWN0Q2xhc3NNYXAgOiBzdGF0ZS5sYXN0RGlyZWN0U3R5bGVNYXA7XG4gICAgICBhcHBsaWVkID0gbWFwID9cbiAgICAgICAgICBmaW5kQW5kQXBwbHlNYXBWYWx1ZShyZW5kZXJlciwgZWxlbWVudCwgYXBwbHlGbiwgbWFwLCBwcm9wLCBiaW5kaW5nSW5kZXgsIHNhbml0aXplcikgOlxuICAgICAgICAgIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIGNhc2UgMzogYXBwbHkgdGhlIGluaXRpYWwgdmFsdWUgKGlmIGl0IGV4aXN0cylcbiAgICBpZiAoIWFwcGxpZWQgJiYgaGFzQ29uZmlnKHROb2RlLCBUTm9kZUZsYWdzLmhhc0luaXRpYWxTdHlsaW5nKSkge1xuICAgICAgY29uc3QgbWFwID0gZ2V0U3R5bGluZ01hcEFycmF5KGNvbnRleHQpO1xuICAgICAgYXBwbGllZCA9XG4gICAgICAgICAgbWFwID8gZmluZEFuZEFwcGx5TWFwVmFsdWUocmVuZGVyZXIsIGVsZW1lbnQsIGFwcGx5Rm4sIG1hcCwgcHJvcCwgYmluZGluZ0luZGV4KSA6IGZhbHNlO1xuICAgIH1cblxuICAgIC8vIGRlZmF1bHQgY2FzZTogYXBwbHkgYG51bGxgIHRvIHJlbW92ZSB0aGUgdmFsdWVcbiAgICBpZiAoIWFwcGxpZWQpIHtcbiAgICAgIGFwcGx5Rm4ocmVuZGVyZXIsIGVsZW1lbnQsIHByb3AsIG51bGwsIGJpbmRpbmdJbmRleCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBhcHBsaWVkO1xufVxuXG5mdW5jdGlvbiBhcHBseVN0eWxpbmdWYWx1ZShcbiAgICByZW5kZXJlcjogYW55LCBlbGVtZW50OiBSRWxlbWVudCwgcHJvcDogc3RyaW5nLCB2YWx1ZTogYW55LCBhcHBseUZuOiBBcHBseVN0eWxpbmdGbixcbiAgICBiaW5kaW5nSW5kZXg6IG51bWJlciwgc2FuaXRpemVyPzogU3R5bGVTYW5pdGl6ZUZuIHwgbnVsbCk6IGJvb2xlYW4ge1xuICBsZXQgdmFsdWVUb0FwcGx5OiBzdHJpbmd8bnVsbCA9IHVud3JhcFNhZmVWYWx1ZSh2YWx1ZSk7XG4gIGlmIChpc1N0eWxpbmdWYWx1ZURlZmluZWQodmFsdWVUb0FwcGx5KSkge1xuICAgIHZhbHVlVG9BcHBseSA9XG4gICAgICAgIHNhbml0aXplciA/IHNhbml0aXplcihwcm9wLCB2YWx1ZSwgU3R5bGVTYW5pdGl6ZU1vZGUuVmFsaWRhdGVBbmRTYW5pdGl6ZSkgOiB2YWx1ZVRvQXBwbHk7XG4gICAgYXBwbHlGbihyZW5kZXJlciwgZWxlbWVudCwgcHJvcCwgdmFsdWVUb0FwcGx5LCBiaW5kaW5nSW5kZXgpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZmluZEFuZEFwcGx5TWFwVmFsdWUoXG4gICAgcmVuZGVyZXI6IGFueSwgZWxlbWVudDogUkVsZW1lbnQsIGFwcGx5Rm46IEFwcGx5U3R5bGluZ0ZuLCBtYXA6IFN0eWxpbmdNYXBBcnJheSwgcHJvcDogc3RyaW5nLFxuICAgIGJpbmRpbmdJbmRleDogbnVtYmVyLCBzYW5pdGl6ZXI/OiBTdHlsZVNhbml0aXplRm4gfCBudWxsKSB7XG4gIGZvciAobGV0IGkgPSBTdHlsaW5nTWFwQXJyYXlJbmRleC5WYWx1ZXNTdGFydFBvc2l0aW9uOyBpIDwgbWFwLmxlbmd0aDtcbiAgICAgICBpICs9IFN0eWxpbmdNYXBBcnJheUluZGV4LlR1cGxlU2l6ZSkge1xuICAgIGNvbnN0IHAgPSBnZXRNYXBQcm9wKG1hcCwgaSk7XG4gICAgaWYgKHAgPT09IHByb3ApIHtcbiAgICAgIGxldCB2YWx1ZVRvQXBwbHkgPSBnZXRNYXBWYWx1ZShtYXAsIGkpO1xuICAgICAgdmFsdWVUb0FwcGx5ID0gc2FuaXRpemVyID9cbiAgICAgICAgICBzYW5pdGl6ZXIocHJvcCwgdmFsdWVUb0FwcGx5LCBTdHlsZVNhbml0aXplTW9kZS5WYWxpZGF0ZUFuZFNhbml0aXplKSA6XG4gICAgICAgICAgdmFsdWVUb0FwcGx5O1xuICAgICAgYXBwbHlGbihyZW5kZXJlciwgZWxlbWVudCwgcHJvcCwgdmFsdWVUb0FwcGx5LCBiaW5kaW5nSW5kZXgpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChwID4gcHJvcCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplQml0TWFza1ZhbHVlKHZhbHVlOiBudW1iZXIgfCBib29sZWFuKTogbnVtYmVyIHtcbiAgLy8gaWYgcGFzcyA9PiBhcHBseSBhbGwgdmFsdWVzICgtMSBpbXBsaWVzIHRoYXQgYWxsIGJpdHMgYXJlIGZsaXBwZWQgdG8gdHJ1ZSlcbiAgaWYgKHZhbHVlID09PSB0cnVlKSByZXR1cm4gLTE7XG5cbiAgLy8gaWYgcGFzcyA9PiBza2lwIGFsbCB2YWx1ZXNcbiAgaWYgKHZhbHVlID09PSBmYWxzZSkgcmV0dXJuIDA7XG5cbiAgLy8gcmV0dXJuIHRoZSBiaXQgbWFzayB2YWx1ZSBhcyBpc1xuICByZXR1cm4gdmFsdWU7XG59XG5cbmxldCBfYWN0aXZlU3R5bGluZ01hcEFwcGx5Rm46IFN5bmNTdHlsaW5nTWFwc0ZufG51bGwgPSBudWxsO1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0eWxpbmdNYXBzU3luY0ZuKCkge1xuICByZXR1cm4gX2FjdGl2ZVN0eWxpbmdNYXBBcHBseUZuO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0U3R5bGluZ01hcHNTeW5jRm4oZm46IFN5bmNTdHlsaW5nTWFwc0ZuKSB7XG4gIF9hY3RpdmVTdHlsaW5nTWFwQXBwbHlGbiA9IGZuO1xufVxuXG4vKipcbiAqIEFzc2lnbnMgYSBzdHlsZSB2YWx1ZSB0byBhIHN0eWxlIHByb3BlcnR5IGZvciB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAqL1xuZXhwb3J0IGNvbnN0IHNldFN0eWxlOiBBcHBseVN0eWxpbmdGbiA9XG4gICAgKHJlbmRlcmVyOiBSZW5kZXJlcjMgfCBudWxsLCBuYXRpdmU6IFJFbGVtZW50LCBwcm9wOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcgfCBudWxsKSA9PiB7XG4gICAgICBpZiAocmVuZGVyZXIgIT09IG51bGwpIHtcbiAgICAgICAgLy8gVXNlIGBpc1N0eWxpbmdWYWx1ZURlZmluZWRgIHRvIGFjY291bnQgZm9yIGZhbHN5IHZhbHVlcyB0aGF0IHNob3VsZCBiZSBib3VuZCBsaWtlIDAuXG4gICAgICAgIGlmIChpc1N0eWxpbmdWYWx1ZURlZmluZWQodmFsdWUpKSB7XG4gICAgICAgICAgLy8gb3BhY2l0eSwgei1pbmRleCBhbmQgZmxleGJveCBhbGwgaGF2ZSBudW1iZXIgdmFsdWVzXG4gICAgICAgICAgLy8gYW5kIHRoZXNlIG5lZWQgdG8gYmUgY29udmVydGVkIGludG8gc3RyaW5ncyBzbyB0aGF0XG4gICAgICAgICAgLy8gdGhleSBjYW4gYmUgYXNzaWduZWQgcHJvcGVybHkuXG4gICAgICAgICAgdmFsdWUgPSB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgICAgIG5nRGV2TW9kZSAmJiBuZ0Rldk1vZGUucmVuZGVyZXJTZXRTdHlsZSsrO1xuICAgICAgICAgIGlmIChpc1Byb2NlZHVyYWxSZW5kZXJlcihyZW5kZXJlcikpIHtcbiAgICAgICAgICAgIHJlbmRlcmVyLnNldFN0eWxlKG5hdGl2ZSwgcHJvcCwgdmFsdWUsIFJlbmRlcmVyU3R5bGVGbGFnczMuRGFzaENhc2UpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBUaGUgcmVhc29uIHdoeSBuYXRpdmUgc3R5bGUgbWF5IGJlIGBudWxsYCBpcyBlaXRoZXIgYmVjYXVzZVxuICAgICAgICAgICAgLy8gaXQncyBhIGNvbnRhaW5lciBlbGVtZW50IG9yIGl0J3MgYSBwYXJ0IG9mIGEgdGVzdFxuICAgICAgICAgICAgLy8gZW52aXJvbm1lbnQgdGhhdCBkb2Vzbid0IGhhdmUgc3R5bGluZy4gSW4gZWl0aGVyXG4gICAgICAgICAgICAvLyBjYXNlIGl0J3Mgc2FmZSBub3QgdG8gYXBwbHkgc3R5bGluZyB0byB0aGUgZWxlbWVudC5cbiAgICAgICAgICAgIGNvbnN0IG5hdGl2ZVN0eWxlID0gbmF0aXZlLnN0eWxlO1xuICAgICAgICAgICAgaWYgKG5hdGl2ZVN0eWxlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgbmF0aXZlU3R5bGUuc2V0UHJvcGVydHkocHJvcCwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZ0Rldk1vZGUgJiYgbmdEZXZNb2RlLnJlbmRlcmVyUmVtb3ZlU3R5bGUrKztcblxuICAgICAgICAgIGlmIChpc1Byb2NlZHVyYWxSZW5kZXJlcihyZW5kZXJlcikpIHtcbiAgICAgICAgICAgIHJlbmRlcmVyLnJlbW92ZVN0eWxlKG5hdGl2ZSwgcHJvcCwgUmVuZGVyZXJTdHlsZUZsYWdzMy5EYXNoQ2FzZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG5hdGl2ZVN0eWxlID0gbmF0aXZlLnN0eWxlO1xuICAgICAgICAgICAgaWYgKG5hdGl2ZVN0eWxlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgbmF0aXZlU3R5bGUucmVtb3ZlUHJvcGVydHkocHJvcCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuLyoqXG4gKiBBZGRzL3JlbW92ZXMgdGhlIHByb3ZpZGVkIGNsYXNzTmFtZSB2YWx1ZSB0byB0aGUgcHJvdmlkZWQgZWxlbWVudC5cbiAqL1xuZXhwb3J0IGNvbnN0IHNldENsYXNzOiBBcHBseVN0eWxpbmdGbiA9XG4gICAgKHJlbmRlcmVyOiBSZW5kZXJlcjMgfCBudWxsLCBuYXRpdmU6IFJFbGVtZW50LCBjbGFzc05hbWU6IHN0cmluZywgdmFsdWU6IGFueSkgPT4ge1xuICAgICAgaWYgKHJlbmRlcmVyICE9PSBudWxsICYmIGNsYXNzTmFtZSAhPT0gJycpIHtcbiAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgbmdEZXZNb2RlICYmIG5nRGV2TW9kZS5yZW5kZXJlckFkZENsYXNzKys7XG4gICAgICAgICAgaWYgKGlzUHJvY2VkdXJhbFJlbmRlcmVyKHJlbmRlcmVyKSkge1xuICAgICAgICAgICAgcmVuZGVyZXIuYWRkQ2xhc3MobmF0aXZlLCBjbGFzc05hbWUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0aGUgcmVhc29uIHdoeSBjbGFzc0xpc3QgbWF5IGJlIGBudWxsYCBpcyBlaXRoZXIgYmVjYXVzZVxuICAgICAgICAgICAgLy8gaXQncyBhIGNvbnRhaW5lciBlbGVtZW50IG9yIGl0J3MgYSBwYXJ0IG9mIGEgdGVzdFxuICAgICAgICAgICAgLy8gZW52aXJvbm1lbnQgdGhhdCBkb2Vzbid0IGhhdmUgc3R5bGluZy4gSW4gZWl0aGVyXG4gICAgICAgICAgICAvLyBjYXNlIGl0J3Mgc2FmZSBub3QgdG8gYXBwbHkgc3R5bGluZyB0byB0aGUgZWxlbWVudC5cbiAgICAgICAgICAgIGNvbnN0IGNsYXNzTGlzdCA9IG5hdGl2ZS5jbGFzc0xpc3Q7XG4gICAgICAgICAgICBpZiAoY2xhc3NMaXN0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZ0Rldk1vZGUgJiYgbmdEZXZNb2RlLnJlbmRlcmVyUmVtb3ZlQ2xhc3MrKztcbiAgICAgICAgICBpZiAoaXNQcm9jZWR1cmFsUmVuZGVyZXIocmVuZGVyZXIpKSB7XG4gICAgICAgICAgICByZW5kZXJlci5yZW1vdmVDbGFzcyhuYXRpdmUsIGNsYXNzTmFtZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGNsYXNzTGlzdCA9IG5hdGl2ZS5jbGFzc0xpc3Q7XG4gICAgICAgICAgICBpZiAoY2xhc3NMaXN0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbmV4cG9ydCBjb25zdCBzZXRDbGFzc05hbWUgPSAocmVuZGVyZXI6IFJlbmRlcmVyMyB8IG51bGwsIG5hdGl2ZTogUkVsZW1lbnQsIGNsYXNzTmFtZTogc3RyaW5nKSA9PiB7XG4gIGlmIChyZW5kZXJlciAhPT0gbnVsbCkge1xuICAgIGlmIChpc1Byb2NlZHVyYWxSZW5kZXJlcihyZW5kZXJlcikpIHtcbiAgICAgIHJlbmRlcmVyLnNldEF0dHJpYnV0ZShuYXRpdmUsICdjbGFzcycsIGNsYXNzTmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5hdGl2ZS5jbGFzc05hbWUgPSBjbGFzc05hbWU7XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgY29uc3Qgc2V0U3R5bGVBdHRyID0gKHJlbmRlcmVyOiBSZW5kZXJlcjMgfCBudWxsLCBuYXRpdmU6IFJFbGVtZW50LCB2YWx1ZTogc3RyaW5nKSA9PiB7XG4gIGlmIChyZW5kZXJlciAhPT0gbnVsbCkge1xuICAgIGlmIChpc1Byb2NlZHVyYWxSZW5kZXJlcihyZW5kZXJlcikpIHtcbiAgICAgIHJlbmRlcmVyLnNldEF0dHJpYnV0ZShuYXRpdmUsICdzdHlsZScsIHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmF0aXZlLnNldEF0dHJpYnV0ZSgnc3R5bGUnLCB2YWx1ZSk7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEl0ZXJhdGVzIG92ZXIgYWxsIHByb3ZpZGVkIHN0eWxpbmcgZW50cmllcyBhbmQgcmVuZGVycyB0aGVtIG9uIHRoZSBlbGVtZW50LlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCBhbG9uZ3NpZGUgYSBgU3R5bGluZ01hcEFycmF5YCBlbnRyeS4gVGhpcyBlbnRyeSBpcyBub3RcbiAqIHRoZSBzYW1lIGFzIHRoZSBgVFN0eWxpbmdDb250ZXh0YCBhbmQgaXMgb25seSByZWFsbHkgdXNlZCB3aGVuIGFuIGVsZW1lbnQgY29udGFpbnNcbiAqIGluaXRpYWwgc3R5bGluZyB2YWx1ZXMgKGUuZy4gYDxkaXYgc3R5bGU9XCJ3aWR0aDoyMDBweFwiPmApLCBidXQgbm8gc3R5bGUvY2xhc3MgYmluZGluZ3NcbiAqIGFyZSBwcmVzZW50LiBJZiBhbmQgd2hlbiB0aGF0IGhhcHBlbnMgdGhlbiB0aGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIHRvIHJlbmRlciBhbGxcbiAqIGluaXRpYWwgc3R5bGluZyB2YWx1ZXMgb24gYW4gZWxlbWVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlclN0eWxpbmdNYXAoXG4gICAgcmVuZGVyZXI6IFJlbmRlcmVyMywgZWxlbWVudDogUkVsZW1lbnQsIHN0eWxpbmdWYWx1ZXM6IFRTdHlsaW5nQ29udGV4dCB8IFN0eWxpbmdNYXBBcnJheSB8IG51bGwsXG4gICAgaXNDbGFzc0Jhc2VkOiBib29sZWFuKTogdm9pZCB7XG4gIGNvbnN0IHN0eWxpbmdNYXBBcnIgPSBnZXRTdHlsaW5nTWFwQXJyYXkoc3R5bGluZ1ZhbHVlcyk7XG4gIGlmIChzdHlsaW5nTWFwQXJyKSB7XG4gICAgZm9yIChsZXQgaSA9IFN0eWxpbmdNYXBBcnJheUluZGV4LlZhbHVlc1N0YXJ0UG9zaXRpb247IGkgPCBzdHlsaW5nTWFwQXJyLmxlbmd0aDtcbiAgICAgICAgIGkgKz0gU3R5bGluZ01hcEFycmF5SW5kZXguVHVwbGVTaXplKSB7XG4gICAgICBjb25zdCBwcm9wID0gZ2V0TWFwUHJvcChzdHlsaW5nTWFwQXJyLCBpKTtcbiAgICAgIGNvbnN0IHZhbHVlID0gZ2V0TWFwVmFsdWUoc3R5bGluZ01hcEFyciwgaSk7XG4gICAgICBpZiAoaXNDbGFzc0Jhc2VkKSB7XG4gICAgICAgIHNldENsYXNzKHJlbmRlcmVyLCBlbGVtZW50LCBwcm9wLCB2YWx1ZSwgbnVsbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXRTdHlsZShyZW5kZXJlciwgZWxlbWVudCwgcHJvcCwgdmFsdWUsIG51bGwpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBvYmplY3RUb0NsYXNzTmFtZShvYmo6IHtba2V5OiBzdHJpbmddOiBhbnl9IHwgbnVsbCk6IHN0cmluZyB7XG4gIGxldCBzdHIgPSAnJztcbiAgaWYgKG9iaikge1xuICAgIGZvciAobGV0IGtleSBpbiBvYmopIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gb2JqW2tleV07XG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgc3RyICs9IChzdHIubGVuZ3RoID8gJyAnIDogJycpICsga2V5O1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gc3RyO1xufVxuXG4vKipcbiAqIERldGVybWluZXMgd2hldGhlciBvciBub3QgYW4gZWxlbWVudCBzdHlsZS9jbGFzc05hbWUgdmFsdWUgaGFzIGNoYW5nZWQgc2luY2UgdGhlIGxhc3QgdXBkYXRlLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaGVscHMgQW5ndWxhciBkZXRlcm1pbmUgaWYgYSBzdHlsZSBvciBjbGFzcyBhdHRyaWJ1dGUgdmFsdWUgd2FzXG4gKiBtb2RpZmllZCBieSBhbiBleHRlcm5hbCBwbHVnaW4gb3IgQVBJIG91dHNpZGUgb2YgdGhlIHN0eWxlIGJpbmRpbmcgY29kZS4gVGhpc1xuICogbWVhbnMgYW55IEpTIGNvZGUgdGhhdCBhZGRzL3JlbW92ZXMgY2xhc3Mvc3R5bGUgdmFsdWVzIG9uIGFuIGVsZW1lbnQgb3V0c2lkZVxuICogb2YgQW5ndWxhcidzIHN0eWxpbmcgYmluZGluZyBhbGdvcml0aG0uXG4gKlxuICogQHJldHVybnMgdHJ1ZSB3aGVuIHRoZSB2YWx1ZSB3YXMgbW9kaWZpZWQgZXh0ZXJuYWxseS5cbiAqL1xuZnVuY3Rpb24gY2hlY2tJZkV4dGVybmFsbHlNb2RpZmllZChlbGVtZW50OiBIVE1MRWxlbWVudCwgY2FjaGVkVmFsdWU6IGFueSwgaXNDbGFzc0Jhc2VkOiBib29sZWFuKSB7XG4gIC8vIHRoaXMgbWVhbnMgaXQgd2FzIGNoZWNrZWQgYmVmb3JlIGFuZCB0aGVyZSBpcyBubyByZWFzb25cbiAgLy8gdG8gY29tcGFyZSB0aGUgc3R5bGUvY2xhc3MgdmFsdWVzIGFnYWluLiBFaXRoZXIgdGhhdCBvclxuICAvLyB3ZWIgd29ya2VycyBhcmUgYmVpbmcgdXNlZC5cbiAgaWYgKGdsb2JhbC5Ob2RlID09PSAndW5kZWZpbmVkJyB8fCBjYWNoZWRWYWx1ZSA9PT0gVkFMVUVfSVNfRVhURVJOQUxMWV9NT0RJRklFRCkgcmV0dXJuIHRydWU7XG5cbiAgLy8gY29tcGFyaW5nIHRoZSBET00gdmFsdWUgYWdhaW5zdCB0aGUgY2FjaGVkIHZhbHVlIGlzIHRoZSBiZXN0IHdheSB0b1xuICAvLyBzZWUgaWYgc29tZXRoaW5nIGhhcyBjaGFuZ2VkLlxuICBjb25zdCBjdXJyZW50VmFsdWUgPVxuICAgICAgKGlzQ2xhc3NCYXNlZCA/IGVsZW1lbnQuY2xhc3NOYW1lIDogKGVsZW1lbnQuc3R5bGUgJiYgZWxlbWVudC5zdHlsZS5jc3NUZXh0KSkgfHwgJyc7XG4gIHJldHVybiBjdXJyZW50VmFsdWUgIT09IChjYWNoZWRWYWx1ZSB8fCAnJyk7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBwcm92aWRlZCBzdHlsaW5nIHZhbHVlcyBmcm9tIHRoZSBlbGVtZW50XG4gKi9cbmZ1bmN0aW9uIHJlbW92ZVN0eWxpbmdWYWx1ZXMoXG4gICAgcmVuZGVyZXI6IGFueSwgZWxlbWVudDogUkVsZW1lbnQsIHZhbHVlczogc3RyaW5nIHwge1trZXk6IHN0cmluZ106IGFueX0gfCBTdHlsaW5nTWFwQXJyYXksXG4gICAgaXNDbGFzc0Jhc2VkOiBib29sZWFuKSB7XG4gIGxldCBhcnI6IFN0eWxpbmdNYXBBcnJheTtcbiAgaWYgKGlzU3R5bGluZ01hcEFycmF5KHZhbHVlcykpIHtcbiAgICBhcnIgPSB2YWx1ZXMgYXMgU3R5bGluZ01hcEFycmF5O1xuICB9IGVsc2Uge1xuICAgIGFyciA9IG5vcm1hbGl6ZUludG9TdHlsaW5nTWFwKG51bGwsIHZhbHVlcywgIWlzQ2xhc3NCYXNlZCk7XG4gIH1cblxuICBjb25zdCBhcHBseUZuID0gaXNDbGFzc0Jhc2VkID8gc2V0Q2xhc3MgOiBzZXRTdHlsZTtcbiAgZm9yIChsZXQgaSA9IFN0eWxpbmdNYXBBcnJheUluZGV4LlZhbHVlc1N0YXJ0UG9zaXRpb247IGkgPCBhcnIubGVuZ3RoO1xuICAgICAgIGkgKz0gU3R5bGluZ01hcEFycmF5SW5kZXguVHVwbGVTaXplKSB7XG4gICAgY29uc3QgdmFsdWUgPSBnZXRNYXBWYWx1ZShhcnIsIGkpO1xuICAgIGlmICh2YWx1ZSkge1xuICAgICAgY29uc3QgcHJvcCA9IGdldE1hcFByb3AoYXJyLCBpKTtcbiAgICAgIGFwcGx5Rm4ocmVuZGVyZXIsIGVsZW1lbnQsIHByb3AsIG51bGwpO1xuICAgIH1cbiAgfVxufVxuIl19