@angular/core 9.0.0-rc.6 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/core-testing.umd.js +18 -16
- package/bundles/core-testing.umd.js.map +1 -1
- package/bundles/core-testing.umd.min.js +7 -7
- package/bundles/core-testing.umd.min.js.map +1 -1
- package/bundles/core.umd.js +4018 -4002
- package/bundles/core.umd.js.map +1 -1
- package/bundles/core.umd.min.js +172 -187
- package/bundles/core.umd.min.js.map +1 -1
- package/core.d.ts +725 -735
- package/core.metadata.json +1 -1
- package/esm2015/core.externs.js +5 -5
- package/esm2015/core.js +17 -15
- package/esm2015/index.js +2 -2
- package/esm2015/public_api.js +2 -2
- package/esm2015/src/application_init.js +10 -2
- package/esm2015/src/application_module.js +6 -3
- package/esm2015/src/application_ref.js +7 -7
- package/esm2015/src/core.js +4 -4
- package/esm2015/src/core_private_export.js +7 -7
- package/esm2015/src/core_render3_private_export.js +2 -2
- package/esm2015/src/debug/debug_node.js +71 -69
- package/esm2015/src/di/injectable.js +1 -13
- package/esm2015/src/di/injector.js +12 -10
- package/esm2015/src/di/interface/defs.js +28 -4
- package/esm2015/src/di/interface/provider.js +1 -1
- package/esm2015/src/di/jit/injectable.js +14 -2
- package/esm2015/src/di/jit/util.js +7 -5
- package/esm2015/src/di/r3_injector.js +5 -5
- package/esm2015/src/i18n/locale_data_api.js +22 -6
- package/esm2015/src/i18n/locale_en.js +16 -5
- package/esm2015/src/i18n/localization.js +7 -1
- package/esm2015/src/i18n/tokens.js +41 -1
- package/esm2015/src/interface/type.js +1 -1
- package/esm2015/src/metadata/ng_module.js +1 -1
- package/esm2015/src/render/api.js +4 -1
- package/esm2015/src/render3/assert.js +9 -1
- package/esm2015/src/render3/bindings.js +20 -7
- package/esm2015/src/render3/component.js +54 -25
- package/esm2015/src/render3/component_ref.js +17 -18
- package/esm2015/src/render3/definition.js +3 -1
- package/esm2015/src/render3/di.js +3 -4
- package/esm2015/src/render3/di_setup.js +5 -7
- package/esm2015/src/render3/errors.js +99 -19
- package/esm2015/src/render3/features/inherit_definition_feature.js +89 -52
- package/esm2015/src/render3/features/ng_onchanges_feature.js +2 -2
- package/esm2015/src/render3/global_utils_api.js +3 -3
- package/esm2015/src/render3/i18n.js +60 -56
- package/esm2015/src/render3/index.js +2 -2
- package/esm2015/src/render3/instructions/advance.js +10 -11
- package/esm2015/src/render3/instructions/all.js +4 -5
- package/esm2015/src/render3/instructions/attribute.js +12 -5
- package/esm2015/src/render3/instructions/attribute_interpolation.js +66 -14
- package/esm2015/src/render3/instructions/change_detection.js +8 -23
- package/esm2015/src/render3/instructions/class_map_interpolation.js +13 -12
- package/esm2015/src/render3/instructions/container.js +15 -12
- package/esm2015/src/render3/instructions/element.js +50 -133
- package/esm2015/src/render3/instructions/element_container.js +8 -10
- package/esm2015/src/render3/instructions/embedded_view.js +7 -7
- package/esm2015/src/render3/instructions/host_property.js +10 -7
- package/esm2015/src/render3/instructions/listener.js +18 -16
- package/esm2015/src/render3/instructions/lview_debug.js +160 -23
- package/esm2015/src/render3/instructions/projection.js +7 -5
- package/esm2015/src/render3/instructions/property.js +27 -6
- package/esm2015/src/render3/instructions/property_interpolation.js +42 -23
- package/esm2015/src/render3/instructions/shared.js +285 -245
- package/esm2015/src/render3/instructions/storage.js +6 -8
- package/esm2015/src/render3/instructions/style_prop_interpolation.js +12 -12
- package/esm2015/src/render3/instructions/styling.js +732 -470
- package/esm2015/src/render3/instructions/text.js +5 -5
- package/esm2015/src/render3/interfaces/definition.js +41 -1
- package/esm2015/src/render3/interfaces/node.js +160 -115
- package/esm2015/src/render3/interfaces/styling.js +183 -375
- package/esm2015/src/render3/interfaces/view.js +10 -2
- package/esm2015/src/render3/jit/directive.js +10 -16
- package/esm2015/src/render3/jit/environment.js +1 -3
- package/esm2015/src/render3/node_manipulation.js +177 -57
- package/esm2015/src/render3/node_selector_matcher.js +128 -24
- package/esm2015/src/render3/node_util.js +12 -7
- package/esm2015/src/render3/pipe.js +10 -14
- package/esm2015/src/render3/pure_function.js +107 -42
- package/esm2015/src/render3/query.js +32 -26
- package/esm2015/src/render3/state.js +54 -183
- package/esm2015/src/render3/styling/class_differ.js +47 -0
- package/esm2015/src/render3/styling/static_styling.js +54 -0
- package/esm2015/src/render3/styling/style_binding_list.js +437 -0
- package/esm2015/src/render3/styling/styling_parser.js +336 -0
- package/esm2015/src/render3/tokens.js +2 -2
- package/esm2015/src/render3/util/attrs_utils.js +125 -2
- package/esm2015/src/render3/util/change_detection_utils.js +33 -0
- package/esm2015/src/render3/util/discovery_utils.js +146 -119
- package/esm2015/src/render3/util/global_utils.js +5 -5
- package/esm2015/src/render3/util/view_utils.js +6 -6
- package/esm2015/src/render3/view_engine_compatibility.js +16 -17
- package/esm2015/src/render3/view_ref.js +16 -13
- package/esm2015/src/sanitization/bypass.js +1 -1
- package/esm2015/src/sanitization/inert_body.js +22 -18
- package/esm2015/src/sanitization/sanitization.js +20 -5
- package/esm2015/src/util/array_utils.js +240 -1
- package/esm2015/src/util/assert.js +37 -21
- package/esm2015/src/util/char_code.js +8 -0
- package/esm2015/src/util/iterable.js +4 -1
- package/esm2015/src/util/ng_dev_mode.js +1 -12
- package/esm2015/src/util/stringify.js +14 -1
- package/esm2015/src/version.js +1 -1
- package/esm2015/src/view/services.js +1 -1
- package/esm2015/testing/src/r3_test_bed.js +5 -1
- package/esm2015/testing/src/r3_test_bed_compiler.js +5 -13
- package/esm2015/testing/src/styling.js +103 -0
- package/esm5/core.js +17 -15
- package/esm5/src/application_init.js +10 -2
- package/esm5/src/application_module.js +6 -3
- package/esm5/src/application_ref.js +6 -6
- package/esm5/src/core.js +2 -2
- package/esm5/src/core_private_export.js +7 -7
- package/esm5/src/core_render3_private_export.js +2 -2
- package/esm5/src/debug/debug_node.js +47 -41
- package/esm5/src/di/injectable.js +1 -1
- package/esm5/src/di/injector.js +12 -12
- package/esm5/src/di/interface/defs.js +28 -4
- package/esm5/src/di/interface/provider.js +1 -1
- package/esm5/src/di/jit/injectable.js +11 -2
- package/esm5/src/di/jit/util.js +6 -5
- package/esm5/src/di/r3_injector.js +4 -4
- package/esm5/src/i18n/locale_data_api.js +20 -6
- package/esm5/src/i18n/locale_en.js +16 -5
- package/esm5/src/i18n/localization.js +6 -1
- package/esm5/src/i18n/tokens.js +40 -1
- package/esm5/src/interface/type.js +1 -1
- package/esm5/src/metadata/ng_module.js +1 -1
- package/esm5/src/render/api.js +4 -1
- package/esm5/src/render3/assert.js +4 -1
- package/esm5/src/render3/bindings.js +22 -4
- package/esm5/src/render3/component.js +47 -22
- package/esm5/src/render3/component_ref.js +15 -17
- package/esm5/src/render3/definition.js +3 -1
- package/esm5/src/render3/di.js +3 -4
- package/esm5/src/render3/di_setup.js +4 -5
- package/esm5/src/render3/errors.js +69 -12
- package/esm5/src/render3/features/inherit_definition_feature.js +74 -42
- package/esm5/src/render3/features/ng_onchanges_feature.js +1 -1
- package/esm5/src/render3/global_utils_api.js +3 -3
- package/esm5/src/render3/i18n.js +51 -51
- package/esm5/src/render3/index.js +2 -2
- package/esm5/src/render3/instructions/advance.js +9 -11
- package/esm5/src/render3/instructions/all.js +1 -2
- package/esm5/src/render3/instructions/attribute.js +9 -5
- package/esm5/src/render3/instructions/attribute_interpolation.js +49 -13
- package/esm5/src/render3/instructions/change_detection.js +8 -21
- package/esm5/src/render3/instructions/class_map_interpolation.js +13 -12
- package/esm5/src/render3/instructions/container.js +13 -12
- package/esm5/src/render3/instructions/element.js +46 -114
- package/esm5/src/render3/instructions/element_container.js +8 -9
- package/esm5/src/render3/instructions/embedded_view.js +7 -7
- package/esm5/src/render3/instructions/host_property.js +8 -7
- package/esm5/src/render3/instructions/listener.js +13 -13
- package/esm5/src/render3/instructions/lview_debug.js +56 -15
- package/esm5/src/render3/instructions/projection.js +6 -5
- package/esm5/src/render3/instructions/property.js +17 -6
- package/esm5/src/render3/instructions/property_interpolation.js +32 -24
- package/esm5/src/render3/instructions/shared.js +264 -211
- package/esm5/src/render3/instructions/storage.js +4 -6
- package/esm5/src/render3/instructions/style_prop_interpolation.js +12 -12
- package/esm5/src/render3/instructions/styling.js +685 -363
- package/esm5/src/render3/instructions/text.js +5 -5
- package/esm5/src/render3/interfaces/definition.js +1 -1
- package/esm5/src/render3/interfaces/node.js +49 -1
- package/esm5/src/render3/interfaces/styling.js +57 -1
- package/esm5/src/render3/interfaces/view.js +1 -1
- package/esm5/src/render3/jit/directive.js +8 -10
- package/esm5/src/render3/jit/environment.js +1 -3
- package/esm5/src/render3/node_manipulation.js +167 -54
- package/esm5/src/render3/node_selector_matcher.js +113 -20
- package/esm5/src/render3/node_util.js +12 -7
- package/esm5/src/render3/pipe.js +10 -14
- package/esm5/src/render3/pure_function.js +103 -33
- package/esm5/src/render3/query.js +25 -24
- package/esm5/src/render3/state.js +34 -131
- package/esm5/src/render3/styling/class_differ.js +39 -0
- package/esm5/src/render3/styling/static_styling.js +42 -0
- package/esm5/src/render3/styling/style_binding_list.js +411 -0
- package/esm5/src/render3/styling/styling_parser.js +265 -0
- package/esm5/src/render3/tokens.js +2 -2
- package/esm5/src/render3/util/attrs_utils.js +117 -2
- package/esm5/src/render3/util/change_detection_utils.js +23 -0
- package/esm5/src/render3/util/discovery_utils.js +115 -99
- package/esm5/src/render3/util/global_utils.js +5 -5
- package/esm5/src/render3/util/view_utils.js +5 -5
- package/esm5/src/render3/view_engine_compatibility.js +37 -39
- package/esm5/src/render3/view_ref.js +14 -13
- package/esm5/src/sanitization/bypass.js +1 -1
- package/esm5/src/sanitization/inert_body.js +20 -13
- package/esm5/src/sanitization/sanitization.js +16 -5
- package/esm5/src/util/array_utils.js +240 -1
- package/esm5/src/util/assert.js +37 -21
- package/esm5/src/util/char_code.js +8 -0
- package/esm5/src/util/iterable.js +4 -1
- package/esm5/src/util/ng_dev_mode.js +1 -12
- package/esm5/src/util/stringify.js +14 -1
- package/esm5/src/version.js +1 -1
- package/esm5/src/view/services.js +1 -1
- package/esm5/testing/src/r3_test_bed.js +9 -1
- package/esm5/testing/src/r3_test_bed_compiler.js +9 -15
- package/esm5/testing/src/styling.js +82 -0
- package/fesm2015/core.js +5352 -6012
- package/fesm2015/core.js.map +1 -1
- package/fesm2015/testing.js +10 -14
- package/fesm2015/testing.js.map +1 -1
- package/fesm5/core.js +3987 -3980
- package/fesm5/core.js.map +1 -1
- package/fesm5/testing.js +18 -16
- package/fesm5/testing.js.map +1 -1
- package/package.json +1 -1
- package/schematics/migrations/missing-injectable/transform.js +2 -3
- package/schematics/migrations/module-with-providers/transform.js +3 -2
- package/schematics/migrations/undecorated-classes-with-di/index.js +2 -2
- package/schematics/utils/typescript/compiler_host.js +2 -2
- package/src/r3_symbols.d.ts +46 -23
- package/testing/testing.d.ts +3 -5
- package/testing/testing.metadata.json +1 -1
- package/testing.d.ts +2 -2
- package/esm2015/global.js +0 -7
- package/esm2015/src/render3/instructions/alloc_host_vars.js +0 -80
- package/esm2015/src/render3/styling/bindings.js +0 -1248
- package/esm2015/src/render3/styling/map_based_bindings.js +0 -384
- package/esm2015/src/render3/styling/state.js +0 -135
- package/esm2015/src/render3/styling/styling_debug.js +0 -712
- package/esm2015/src/render3/util/styling_utils.js +0 -625
- package/esm5/global.js +0 -9
- package/esm5/src/render3/instructions/alloc_host_vars.js +0 -62
- package/esm5/src/render3/styling/bindings.js +0 -949
- package/esm5/src/render3/styling/map_based_bindings.js +0 -310
- package/esm5/src/render3/styling/state.js +0 -56
- package/esm5/src/render3/styling/styling_debug.js +0 -352
- 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
|