@angular/core 8.0.0 → 8.1.0-beta.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 +35 -9
- package/bundles/core-testing.umd.js.map +1 -1
- package/bundles/core-testing.umd.min.js +10 -10
- package/bundles/core-testing.umd.min.js.map +1 -1
- package/bundles/core.umd.js +11356 -9352
- package/bundles/core.umd.js.map +1 -1
- package/bundles/core.umd.min.js +201 -139
- package/bundles/core.umd.min.js.map +1 -1
- package/core.d.ts +1302 -404
- package/core.metadata.json +1 -1
- package/esm2015/core.js +2 -3
- package/esm2015/index.js +2 -2
- package/esm2015/public_api.js +2 -2
- package/esm2015/src/application_ref.js +7 -1
- package/esm2015/src/codegen_private_exports.js +2 -2
- package/esm2015/src/compiler/compiler_facade_interface.js +1 -1
- package/esm2015/src/core.js +4 -4
- package/esm2015/src/core_private_export.js +3 -1
- package/esm2015/src/core_render3_private_export.js +5 -3
- package/esm2015/src/debug/debug_node.js +4 -4
- package/esm2015/src/di/index.js +3 -3
- package/esm2015/src/di/injector.js +24 -96
- package/esm2015/src/di/injector_compatibility.js +103 -6
- package/esm2015/src/di/interface/defs.js +24 -3
- package/esm2015/src/di/r3_injector.js +82 -49
- package/esm2015/src/di/reflective_injector.js +3 -2
- package/esm2015/src/di.js +1 -1
- package/esm2015/src/i18n/locale_data.js +61 -0
- package/esm2015/src/i18n/locale_data_api.js +53 -0
- package/esm2015/src/i18n/locale_en.js +51 -0
- package/esm2015/src/i18n/localization.js +37 -0
- package/esm2015/src/linker/ng_module_factory_loader.js +4 -52
- package/esm2015/src/linker/ng_module_factory_registration.js +83 -0
- package/esm2015/src/metadata/ng_module.js +6 -1
- package/esm2015/src/metadata/resource_loading.js +2 -2
- package/esm2015/src/reflection/reflection_capabilities.js +14 -3
- package/esm2015/src/render3/assert.js +3 -2
- package/esm2015/src/render3/component.js +11 -5
- package/esm2015/src/render3/debug.js +23 -15
- package/esm2015/src/render3/definition.js +12 -2
- package/esm2015/src/render3/errors.js +29 -1
- package/esm2015/src/render3/features/inherit_definition_feature.js +51 -37
- package/esm2015/src/render3/fields.js +3 -1
- package/esm2015/src/render3/i18n.js +76 -465
- package/esm2015/src/render3/index.js +3 -3
- package/esm2015/src/render3/instructions/all.js +9 -4
- package/esm2015/src/render3/instructions/attribute.js +28 -0
- package/esm2015/src/render3/instructions/attribute_interpolation.js +376 -0
- package/esm2015/src/render3/instructions/container.js +17 -16
- package/esm2015/src/render3/instructions/element.js +57 -35
- package/esm2015/src/render3/instructions/element_container.js +9 -8
- package/esm2015/src/render3/instructions/embedded_view.js +9 -12
- package/esm2015/src/render3/instructions/interpolation.js +375 -0
- package/esm2015/src/render3/instructions/listener.js +3 -2
- package/esm2015/src/render3/instructions/projection.js +6 -6
- package/esm2015/src/render3/instructions/property.js +10 -4
- package/esm2015/src/render3/instructions/property_interpolation.js +49 -382
- package/esm2015/src/render3/instructions/shared.js +82 -118
- package/esm2015/src/render3/instructions/styling.js +189 -236
- package/esm2015/src/render3/instructions/text.js +8 -7
- package/esm2015/src/render3/instructions/text_interpolation.js +357 -0
- package/esm2015/src/render3/interfaces/container.js +9 -5
- package/esm2015/src/render3/interfaces/definition.js +12 -6
- package/esm2015/src/render3/interfaces/node.js +20 -8
- package/esm2015/src/render3/interfaces/styling.js +16 -15
- package/esm2015/src/render3/interfaces/view.js +2 -2
- package/esm2015/src/render3/jit/directive.js +14 -5
- package/esm2015/src/render3/jit/environment.js +30 -15
- package/esm2015/src/render3/jit/module.js +38 -19
- package/esm2015/src/render3/ng_module_ref.js +39 -3
- package/esm2015/src/render3/node_manipulation.js +45 -43
- package/esm2015/src/render3/node_selector_matcher.js +14 -13
- package/esm2015/src/render3/query.js +77 -61
- package/esm2015/src/render3/state.js +33 -6
- package/esm2015/src/render3/styling/class_and_style_bindings.js +91 -79
- package/esm2015/src/render3/styling/host_instructions_queue.js +8 -5
- package/esm2015/src/render3/styling/shared.js +2 -2
- package/esm2015/src/render3/styling/util.js +2 -2
- package/esm2015/src/render3/styling_next/bindings.js +602 -0
- package/esm2015/src/render3/styling_next/instructions.js +366 -0
- package/esm2015/src/render3/styling_next/interfaces.js +374 -0
- package/esm2015/src/render3/styling_next/map_based_bindings.js +408 -0
- package/esm2015/src/render3/styling_next/state.js +51 -0
- package/esm2015/src/render3/styling_next/styling_debug.js +291 -0
- package/esm2015/src/render3/styling_next/util.js +259 -0
- package/esm2015/src/render3/util/attrs_utils.js +4 -3
- package/esm2015/src/render3/util/debug_utils.js +18 -0
- package/esm2015/src/render3/util/view_traversal_utils.js +2 -2
- package/esm2015/src/render3/view_engine_compatibility.js +24 -10
- package/esm2015/src/sanitization/sanitization.js +17 -7
- package/esm2015/src/sanitization/style_sanitizer.js +11 -1
- package/esm2015/src/util/ng_dev_mode.js +7 -3
- package/esm2015/src/version.js +1 -1
- package/esm2015/src/view/ng_module.js +3 -3
- package/esm2015/src/view/util.js +2 -2
- package/esm2015/testing/src/r3_test_bed_compiler.js +44 -12
- package/esm5/core.js +2 -3
- package/esm5/src/application_ref.js +6 -1
- package/esm5/src/codegen_private_exports.js +2 -2
- package/esm5/src/compiler/compiler_facade_interface.js +1 -1
- package/esm5/src/core_private_export.js +3 -1
- package/esm5/src/core_render3_private_export.js +5 -3
- package/esm5/src/debug/debug_node.js +4 -4
- package/esm5/src/di/index.js +3 -3
- package/esm5/src/di/injector.js +14 -74
- package/esm5/src/di/injector_compatibility.js +77 -6
- package/esm5/src/di/interface/defs.js +24 -3
- package/esm5/src/di/r3_injector.js +60 -37
- package/esm5/src/di/reflective_injector.js +3 -2
- package/esm5/src/i18n/locale_data.js +38 -0
- package/esm5/src/i18n/locale_data_api.js +46 -0
- package/esm5/src/i18n/locale_en.js +39 -0
- package/esm5/src/i18n/localization.js +29 -0
- package/esm5/src/linker/ng_module_factory_loader.js +4 -32
- package/esm5/src/linker/ng_module_factory_registration.js +50 -0
- package/esm5/src/metadata/ng_module.js +1 -1
- package/esm5/src/metadata/resource_loading.js +2 -2
- package/esm5/src/reflection/reflection_capabilities.js +14 -3
- package/esm5/src/render3/assert.js +2 -1
- package/esm5/src/render3/component.js +10 -4
- package/esm5/src/render3/debug.js +17 -10
- package/esm5/src/render3/definition.js +8 -2
- package/esm5/src/render3/errors.js +14 -1
- package/esm5/src/render3/features/inherit_definition_feature.js +41 -36
- package/esm5/src/render3/fields.js +2 -1
- package/esm5/src/render3/i18n.js +67 -437
- package/esm5/src/render3/index.js +3 -3
- package/esm5/src/render3/instructions/all.js +6 -1
- package/esm5/src/render3/instructions/attribute.js +22 -0
- package/esm5/src/render3/instructions/attribute_interpolation.js +346 -0
- package/esm5/src/render3/instructions/container.js +16 -15
- package/esm5/src/render3/instructions/element.js +43 -32
- package/esm5/src/render3/instructions/element_container.js +9 -8
- package/esm5/src/render3/instructions/embedded_view.js +8 -11
- package/esm5/src/render3/instructions/interpolation.js +243 -0
- package/esm5/src/render3/instructions/listener.js +3 -2
- package/esm5/src/render3/instructions/projection.js +6 -6
- package/esm5/src/render3/instructions/property.js +10 -4
- package/esm5/src/render3/instructions/property_interpolation.js +40 -254
- package/esm5/src/render3/instructions/shared.js +70 -105
- package/esm5/src/render3/instructions/styling.js +167 -209
- package/esm5/src/render3/instructions/text.js +8 -7
- package/esm5/src/render3/instructions/text_interpolation.js +264 -0
- package/esm5/src/render3/interfaces/container.js +8 -2
- package/esm5/src/render3/interfaces/definition.js +1 -1
- package/esm5/src/render3/interfaces/node.js +1 -8
- package/esm5/src/render3/interfaces/styling.js +2 -2
- package/esm5/src/render3/interfaces/view.js +1 -1
- package/esm5/src/render3/jit/directive.js +12 -5
- package/esm5/src/render3/jit/environment.js +30 -15
- package/esm5/src/render3/jit/module.js +23 -18
- package/esm5/src/render3/ng_module_ref.js +37 -3
- package/esm5/src/render3/node_manipulation.js +39 -38
- package/esm5/src/render3/node_selector_matcher.js +14 -13
- package/esm5/src/render3/query.js +75 -53
- package/esm5/src/render3/state.js +29 -5
- package/esm5/src/render3/styling/class_and_style_bindings.js +79 -65
- package/esm5/src/render3/styling/host_instructions_queue.js +6 -3
- package/esm5/src/render3/styling/shared.js +2 -2
- package/esm5/src/render3/styling/util.js +2 -2
- package/esm5/src/render3/styling_next/bindings.js +446 -0
- package/esm5/src/render3/styling_next/instructions.js +277 -0
- package/esm5/src/render3/styling_next/interfaces.js +1 -0
- package/esm5/src/render3/styling_next/map_based_bindings.js +324 -0
- package/esm5/src/render3/styling_next/state.js +23 -0
- package/esm5/src/render3/styling_next/styling_debug.js +130 -0
- package/esm5/src/render3/styling_next/util.js +147 -0
- package/esm5/src/render3/util/attrs_utils.js +4 -3
- package/esm5/src/render3/util/debug_utils.js +11 -0
- package/esm5/src/render3/util/view_traversal_utils.js +2 -2
- package/esm5/src/render3/view_engine_compatibility.js +23 -10
- package/esm5/src/sanitization/sanitization.js +14 -6
- package/esm5/src/sanitization/style_sanitizer.js +1 -1
- package/esm5/src/util/ng_dev_mode.js +7 -3
- package/esm5/src/version.js +1 -1
- package/esm5/src/view/ng_module.js +3 -3
- package/esm5/src/view/util.js +2 -2
- package/esm5/testing/src/r3_test_bed_compiler.js +37 -11
- package/fesm2015/core.js +13481 -10733
- package/fesm2015/core.js.map +1 -1
- package/fesm2015/testing.js +43 -11
- package/fesm2015/testing.js.map +1 -1
- package/fesm5/core.js +11255 -9269
- package/fesm5/core.js.map +1 -1
- package/fesm5/testing.js +36 -10
- package/fesm5/testing.js.map +1 -1
- package/package.json +1 -1
- package/schematics/migrations/template-var-assignment/index.js +2 -2
- package/src/r3_symbols.d.ts +5 -1
- package/testing/testing.d.ts +1 -1
- package/testing.d.ts +1 -1
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview added by tsickle
|
|
3
|
+
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
4
|
+
*/
|
|
5
|
+
import { RendererStyleFlags3, isProceduralRenderer } from '../interfaces/renderer';
|
|
6
|
+
import { allowStylingFlush, getBindingValue, getGuardMask, getProp, getPropValuesStartPosition, getValuesCount, hasValueChanged, isContextLocked, isSanitizationRequired, isStylingValueDefined, lockContext, setGuardMask } from './util';
|
|
7
|
+
/**
|
|
8
|
+
* --------
|
|
9
|
+
*
|
|
10
|
+
* This file contains the core logic for styling in Angular.
|
|
11
|
+
*
|
|
12
|
+
* All styling bindings (i.e. `[style]`, `[style.prop]`, `[class]` and `[class.name]`)
|
|
13
|
+
* will have their values be applied through the logic in this file.
|
|
14
|
+
*
|
|
15
|
+
* When a binding is encountered (e.g. `<div [style.width]="w">`) then
|
|
16
|
+
* the binding data will be populated into a `TStylingContext` data-structure.
|
|
17
|
+
* There is only one `TStylingContext` per `TNode` and each element instance
|
|
18
|
+
* will update its style/class binding values in concert with the styling
|
|
19
|
+
* context.
|
|
20
|
+
*
|
|
21
|
+
* To learn more about the algorithm see `TStylingContext`.
|
|
22
|
+
*
|
|
23
|
+
* --------
|
|
24
|
+
* @type {?}
|
|
25
|
+
*/
|
|
26
|
+
const DEFAULT_BINDING_VALUE = null;
|
|
27
|
+
/** @type {?} */
|
|
28
|
+
const DEFAULT_SIZE_VALUE = 1;
|
|
29
|
+
// The first bit value reflects a map-based binding value's bit.
|
|
30
|
+
// The reason why it's always activated for every entry in the map
|
|
31
|
+
// is so that if any map-binding values update then all other prop
|
|
32
|
+
// based bindings will pass the guard check automatically without
|
|
33
|
+
// any extra code or flags.
|
|
34
|
+
/** @type {?} */
|
|
35
|
+
export const DEFAULT_GUARD_MASK_VALUE = 0b1;
|
|
36
|
+
/** @type {?} */
|
|
37
|
+
const STYLING_INDEX_FOR_MAP_BINDING = 0;
|
|
38
|
+
/** @type {?} */
|
|
39
|
+
const STYLING_INDEX_START_VALUE = 1;
|
|
40
|
+
// the values below are global to all styling code below. Each value
|
|
41
|
+
// will either increment or mutate each time a styling instruction is
|
|
42
|
+
// executed. Do not modify the values below.
|
|
43
|
+
/** @type {?} */
|
|
44
|
+
let currentStyleIndex = STYLING_INDEX_START_VALUE;
|
|
45
|
+
/** @type {?} */
|
|
46
|
+
let currentClassIndex = STYLING_INDEX_START_VALUE;
|
|
47
|
+
/** @type {?} */
|
|
48
|
+
let stylesBitMask = 0;
|
|
49
|
+
/** @type {?} */
|
|
50
|
+
let classesBitMask = 0;
|
|
51
|
+
/** @type {?} */
|
|
52
|
+
let deferredBindingQueue = [];
|
|
53
|
+
/**
|
|
54
|
+
* Visits a class-based binding and updates the new value (if changed).
|
|
55
|
+
*
|
|
56
|
+
* This function is called each time a class-based styling instruction
|
|
57
|
+
* is executed. It's important that it's always called (even if the value
|
|
58
|
+
* has not changed) so that the inner counter index value is incremented.
|
|
59
|
+
* This way, each instruction is always guaranteed to get the same counter
|
|
60
|
+
* state each time it's called (which then allows the `TStylingContext`
|
|
61
|
+
* and the bit mask values to be in sync).
|
|
62
|
+
* @param {?} context
|
|
63
|
+
* @param {?} data
|
|
64
|
+
* @param {?} prop
|
|
65
|
+
* @param {?} bindingIndex
|
|
66
|
+
* @param {?} value
|
|
67
|
+
* @param {?} deferRegistration
|
|
68
|
+
* @param {?} forceUpdate
|
|
69
|
+
* @return {?}
|
|
70
|
+
*/
|
|
71
|
+
export function updateClassBinding(context, data, prop, bindingIndex, value, deferRegistration, forceUpdate) {
|
|
72
|
+
/** @type {?} */
|
|
73
|
+
const isMapBased = !prop;
|
|
74
|
+
/** @type {?} */
|
|
75
|
+
const index = isMapBased ? STYLING_INDEX_FOR_MAP_BINDING : currentClassIndex++;
|
|
76
|
+
/** @type {?} */
|
|
77
|
+
const updated = updateBindingData(context, data, index, prop, bindingIndex, value, deferRegistration, forceUpdate, false);
|
|
78
|
+
if (updated || forceUpdate) {
|
|
79
|
+
classesBitMask |= 1 << index;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Visits a style-based binding and updates the new value (if changed).
|
|
84
|
+
*
|
|
85
|
+
* This function is called each time a style-based styling instruction
|
|
86
|
+
* is executed. It's important that it's always called (even if the value
|
|
87
|
+
* has not changed) so that the inner counter index value is incremented.
|
|
88
|
+
* This way, each instruction is always guaranteed to get the same counter
|
|
89
|
+
* state each time it's called (which then allows the `TStylingContext`
|
|
90
|
+
* and the bit mask values to be in sync).
|
|
91
|
+
* @param {?} context
|
|
92
|
+
* @param {?} data
|
|
93
|
+
* @param {?} prop
|
|
94
|
+
* @param {?} bindingIndex
|
|
95
|
+
* @param {?} value
|
|
96
|
+
* @param {?} sanitizer
|
|
97
|
+
* @param {?} deferRegistration
|
|
98
|
+
* @param {?} forceUpdate
|
|
99
|
+
* @return {?}
|
|
100
|
+
*/
|
|
101
|
+
export function updateStyleBinding(context, data, prop, bindingIndex, value, sanitizer, deferRegistration, forceUpdate) {
|
|
102
|
+
/** @type {?} */
|
|
103
|
+
const isMapBased = !prop;
|
|
104
|
+
/** @type {?} */
|
|
105
|
+
const index = isMapBased ? STYLING_INDEX_FOR_MAP_BINDING : currentStyleIndex++;
|
|
106
|
+
/** @type {?} */
|
|
107
|
+
const sanitizationRequired = isMapBased ?
|
|
108
|
+
true :
|
|
109
|
+
(sanitizer ? sanitizer((/** @type {?} */ (prop)), null, 1 /* ValidateProperty */) : false);
|
|
110
|
+
/** @type {?} */
|
|
111
|
+
const updated = updateBindingData(context, data, index, prop, bindingIndex, value, deferRegistration, forceUpdate, sanitizationRequired);
|
|
112
|
+
if (updated || forceUpdate) {
|
|
113
|
+
stylesBitMask |= 1 << index;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Called each time a binding value has changed within the provided `TStylingContext`.
|
|
118
|
+
*
|
|
119
|
+
* This function is designed to be called from `updateStyleBinding` and `updateClassBinding`.
|
|
120
|
+
* If called during the first update pass, the binding will be registered in the context.
|
|
121
|
+
* If the binding does get registered and the `deferRegistration` flag is true then the
|
|
122
|
+
* binding data will be queued up until the context is later flushed in `applyStyling`.
|
|
123
|
+
*
|
|
124
|
+
* This function will also update binding slot in the provided `LStylingData` with the
|
|
125
|
+
* new binding entry (if it has changed).
|
|
126
|
+
*
|
|
127
|
+
* @param {?} context
|
|
128
|
+
* @param {?} data
|
|
129
|
+
* @param {?} counterIndex
|
|
130
|
+
* @param {?} prop
|
|
131
|
+
* @param {?} bindingIndex
|
|
132
|
+
* @param {?} value
|
|
133
|
+
* @param {?} deferRegistration
|
|
134
|
+
* @param {?} forceUpdate
|
|
135
|
+
* @param {?} sanitizationRequired
|
|
136
|
+
* @return {?} whether or not the binding value was updated in the `LStylingData`.
|
|
137
|
+
*/
|
|
138
|
+
function updateBindingData(context, data, counterIndex, prop, bindingIndex, value, deferRegistration, forceUpdate, sanitizationRequired) {
|
|
139
|
+
if (!isContextLocked(context)) {
|
|
140
|
+
if (deferRegistration) {
|
|
141
|
+
deferBindingRegistration(context, counterIndex, prop, bindingIndex, sanitizationRequired);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
deferredBindingQueue.length && flushDeferredBindings();
|
|
145
|
+
// this will only happen during the first update pass of the
|
|
146
|
+
// context. The reason why we can't use `tNode.firstTemplatePass`
|
|
147
|
+
// here is because its not guaranteed to be true when the first
|
|
148
|
+
// update pass is executed (remember that all styling instructions
|
|
149
|
+
// are run in the update phase, and, as a result, are no more
|
|
150
|
+
// styling instructions that are run in the creation phase).
|
|
151
|
+
registerBinding(context, counterIndex, prop, bindingIndex, sanitizationRequired);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/** @type {?} */
|
|
155
|
+
const changed = forceUpdate || hasValueChanged(data[bindingIndex], value);
|
|
156
|
+
if (changed) {
|
|
157
|
+
data[bindingIndex] = value;
|
|
158
|
+
}
|
|
159
|
+
return changed;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Schedules a binding registration to be run at a later point.
|
|
163
|
+
*
|
|
164
|
+
* The reasoning for this feature is to ensure that styling
|
|
165
|
+
* bindings are registered in the correct order for when
|
|
166
|
+
* directives/components have a super/sub class inheritance
|
|
167
|
+
* chains. Each directive's styling bindings must be
|
|
168
|
+
* registered into the context in reverse order. Therefore all
|
|
169
|
+
* bindings will be buffered in reverse order and then applied
|
|
170
|
+
* after the inheritance chain exits.
|
|
171
|
+
* @param {?} context
|
|
172
|
+
* @param {?} counterIndex
|
|
173
|
+
* @param {?} prop
|
|
174
|
+
* @param {?} bindingIndex
|
|
175
|
+
* @param {?} sanitizationRequired
|
|
176
|
+
* @return {?}
|
|
177
|
+
*/
|
|
178
|
+
function deferBindingRegistration(context, counterIndex, prop, bindingIndex, sanitizationRequired) {
|
|
179
|
+
deferredBindingQueue.unshift(context, counterIndex, prop, bindingIndex, sanitizationRequired);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Flushes the collection of deferred bindings and causes each entry
|
|
183
|
+
* to be registered into the context.
|
|
184
|
+
* @return {?}
|
|
185
|
+
*/
|
|
186
|
+
function flushDeferredBindings() {
|
|
187
|
+
/** @type {?} */
|
|
188
|
+
let i = 0;
|
|
189
|
+
while (i < deferredBindingQueue.length) {
|
|
190
|
+
/** @type {?} */
|
|
191
|
+
const context = (/** @type {?} */ (deferredBindingQueue[i++]));
|
|
192
|
+
/** @type {?} */
|
|
193
|
+
const count = (/** @type {?} */ (deferredBindingQueue[i++]));
|
|
194
|
+
/** @type {?} */
|
|
195
|
+
const prop = (/** @type {?} */ (deferredBindingQueue[i++]));
|
|
196
|
+
/** @type {?} */
|
|
197
|
+
const bindingIndex = (/** @type {?} */ (deferredBindingQueue[i++]));
|
|
198
|
+
/** @type {?} */
|
|
199
|
+
const sanitizationRequired = (/** @type {?} */ (deferredBindingQueue[i++]));
|
|
200
|
+
registerBinding(context, count, prop, bindingIndex, sanitizationRequired);
|
|
201
|
+
}
|
|
202
|
+
deferredBindingQueue.length = 0;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Registers the provided binding (prop + bindingIndex) into the context.
|
|
206
|
+
*
|
|
207
|
+
* This function is shared between bindings that are assigned immediately
|
|
208
|
+
* (via `updateBindingData`) and at a deferred stage. When called, it will
|
|
209
|
+
* figure out exactly where to place the binding data in the context.
|
|
210
|
+
*
|
|
211
|
+
* It is needed because it will either update or insert a styling property
|
|
212
|
+
* into the context at the correct spot.
|
|
213
|
+
*
|
|
214
|
+
* When called, one of two things will happen:
|
|
215
|
+
*
|
|
216
|
+
* 1) If the property already exists in the context then it will just add
|
|
217
|
+
* the provided `bindingValue` to the end of the binding sources region
|
|
218
|
+
* for that particular property.
|
|
219
|
+
*
|
|
220
|
+
* - If the binding value is a number then it will be added as a new
|
|
221
|
+
* binding index source next to the other binding sources for the property.
|
|
222
|
+
*
|
|
223
|
+
* - Otherwise, if the binding value is a string/boolean/null type then it will
|
|
224
|
+
* replace the default value for the property if the default value is `null`.
|
|
225
|
+
*
|
|
226
|
+
* 2) If the property does not exist then it will be inserted into the context.
|
|
227
|
+
* The styling context relies on all properties being stored in alphabetical
|
|
228
|
+
* order, so it knows exactly where to store it.
|
|
229
|
+
*
|
|
230
|
+
* When inserted, a default `null` value is created for the property which exists
|
|
231
|
+
* as the default value for the binding. If the bindingValue property is inserted
|
|
232
|
+
* and it is either a string, number or null value then that will replace the default
|
|
233
|
+
* value.
|
|
234
|
+
*
|
|
235
|
+
* Note that this function is also used for map-based styling bindings. They are treated
|
|
236
|
+
* much the same as prop-based bindings, but, because they do not have a property value
|
|
237
|
+
* (since it's a map), all map-based entries are stored in an already populated area of
|
|
238
|
+
* the context at the top (which is reserved for map-based entries).
|
|
239
|
+
* @param {?} context
|
|
240
|
+
* @param {?} countId
|
|
241
|
+
* @param {?} prop
|
|
242
|
+
* @param {?} bindingValue
|
|
243
|
+
* @param {?=} sanitizationRequired
|
|
244
|
+
* @return {?}
|
|
245
|
+
*/
|
|
246
|
+
export function registerBinding(context, countId, prop, bindingValue, sanitizationRequired) {
|
|
247
|
+
// prop-based bindings (e.g `<div [style.width]="w" [class.foo]="f">`)
|
|
248
|
+
if (prop) {
|
|
249
|
+
/** @type {?} */
|
|
250
|
+
let found = false;
|
|
251
|
+
/** @type {?} */
|
|
252
|
+
let i = getPropValuesStartPosition(context);
|
|
253
|
+
while (i < context.length) {
|
|
254
|
+
/** @type {?} */
|
|
255
|
+
const valuesCount = getValuesCount(context, i);
|
|
256
|
+
/** @type {?} */
|
|
257
|
+
const p = getProp(context, i);
|
|
258
|
+
found = prop <= p;
|
|
259
|
+
if (found) {
|
|
260
|
+
// all style/class bindings are sorted by property name
|
|
261
|
+
if (prop < p) {
|
|
262
|
+
allocateNewContextEntry(context, i, prop, sanitizationRequired);
|
|
263
|
+
}
|
|
264
|
+
addBindingIntoContext(context, false, i, bindingValue, countId);
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
i += 3 /* BindingsStartOffset */ + valuesCount;
|
|
268
|
+
}
|
|
269
|
+
if (!found) {
|
|
270
|
+
allocateNewContextEntry(context, context.length, prop, sanitizationRequired);
|
|
271
|
+
addBindingIntoContext(context, false, i, bindingValue, countId);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
// map-based bindings (e.g `<div [style]="s" [class]="{className:true}">`)
|
|
276
|
+
// there is no need to allocate the map-based binding region into the context
|
|
277
|
+
// since it is already there when the context is first created.
|
|
278
|
+
addBindingIntoContext(context, true, 2 /* MapBindingsPosition */, bindingValue, countId);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* @param {?} context
|
|
283
|
+
* @param {?} index
|
|
284
|
+
* @param {?} prop
|
|
285
|
+
* @param {?=} sanitizationRequired
|
|
286
|
+
* @return {?}
|
|
287
|
+
*/
|
|
288
|
+
function allocateNewContextEntry(context, index, prop, sanitizationRequired) {
|
|
289
|
+
// 1,2: splice index locations
|
|
290
|
+
// 3: each entry gets a config value (guard mask + flags)
|
|
291
|
+
// 4. each entry gets a size value (which is always one because there is always a default binding
|
|
292
|
+
// value)
|
|
293
|
+
// 5. the property that is getting allocated into the context
|
|
294
|
+
// 6. the default binding value (usually `null`)
|
|
295
|
+
/** @type {?} */
|
|
296
|
+
const config = sanitizationRequired ? 1 /* SanitizationRequired */ :
|
|
297
|
+
0 /* Default */;
|
|
298
|
+
context.splice(index, 0, config, DEFAULT_SIZE_VALUE, prop, DEFAULT_BINDING_VALUE);
|
|
299
|
+
setGuardMask(context, index, DEFAULT_GUARD_MASK_VALUE);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Inserts a new binding value into a styling property tuple in the `TStylingContext`.
|
|
303
|
+
*
|
|
304
|
+
* A bindingValue is inserted into a context during the first update pass
|
|
305
|
+
* of a template or host bindings function. When this occurs, two things
|
|
306
|
+
* happen:
|
|
307
|
+
*
|
|
308
|
+
* - If the bindingValue value is a number then it is treated as a bindingIndex
|
|
309
|
+
* value (a index in the `LView`) and it will be inserted next to the other
|
|
310
|
+
* binding index entries.
|
|
311
|
+
*
|
|
312
|
+
* - Otherwise the binding value will update the default value for the property
|
|
313
|
+
* and this will only happen if the default value is `null`.
|
|
314
|
+
*
|
|
315
|
+
* Note that this function also handles map-based bindings and will insert them
|
|
316
|
+
* at the top of the context.
|
|
317
|
+
* @param {?} context
|
|
318
|
+
* @param {?} isMapBased
|
|
319
|
+
* @param {?} index
|
|
320
|
+
* @param {?} bindingValue
|
|
321
|
+
* @param {?} countId
|
|
322
|
+
* @return {?}
|
|
323
|
+
*/
|
|
324
|
+
function addBindingIntoContext(context, isMapBased, index, bindingValue, countId) {
|
|
325
|
+
/** @type {?} */
|
|
326
|
+
const valuesCount = getValuesCount(context, index);
|
|
327
|
+
/** @type {?} */
|
|
328
|
+
let lastValueIndex = index + 3 /* BindingsStartOffset */ + valuesCount;
|
|
329
|
+
if (!isMapBased) {
|
|
330
|
+
// prop-based values all have default values, but map-based entries do not.
|
|
331
|
+
// we want to access the index for the default value in this case and not just
|
|
332
|
+
// the bindings...
|
|
333
|
+
lastValueIndex--;
|
|
334
|
+
}
|
|
335
|
+
if (typeof bindingValue === 'number') {
|
|
336
|
+
context.splice(lastValueIndex, 0, bindingValue);
|
|
337
|
+
((/** @type {?} */ (context[index + 1 /* ValuesCountOffset */])))++;
|
|
338
|
+
// now that a new binding index has been added to the property
|
|
339
|
+
// the guard mask bit value (at the `countId` position) needs
|
|
340
|
+
// to be included into the existing mask value.
|
|
341
|
+
/** @type {?} */
|
|
342
|
+
const guardMask = getGuardMask(context, index) | (1 << countId);
|
|
343
|
+
setGuardMask(context, index, guardMask);
|
|
344
|
+
}
|
|
345
|
+
else if (typeof bindingValue === 'string' && context[lastValueIndex] == null) {
|
|
346
|
+
context[lastValueIndex] = bindingValue;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Applies all class entries in the provided context to the provided element and resets
|
|
351
|
+
* any counter and/or bitMask values associated with class bindings.
|
|
352
|
+
*
|
|
353
|
+
* @param {?} renderer
|
|
354
|
+
* @param {?} data
|
|
355
|
+
* @param {?} context
|
|
356
|
+
* @param {?} element
|
|
357
|
+
* @param {?} directiveIndex
|
|
358
|
+
* @return {?} whether or not the classes were flushed to the element.
|
|
359
|
+
*/
|
|
360
|
+
export function applyClasses(renderer, data, context, element, directiveIndex) {
|
|
361
|
+
/** @type {?} */
|
|
362
|
+
let classesFlushed = false;
|
|
363
|
+
if (allowStylingFlush(context, directiveIndex)) {
|
|
364
|
+
/** @type {?} */
|
|
365
|
+
const isFirstPass = !isContextLocked(context);
|
|
366
|
+
isFirstPass && lockContext(context);
|
|
367
|
+
if (classesBitMask) {
|
|
368
|
+
// there is no way to sanitize a class value therefore `sanitizer=null`
|
|
369
|
+
applyStyling(context, renderer, element, data, classesBitMask, setClass, null);
|
|
370
|
+
classesBitMask = 0;
|
|
371
|
+
classesFlushed = true;
|
|
372
|
+
}
|
|
373
|
+
currentClassIndex = STYLING_INDEX_START_VALUE;
|
|
374
|
+
}
|
|
375
|
+
return classesFlushed;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Applies all style entries in the provided context to the provided element and resets
|
|
379
|
+
* any counter and/or bitMask values associated with style bindings.
|
|
380
|
+
*
|
|
381
|
+
* @param {?} renderer
|
|
382
|
+
* @param {?} data
|
|
383
|
+
* @param {?} context
|
|
384
|
+
* @param {?} element
|
|
385
|
+
* @param {?} directiveIndex
|
|
386
|
+
* @param {?} sanitizer
|
|
387
|
+
* @return {?} whether or not the styles were flushed to the element.
|
|
388
|
+
*/
|
|
389
|
+
export function applyStyles(renderer, data, context, element, directiveIndex, sanitizer) {
|
|
390
|
+
/** @type {?} */
|
|
391
|
+
let stylesFlushed = false;
|
|
392
|
+
if (allowStylingFlush(context, directiveIndex)) {
|
|
393
|
+
/** @type {?} */
|
|
394
|
+
const isFirstPass = !isContextLocked(context);
|
|
395
|
+
isFirstPass && lockContext(context);
|
|
396
|
+
if (stylesBitMask) {
|
|
397
|
+
applyStyling(context, renderer, element, data, stylesBitMask, setStyle, sanitizer);
|
|
398
|
+
stylesBitMask = 0;
|
|
399
|
+
stylesFlushed = true;
|
|
400
|
+
}
|
|
401
|
+
currentStyleIndex = STYLING_INDEX_START_VALUE;
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
return stylesFlushed;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Runs through the provided styling context and applies each value to
|
|
408
|
+
* the provided element (via the renderer) if one or more values are present.
|
|
409
|
+
*
|
|
410
|
+
* This function will iterate over all entries present in the provided
|
|
411
|
+
* `TStylingContext` array (both prop-based and map-based bindings).-
|
|
412
|
+
*
|
|
413
|
+
* Each entry, within the `TStylingContext` array, is stored alphabetically
|
|
414
|
+
* and this means that each prop/value entry will be applied in order
|
|
415
|
+
* (so long as it is marked dirty in the provided `bitMask` value).
|
|
416
|
+
*
|
|
417
|
+
* If there are any map-based entries present (which are applied to the
|
|
418
|
+
* element via the `[style]` and `[class]` bindings) then those entries
|
|
419
|
+
* will be applied as well. However, the code for that is not apart of
|
|
420
|
+
* this function. Instead, each time a property is visited, then the
|
|
421
|
+
* code below will call an external function called `stylingMapsSyncFn`
|
|
422
|
+
* and, if present, it will keep the application of styling values in
|
|
423
|
+
* map-based bindings up to sync with the application of prop-based
|
|
424
|
+
* bindings.
|
|
425
|
+
*
|
|
426
|
+
* Visit `styling_next/map_based_bindings.ts` to learn more about how the
|
|
427
|
+
* algorithm works for map-based styling bindings.
|
|
428
|
+
*
|
|
429
|
+
* Note that this function is not designed to be called in isolation (use
|
|
430
|
+
* `applyClasses` and `applyStyles` to actually apply styling values).
|
|
431
|
+
* @param {?} context
|
|
432
|
+
* @param {?} renderer
|
|
433
|
+
* @param {?} element
|
|
434
|
+
* @param {?} bindingData
|
|
435
|
+
* @param {?} bitMaskValue
|
|
436
|
+
* @param {?} applyStylingFn
|
|
437
|
+
* @param {?} sanitizer
|
|
438
|
+
* @return {?}
|
|
439
|
+
*/
|
|
440
|
+
export function applyStyling(context, renderer, element, bindingData, bitMaskValue, applyStylingFn, sanitizer) {
|
|
441
|
+
deferredBindingQueue.length && flushDeferredBindings();
|
|
442
|
+
/** @type {?} */
|
|
443
|
+
const bitMask = normalizeBitMaskValue(bitMaskValue);
|
|
444
|
+
/** @type {?} */
|
|
445
|
+
const stylingMapsSyncFn = getStylingMapsSyncFn();
|
|
446
|
+
/** @type {?} */
|
|
447
|
+
const mapsGuardMask = getGuardMask(context, 2 /* MapBindingsPosition */);
|
|
448
|
+
/** @type {?} */
|
|
449
|
+
const applyAllValues = (bitMask & mapsGuardMask) > 0;
|
|
450
|
+
/** @type {?} */
|
|
451
|
+
const mapsMode = applyAllValues ? 1 /* ApplyAllValues */ : 0 /* TraverseValues */;
|
|
452
|
+
/** @type {?} */
|
|
453
|
+
let i = getPropValuesStartPosition(context);
|
|
454
|
+
while (i < context.length) {
|
|
455
|
+
/** @type {?} */
|
|
456
|
+
const valuesCount = getValuesCount(context, i);
|
|
457
|
+
/** @type {?} */
|
|
458
|
+
const guardMask = getGuardMask(context, i);
|
|
459
|
+
if (bitMask & guardMask) {
|
|
460
|
+
/** @type {?} */
|
|
461
|
+
let valueApplied = false;
|
|
462
|
+
/** @type {?} */
|
|
463
|
+
const prop = getProp(context, i);
|
|
464
|
+
/** @type {?} */
|
|
465
|
+
const valuesCountUpToDefault = valuesCount - 1;
|
|
466
|
+
/** @type {?} */
|
|
467
|
+
const defaultValue = (/** @type {?} */ (getBindingValue(context, i, valuesCountUpToDefault)));
|
|
468
|
+
// case 1: apply prop-based values
|
|
469
|
+
// try to apply the binding values and see if a non-null
|
|
470
|
+
// value gets set for the styling binding
|
|
471
|
+
for (let j = 0; j < valuesCountUpToDefault; j++) {
|
|
472
|
+
/** @type {?} */
|
|
473
|
+
const bindingIndex = (/** @type {?} */ (getBindingValue(context, i, j)));
|
|
474
|
+
/** @type {?} */
|
|
475
|
+
const value = bindingData[bindingIndex];
|
|
476
|
+
if (isStylingValueDefined(value)) {
|
|
477
|
+
/** @type {?} */
|
|
478
|
+
const finalValue = sanitizer && isSanitizationRequired(context, i) ?
|
|
479
|
+
sanitizer(prop, value, 2 /* SanitizeOnly */) :
|
|
480
|
+
value;
|
|
481
|
+
applyStylingFn(renderer, element, prop, finalValue, bindingIndex);
|
|
482
|
+
valueApplied = true;
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
// case 2: apply map-based values
|
|
487
|
+
// traverse through each map-based styling binding and update all values up to
|
|
488
|
+
// the provided `prop` value. If the property was not applied in the loop above
|
|
489
|
+
// then it will be attempted to be applied in the maps sync code below.
|
|
490
|
+
if (stylingMapsSyncFn) {
|
|
491
|
+
// determine whether or not to apply the target property or to skip it
|
|
492
|
+
/** @type {?} */
|
|
493
|
+
const mode = mapsMode | (valueApplied ? 4 /* SkipTargetProp */ :
|
|
494
|
+
2 /* ApplyTargetProp */);
|
|
495
|
+
/** @type {?} */
|
|
496
|
+
const valueAppliedWithinMap = stylingMapsSyncFn(context, renderer, element, bindingData, applyStylingFn, sanitizer, mode, prop, defaultValue);
|
|
497
|
+
valueApplied = valueApplied || valueAppliedWithinMap;
|
|
498
|
+
}
|
|
499
|
+
// case 3: apply the default value
|
|
500
|
+
// if the value has not yet been applied then a truthy value does not exist in the
|
|
501
|
+
// prop-based or map-based bindings code. If and when this happens, just apply the
|
|
502
|
+
// default value (even if the default value is `null`).
|
|
503
|
+
if (!valueApplied) {
|
|
504
|
+
applyStylingFn(renderer, element, prop, defaultValue);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
i += 3 /* BindingsStartOffset */ + valuesCount;
|
|
508
|
+
}
|
|
509
|
+
// the map-based styling entries may have not applied all their
|
|
510
|
+
// values. For this reason, one more call to the sync function
|
|
511
|
+
// needs to be issued at the end.
|
|
512
|
+
if (stylingMapsSyncFn) {
|
|
513
|
+
stylingMapsSyncFn(context, renderer, element, bindingData, applyStylingFn, sanitizer, mapsMode);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* @param {?} value
|
|
518
|
+
* @return {?}
|
|
519
|
+
*/
|
|
520
|
+
function normalizeBitMaskValue(value) {
|
|
521
|
+
// if pass => apply all values (-1 implies that all bits are flipped to true)
|
|
522
|
+
if (value === true)
|
|
523
|
+
return -1;
|
|
524
|
+
// if pass => skip all values
|
|
525
|
+
if (value === false)
|
|
526
|
+
return 0;
|
|
527
|
+
// return the bit mask value as is
|
|
528
|
+
return value;
|
|
529
|
+
}
|
|
530
|
+
/** @type {?} */
|
|
531
|
+
let _activeStylingMapApplyFn = null;
|
|
532
|
+
/**
|
|
533
|
+
* @return {?}
|
|
534
|
+
*/
|
|
535
|
+
export function getStylingMapsSyncFn() {
|
|
536
|
+
return _activeStylingMapApplyFn;
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* @param {?} fn
|
|
540
|
+
* @return {?}
|
|
541
|
+
*/
|
|
542
|
+
export function setStylingMapsSyncFn(fn) {
|
|
543
|
+
_activeStylingMapApplyFn = fn;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Assigns a style value to a style property for the given element.
|
|
547
|
+
* @type {?}
|
|
548
|
+
*/
|
|
549
|
+
const setStyle = (/**
|
|
550
|
+
* @param {?} renderer
|
|
551
|
+
* @param {?} native
|
|
552
|
+
* @param {?} prop
|
|
553
|
+
* @param {?} value
|
|
554
|
+
* @return {?}
|
|
555
|
+
*/
|
|
556
|
+
(renderer, native, prop, value) => {
|
|
557
|
+
if (value) {
|
|
558
|
+
// opacity, z-index and flexbox all have number values
|
|
559
|
+
// and these need to be converted into strings so that
|
|
560
|
+
// they can be assigned properly.
|
|
561
|
+
value = value.toString();
|
|
562
|
+
ngDevMode && ngDevMode.rendererSetStyle++;
|
|
563
|
+
renderer && isProceduralRenderer(renderer) ?
|
|
564
|
+
renderer.setStyle(native, prop, value, RendererStyleFlags3.DashCase) :
|
|
565
|
+
native.style.setProperty(prop, value);
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
ngDevMode && ngDevMode.rendererRemoveStyle++;
|
|
569
|
+
renderer && isProceduralRenderer(renderer) ?
|
|
570
|
+
renderer.removeStyle(native, prop, RendererStyleFlags3.DashCase) :
|
|
571
|
+
native.style.removeProperty(prop);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
const ɵ0 = setStyle;
|
|
575
|
+
/**
|
|
576
|
+
* Adds/removes the provided className value to the provided element.
|
|
577
|
+
* @type {?}
|
|
578
|
+
*/
|
|
579
|
+
const setClass = (/**
|
|
580
|
+
* @param {?} renderer
|
|
581
|
+
* @param {?} native
|
|
582
|
+
* @param {?} className
|
|
583
|
+
* @param {?} value
|
|
584
|
+
* @return {?}
|
|
585
|
+
*/
|
|
586
|
+
(renderer, native, className, value) => {
|
|
587
|
+
if (className !== '') {
|
|
588
|
+
if (value) {
|
|
589
|
+
ngDevMode && ngDevMode.rendererAddClass++;
|
|
590
|
+
renderer && isProceduralRenderer(renderer) ? renderer.addClass(native, className) :
|
|
591
|
+
native.classList.add(className);
|
|
592
|
+
}
|
|
593
|
+
else {
|
|
594
|
+
ngDevMode && ngDevMode.rendererRemoveClass++;
|
|
595
|
+
renderer && isProceduralRenderer(renderer) ? renderer.removeClass(native, className) :
|
|
596
|
+
native.classList.remove(className);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
const ɵ1 = setClass;
|
|
601
|
+
export { ɵ0, ɵ1 };
|
|
602
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmluZGluZ3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb3JlL3NyYy9yZW5kZXIzL3N0eWxpbmdfbmV4dC9iaW5kaW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBUUEsT0FBTyxFQUEyQyxtQkFBbUIsRUFBRSxvQkFBb0IsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBRzNILE9BQU8sRUFBQyxpQkFBaUIsRUFBRSxlQUFlLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxjQUFjLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxzQkFBc0IsRUFBRSxxQkFBcUIsRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFDLE1BQU0sUUFBUSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztNQXNCbk8scUJBQXFCLEdBQUcsSUFBSTs7TUFDNUIsa0JBQWtCLEdBQUcsQ0FBQzs7Ozs7OztBQU81QixNQUFNLE9BQU8sd0JBQXdCLEdBQUcsR0FBRzs7TUFDckMsNkJBQTZCLEdBQUcsQ0FBQzs7TUFDakMseUJBQXlCLEdBQUcsQ0FBQzs7Ozs7SUFLL0IsaUJBQWlCLEdBQUcseUJBQXlCOztJQUM3QyxpQkFBaUIsR0FBRyx5QkFBeUI7O0lBQzdDLGFBQWEsR0FBRyxDQUFDOztJQUNqQixjQUFjLEdBQUcsQ0FBQzs7SUFDbEIsb0JBQW9CLEdBQTJELEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFZckYsTUFBTSxVQUFVLGtCQUFrQixDQUM5QixPQUF3QixFQUFFLElBQWtCLEVBQUUsSUFBbUIsRUFBRSxZQUFvQixFQUN2RixLQUF3RCxFQUFFLGlCQUEwQixFQUNwRixXQUFvQjs7VUFDaEIsVUFBVSxHQUFHLENBQUMsSUFBSTs7VUFDbEIsS0FBSyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsNkJBQTZCLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixFQUFFOztVQUN4RSxPQUFPLEdBQUcsaUJB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QUUsU0FBaUIsRUFBRSxLQUFVLEVBQUUsRUFBRTtJQUN6RSxJQUFJLFNBQVMsS0FBSyxFQUFFLEVBQUU7UUFDcEIsSUFBSSxLQUFLLEVBQUU7WUFDVCxTQUFTLElBQUksU0FBUyxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDMUMsUUFBUSxJQUFJLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO2dCQUN0QyxNQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUM5RTthQUFNO1lBQ0wsU0FBUyxJQUFJLFNBQVMsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQzdDLFFBQVEsSUFBSSxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztnQkFDekMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7U0FDakY7S0FDRjtBQUNILENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuKiBAbGljZW5zZVxuKiBDb3B5cmlnaHQgR29vZ2xlIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbipcbiogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuKi9cbmltcG9ydCB7U3R5bGVTYW5pdGl6ZUZuLCBTdHlsZVNhbml0aXplTW9kZX0gZnJvbSAnLi4vLi4vc2FuaXRpemF0aW9uL3N0eWxlX3Nhbml0aXplcic7XG5pbXBvcnQge1Byb2NlZHVyYWxSZW5kZXJlcjMsIFJFbGVtZW50LCBSZW5kZXJlcjMsIFJlbmRlcmVyU3R5bGVGbGFnczMsIGlzUHJvY2VkdXJhbFJlbmRlcmVyfSBmcm9tICcuLi9pbnRlcmZhY2VzL3JlbmRlcmVyJztcblxuaW1wb3J0IHtBcHBseVN0eWxpbmdGbiwgTFN0eWxpbmdEYXRhLCBMU3R5bGluZ01hcCwgU3R5bGluZ01hcHNTeW5jTW9kZSwgU3luY1N0eWxpbmdNYXBzRm4sIFRTdHlsaW5nQ29udGV4dCwgVFN0eWxpbmdDb250ZXh0SW5kZXgsIFRTdHlsaW5nQ29udGV4dFByb3BDb25maWdGbGFnc30gZnJvbSAnLi9pbnRlcmZhY2VzJztcbmltcG9ydCB7YWxsb3dTdHlsaW5nRmx1c2gsIGdldEJpbmRpbmdWYWx1ZSwgZ2V0R3VhcmRNYXNrLCBnZXRQcm9wLCBnZXRQcm9wVmFsdWVzU3RhcnRQb3NpdGlvbiwgZ2V0VmFsdWVzQ291bnQsIGhhc1ZhbHVlQ2hhbmdlZCwgaXNDb250ZXh0TG9ja2VkLCBpc1Nhbml0aXphdGlvblJlcXVpcmVkLCBpc1N0eWxpbmdWYWx1ZURlZmluZWQsIGxvY2tDb250ZXh0LCBzZXRHdWFyZE1hc2t9IGZyb20gJy4vdXRpbCc7XG5cblxuLyoqXG4gKiAtLS0tLS0tLVxuICpcbiAqIFRoaXMgZmlsZSBjb250YWlucyB0aGUgY29yZSBsb2dpYyBmb3Igc3R5bGluZyBpbiBBbmd1bGFyLlxuICpcbiAqIEFsbCBzdHlsaW5nIGJpbmRpbmdzIChpLmUuIGBbc3R5bGVdYCwgYFtzdHlsZS5wcm9wXWAsIGBbY2xhc3NdYCBhbmQgYFtjbGFzcy5uYW1lXWApXG4gKiB3aWxsIGhhdmUgdGhlaXIgdmFsdWVzIGJlIGFwcGxpZWQgdGhyb3VnaCB0aGUgbG9naWMgaW4gdGhpcyBmaWxlLlxuICpcbiAqIFdoZW4gYSBiaW5kaW5nIGlzIGVuY291bnRlcmVkIChlLmcuIGA8ZGl2IFtzdHlsZS53aWR0aF09XCJ3XCI+YCkgdGhlblxuICogdGhlIGJpbmRpbmcgZGF0YSB3aWxsIGJlIHBvcHVsYXRlZCBpbnRvIGEgYFRTdHlsaW5nQ29udGV4dGAgZGF0YS1zdHJ1Y3R1cmUuXG4gKiBUaGVyZSBpcyBvbmx5IG9uZSBgVFN0eWxpbmdDb250ZXh0YCBwZXIgYFROb2RlYCBhbmQgZWFjaCBlbGVtZW50IGluc3RhbmNlXG4gKiB3aWxsIHVwZGF0ZSBpdHMgc3R5bGUvY2xhc3MgYmluZGluZyB2YWx1ZXMgaW4gY29uY2VydCB3aXRoIHRoZSBzdHlsaW5nXG4gKiBjb250ZXh0LlxuICpcbiAqIFRvIGxlYXJuIG1vcmUgYWJvdXQgdGhlIGFsZ29yaXRobSBzZWUgYFRTdHlsaW5nQ29udGV4dGAuXG4gKlxuICogLS0tLS0tLS1cbiAqL1xuXG5jb25zdCBERUZBVUxUX0JJTkRJTkdfVkFMVUUgPSBudWxsO1xuY29uc3QgREVGQVVMVF9TSVpFX1ZBTFVFID0gMTtcblxuLy8gVGhlIGZpcnN0IGJpdCB2YWx1ZSByZWZsZWN0cyBhIG1hcC1iYXNlZCBiaW5kaW5nIHZhbHVlJ3MgYml0LlxuLy8gVGhlIHJlYXNvbiB3aHkgaXQncyBhbHdheXMgYWN0aXZhdGVkIGZvciBldmVyeSBlbnRyeSBpbiB0aGUgbWFwXG4vLyBpcyBzbyB0aGF0IGlmIGFueSBtYXAtYmluZGluZyB2YWx1ZXMgdXBkYXRlIHRoZW4gYWxsIG90aGVyIHByb3Bcbi8vIGJhc2VkIGJpbmRpbmdzIHdpbGwgcGFzcyB0aGUgZ3VhcmQgY2hlY2sgYXV0b21hdGljYWxseSB3aXRob3V0XG4vLyBhbnkgZXh0cmEgY29kZSBvciBmbGFncy5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0dVQVJEX01BU0tfVkFMVUUgPSAwYjE7XG5jb25zdCBTVFlMSU5HX0lOREVYX0ZPUl9NQVBfQklORElORyA9IDA7XG5jb25zdCBTVFlMSU5HX0lOREVYX1NUQVJUX1ZBTFVFID0gMTtcblxuLy8gdGhlIHZhbHVlcyBiZWxvdyBhcmUgZ2xvYmFsIHRvIGFsbCBzdHlsaW5nIGNvZGUgYmVsb3cuIEVhY2ggdmFsdWVcbi8vIHdpbGwgZWl0aGVyIGluY3JlbWVudCBvciBtdXRhdGUgZWFjaCB0aW1lIGEgc3R5bGluZyBpbnN0cnVjdGlvbiBpc1xuLy8gZXhlY3V0ZWQuIERvIG5vdCBtb2RpZnkgdGhlIHZhbHVlcyBiZWxvdy5cbmxldCBjdXJyZW50U3R5bGVJbmRleCA9IFNUWUxJTkdfSU5ERVhfU1RBUlRfVkFMVUU7XG5sZXQgY3VycmVudENsYXNzSW5kZXggPSBTVFlMSU5HX0lOREVYX1NUQVJUX1ZBTFVFO1xubGV0IHN0eWxlc0JpdE1hc2sgPSAwO1xubGV0IGNsYXNzZXNCaXRNYXNrID0gMDtcbmxldCBkZWZlcnJlZEJpbmRpbmdRdWV1ZTogKFRTdHlsaW5nQ29udGV4dCB8IG51bWJlciB8IHN0cmluZyB8IG51bGwgfCBib29sZWFuKVtdID0gW107XG5cbi8qKlxuICogVmlzaXRzIGEgY2xhc3MtYmFzZWQgYmluZGluZyBhbmQgdXBkYXRlcyB0aGUgbmV3IHZhbHVlIChpZiBjaGFuZ2VkKS5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBlYWNoIHRpbWUgYSBjbGFzcy1iYXNlZCBzdHlsaW5nIGluc3RydWN0aW9uXG4gKiBpcyBleGVjdXRlZC4gSXQncyBpbXBvcnRhbnQgdGhhdCBpdCdzIGFsd2F5cyBjYWxsZWQgKGV2ZW4gaWYgdGhlIHZhbHVlXG4gKiBoYXMgbm90IGNoYW5nZWQpIHNvIHRoYXQgdGhlIGlubmVyIGNvdW50ZXIgaW5kZXggdmFsdWUgaXMgaW5jcmVtZW50ZWQuXG4gKiBUaGlzIHdheSwgZWFjaCBpbnN0cnVjdGlvbiBpcyBhbHdheXMgZ3VhcmFudGVlZCB0byBnZXQgdGhlIHNhbWUgY291bnRlclxuICogc3RhdGUgZWFjaCB0aW1lIGl0J3MgY2FsbGVkICh3aGljaCB0aGVuIGFsbG93cyB0aGUgYFRTdHlsaW5nQ29udGV4dGBcbiAqIGFuZCB0aGUgYml0IG1hc2sgdmFsdWVzIHRvIGJlIGluIHN5bmMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlQ2xhc3NCaW5kaW5nKFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgZGF0YTogTFN0eWxpbmdEYXRhLCBwcm9wOiBzdHJpbmcgfCBudWxsLCBiaW5kaW5nSW5kZXg6IG51bWJlcixcbiAgICB2YWx1ZTogYm9vbGVhbiB8IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQgfCBMU3R5bGluZ01hcCwgZGVmZXJSZWdpc3RyYXRpb246IGJvb2xlYW4sXG4gICAgZm9yY2VVcGRhdGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgY29uc3QgaXNNYXBCYXNlZCA9ICFwcm9wO1xuICBjb25zdCBpbmRleCA9IGlzTWFwQmFzZWQgPyBTVFlMSU5HX0lOREVYX0ZPUl9NQVBfQklORElORyA6IGN1cnJlbnRDbGFzc0luZGV4Kys7XG4gIGNvbnN0IHVwZGF0ZWQgPSB1cGRhdGVCaW5kaW5nRGF0YShcbiAgICAgIGNvbnRleHQsIGRhdGEsIGluZGV4LCBwcm9wLCBiaW5kaW5nSW5kZXgsIHZhbHVlLCBkZWZlclJlZ2lzdHJhdGlvbiwgZm9yY2VVcGRhdGUsIGZhbHNlKTtcbiAgaWYgKHVwZGF0ZWQgfHwgZm9yY2VVcGRhdGUpIHtcbiAgICBjbGFzc2VzQml0TWFzayB8PSAxIDw8IGluZGV4O1xuICB9XG59XG5cbi8qKlxuICogVmlzaXRzIGEgc3R5bGUtYmFzZWQgYmluZGluZyBhbmQgdXBkYXRlcyB0aGUgbmV3IHZhbHVlIChpZiBjaGFuZ2VkKS5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBlYWNoIHRpbWUgYSBzdHlsZS1iYXNlZCBzdHlsaW5nIGluc3RydWN0aW9uXG4gKiBpcyBleGVjdXRlZC4gSXQncyBpbXBvcnRhbnQgdGhhdCBpdCdzIGFsd2F5cyBjYWxsZWQgKGV2ZW4gaWYgdGhlIHZhbHVlXG4gKiBoYXMgbm90IGNoYW5nZWQpIHNvIHRoYXQgdGhlIGlubmVyIGNvdW50ZXIgaW5kZXggdmFsdWUgaXMgaW5jcmVtZW50ZWQuXG4gKiBUaGlzIHdheSwgZWFjaCBpbnN0cnVjdGlvbiBpcyBhbHdheXMgZ3VhcmFudGVlZCB0byBnZXQgdGhlIHNhbWUgY291bnRlclxuICogc3RhdGUgZWFjaCB0aW1lIGl0J3MgY2FsbGVkICh3aGljaCB0aGVuIGFsbG93cyB0aGUgYFRTdHlsaW5nQ29udGV4dGBcbiAqIGFuZCB0aGUgYml0IG1hc2sgdmFsdWVzIHRvIGJlIGluIHN5bmMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlU3R5bGVCaW5kaW5nKFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgZGF0YTogTFN0eWxpbmdEYXRhLCBwcm9wOiBzdHJpbmcgfCBudWxsLCBiaW5kaW5nSW5kZXg6IG51bWJlcixcbiAgICB2YWx1ZTogU3RyaW5nIHwgc3RyaW5nIHwgbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCB8IExTdHlsaW5nTWFwLFxuICAgIHNhbml0aXplcjogU3R5bGVTYW5pdGl6ZUZuIHwgbnVsbCwgZGVmZXJSZWdpc3RyYXRpb246IGJvb2xlYW4sIGZvcmNlVXBkYXRlOiBib29sZWFuKTogdm9pZCB7XG4gIGNvbnN0IGlzTWFwQmFzZWQgPSAhcHJvcDtcbiAgY29uc3QgaW5kZXggPSBpc01hcEJhc2VkID8gU1RZTElOR19JTkRFWF9GT1JfTUFQX0JJTkRJTkcgOiBjdXJyZW50U3R5bGVJbmRleCsrO1xuICBjb25zdCBzYW5pdGl6YXRpb25SZXF1aXJlZCA9IGlzTWFwQmFzZWQgP1xuICAgICAgdHJ1ZSA6XG4gICAgICAoc2FuaXRpemVyID8gc2FuaXRpemVyKHByb3AgISwgbnVsbCwgU3R5bGVTYW5pdGl6ZU1vZGUuVmFsaWRhdGVQcm9wZXJ0eSkgOiBmYWxzZSk7XG4gIGNvbnN0IHVwZGF0ZWQgPSB1cGRhdGVCaW5kaW5nRGF0YShcbiAgICAgIGNvbnRleHQsIGRhdGEsIGluZGV4LCBwcm9wLCBiaW5kaW5nSW5kZXgsIHZhbHVlLCBkZWZlclJlZ2lzdHJhdGlvbiwgZm9yY2VVcGRhdGUsXG4gICAgICBzYW5pdGl6YXRpb25SZXF1aXJlZCk7XG4gIGlmICh1cGRhdGVkIHx8IGZvcmNlVXBkYXRlKSB7XG4gICAgc3R5bGVzQml0TWFzayB8PSAxIDw8IGluZGV4O1xuICB9XG59XG5cbi8qKlxuICogQ2FsbGVkIGVhY2ggdGltZSBhIGJpbmRpbmcgdmFsdWUgaGFzIGNoYW5nZWQgd2l0aGluIHRoZSBwcm92aWRlZCBgVFN0eWxpbmdDb250ZXh0YC5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGRlc2lnbmVkIHRvIGJlIGNhbGxlZCBmcm9tIGB1cGRhdGVTdHlsZUJpbmRpbmdgIGFuZCBgdXBkYXRlQ2xhc3NCaW5kaW5nYC5cbiAqIElmIGNhbGxlZCBkdXJpbmcgdGhlIGZpcnN0IHVwZGF0ZSBwYXNzLCB0aGUgYmluZGluZyB3aWxsIGJlIHJlZ2lzdGVyZWQgaW4gdGhlIGNvbnRleHQuXG4gKiBJZiB0aGUgYmluZGluZyBkb2VzIGdldCByZWdpc3RlcmVkIGFuZCB0aGUgYGRlZmVyUmVnaXN0cmF0aW9uYCBmbGFnIGlzIHRydWUgdGhlbiB0aGVcbiAqIGJpbmRpbmcgZGF0YSB3aWxsIGJlIHF1ZXVlZCB1cCB1bnRpbCB0aGUgY29udGV4dCBpcyBsYXRlciBmbHVzaGVkIGluIGBhcHBseVN0eWxpbmdgLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBhbHNvIHVwZGF0ZSBiaW5kaW5nIHNsb3QgaW4gdGhlIHByb3ZpZGVkIGBMU3R5bGluZ0RhdGFgIHdpdGggdGhlXG4gKiBuZXcgYmluZGluZyBlbnRyeSAoaWYgaXQgaGFzIGNoYW5nZWQpLlxuICpcbiAqIEByZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBiaW5kaW5nIHZhbHVlIHdhcyB1cGRhdGVkIGluIHRoZSBgTFN0eWxpbmdEYXRhYC5cbiAqL1xuZnVuY3Rpb24gdXBkYXRlQmluZGluZ0RhdGEoXG4gICAgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LCBkYXRhOiBMU3R5bGluZ0RhdGEsIGNvdW50ZXJJbmRleDogbnVtYmVyLCBwcm9wOiBzdHJpbmcgfCBudWxsLFxuICAgIGJpbmRpbmdJbmRleDogbnVtYmVyLFxuICAgIHZhbHVlOiBzdHJpbmcgfCBTdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgbnVsbCB8IHVuZGVmaW5lZCB8IExTdHlsaW5nTWFwLFxuICAgIGRlZmVyUmVnaXN0cmF0aW9uOiBib29sZWFuLCBmb3JjZVVwZGF0ZTogYm9vbGVhbiwgc2FuaXRpemF0aW9uUmVxdWlyZWQ6IGJvb2xlYW4pOiBib29sZWFuIHtcbiAgaWYgKCFpc0NvbnRleHRMb2NrZWQoY29udGV4dCkpIHtcbiAgICBpZiAoZGVmZXJSZWdpc3RyYXRpb24pIHtcbiAgICAgIGRlZmVyQmluZGluZ1JlZ2lzdHJhdGlvbihjb250ZXh0LCBjb3VudGVySW5kZXgsIHByb3AsIGJpbmRpbmdJbmRleCwgc2FuaXRpemF0aW9uUmVxdWlyZWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWZlcnJlZEJpbmRpbmdRdWV1ZS5sZW5ndGggJiYgZmx1c2hEZWZlcnJlZEJpbmRpbmdzKCk7XG5cbiAgICAgIC8vIHRoaXMgd2lsbCBvbmx5IGhhcHBlbiBkdXJpbmcgdGhlIGZpcnN0IHVwZGF0ZSBwYXNzIG9mIHRoZVxuICAgICAgLy8gY29udGV4dC4gVGhlIHJlYXNvbiB3aHkgd2UgY2FuJ3QgdXNlIGB0Tm9kZS5maXJzdFRlbXBsYXRlUGFzc2BcbiAgICAgIC8vIGhlcmUgaXMgYmVjYXVzZSBpdHMgbm90IGd1YXJhbnRlZWQgdG8gYmUgdHJ1ZSB3aGVuIHRoZSBmaXJzdFxuICAgICAgLy8gdXBkYXRlIHBhc3MgaXMgZXhlY3V0ZWQgKHJlbWVtYmVyIHRoYXQgYWxsIHN0eWxpbmcgaW5zdHJ1Y3Rpb25zXG4gICAgICAvLyBhcmUgcnVuIGluIHRoZSB1cGRhdGUgcGhhc2UsIGFuZCwgYXMgYSByZXN1bHQsIGFyZSBubyBtb3JlXG4gICAgICAvLyBzdHlsaW5nIGluc3RydWN0aW9ucyB0aGF0IGFyZSBydW4gaW4gdGhlIGNyZWF0aW9uIHBoYXNlKS5cbiAgICAgIHJlZ2lzdGVyQmluZGluZyhjb250ZXh0LCBjb3VudGVySW5kZXgsIHByb3AsIGJpbmRpbmdJbmRleCwgc2FuaXRpemF0aW9uUmVxdWlyZWQpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGNoYW5nZWQgPSBmb3JjZVVwZGF0ZSB8fCBoYXNWYWx1ZUNoYW5nZWQoZGF0YVtiaW5kaW5nSW5kZXhdLCB2YWx1ZSk7XG4gIGlmIChjaGFuZ2VkKSB7XG4gICAgZGF0YVtiaW5kaW5nSW5kZXhdID0gdmFsdWU7XG4gIH1cbiAgcmV0dXJuIGNoYW5nZWQ7XG59XG5cbi8qKlxuICogU2NoZWR1bGVzIGEgYmluZGluZyByZWdpc3RyYXRpb24gdG8gYmUgcnVuIGF0IGEgbGF0ZXIgcG9pbnQuXG4gKlxuICogVGhlIHJlYXNvbmluZyBmb3IgdGhpcyBmZWF0dXJlIGlzIHRvIGVuc3VyZSB0aGF0IHN0eWxpbmdcbiAqIGJpbmRpbmdzIGFyZSByZWdpc3RlcmVkIGluIHRoZSBjb3JyZWN0IG9yZGVyIGZvciB3aGVuXG4gKiBkaXJlY3RpdmVzL2NvbXBvbmVudHMgaGF2ZSBhIHN1cGVyL3N1YiBjbGFzcyBpbmhlcml0YW5jZVxuICogY2hhaW5zLiBFYWNoIGRpcmVjdGl2ZSdzIHN0eWxpbmcgYmluZGluZ3MgbXVzdCBiZVxuICogcmVnaXN0ZXJlZCBpbnRvIHRoZSBjb250ZXh0IGluIHJldmVyc2Ugb3JkZXIuIFRoZXJlZm9yZSBhbGxcbiAqIGJpbmRpbmdzIHdpbGwgYmUgYnVmZmVyZWQgaW4gcmV2ZXJzZSBvcmRlciBhbmQgdGhlbiBhcHBsaWVkXG4gKiBhZnRlciB0aGUgaW5oZXJpdGFuY2UgY2hhaW4gZXhpdHMuXG4gKi9cbmZ1bmN0aW9uIGRlZmVyQmluZGluZ1JlZ2lzdHJhdGlvbihcbiAgICBjb250ZXh0OiBUU3R5bGluZ0NvbnRleHQsIGNvdW50ZXJJbmRleDogbnVtYmVyLCBwcm9wOiBzdHJpbmcgfCBudWxsLCBiaW5kaW5nSW5kZXg6IG51bWJlcixcbiAgICBzYW5pdGl6YXRpb25SZXF1aXJlZDogYm9vbGVhbikge1xuICBkZWZlcnJlZEJpbmRpbmdRdWV1ZS51bnNoaWZ0KGNvbnRleHQsIGNvdW50ZXJJbmRleCwgcHJvcCwgYmluZGluZ0luZGV4LCBzYW5pdGl6YXRpb25SZXF1aXJlZCk7XG59XG5cbi8qKlxuICogRmx1c2hlcyB0aGUgY29sbGVjdGlvbiBvZiBkZWZlcnJlZCBiaW5kaW5ncyBhbmQgY2F1c2VzIGVhY2ggZW50cnlcbiAqIHRvIGJlIHJlZ2lzdGVyZWQgaW50byB0aGUgY29udGV4dC5cbiAqL1xuZnVuY3Rpb24gZmx1c2hEZWZlcnJlZEJpbmRpbmdzKCkge1xuICBsZXQgaSA9IDA7XG4gIHdoaWxlIChpIDwgZGVmZXJyZWRCaW5kaW5nUXVldWUubGVuZ3RoKSB7XG4gICAgY29uc3QgY29udGV4dCA9IGRlZmVycmVkQmluZGluZ1F1ZXVlW2krK10gYXMgVFN0eWxpbmdDb250ZXh0O1xuICAgIGNvbnN0IGNvdW50ID0gZGVmZXJyZWRCaW5kaW5nUXVldWVbaSsrXSBhcyBudW1iZXI7XG4gICAgY29uc3QgcHJvcCA9IGRlZmVycmVkQmluZGluZ1F1ZXVlW2krK10gYXMgc3RyaW5nO1xuICAgIGNvbnN0IGJpbmRpbmdJbmRleCA9IGRlZmVycmVkQmluZGluZ1F1ZXVlW2krK10gYXMgbnVtYmVyIHwgbnVsbDtcbiAgICBjb25zdCBzYW5pdGl6YXRpb25SZXF1aXJlZCA9IGRlZmVycmVkQmluZGluZ1F1ZXVlW2krK10gYXMgYm9vbGVhbjtcbiAgICByZWdpc3RlckJpbmRpbmcoY29udGV4dCwgY291bnQsIHByb3AsIGJpbmRpbmdJbmRleCwgc2FuaXRpemF0aW9uUmVxdWlyZWQpO1xuICB9XG4gIGRlZmVycmVkQmluZGluZ1F1ZXVlLmxlbmd0aCA9IDA7XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIHRoZSBwcm92aWRlZCBiaW5kaW5nIChwcm9wICsgYmluZGluZ0luZGV4KSBpbnRvIHRoZSBjb250ZXh0LlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgc2hhcmVkIGJldHdlZW4gYmluZGluZ3MgdGhhdCBhcmUgYXNzaWduZWQgaW1tZWRpYXRlbHlcbiAqICh2aWEgYHVwZGF0ZUJpbmRpbmdEYXRhYCkgYW5kIGF0IGEgZGVmZXJyZWQgc3RhZ2UuIFdoZW4gY2FsbGVkLCBpdCB3aWxsXG4gKiBmaWd1cmUgb3V0IGV4YWN0bHkgd2hlcmUgdG8gcGxhY2UgdGhlIGJpbmRpbmcgZGF0YSBpbiB0aGUgY29udGV4dC5cbiAqXG4gKiBJdCBpcyBuZWVkZWQgYmVjYXVzZSBpdCB3aWxsIGVpdGhlciB1cGRhdGUgb3IgaW5zZXJ0IGEgc3R5bGluZyBwcm9wZXJ0eVxuICogaW50byB0aGUgY29udGV4dCBhdCB0aGUgY29ycmVjdCBzcG90LlxuICpcbiAqIFdoZW4gY2FsbGVkLCBvbmUgb2YgdHdvIHRoaW5ncyB3aWxsIGhhcHBlbjpcbiAqXG4gKiAxKSBJZiB0aGUgcHJvcGVydHkgYWxyZWFkeSBleGlzdHMgaW4gdGhlIGNvbnRleHQgdGhlbiBpdCB3aWxsIGp1c3QgYWRkXG4gKiAgICB0aGUgcHJvdmlkZWQgYGJpbmRpbmdWYWx1ZWAgdG8gdGhlIGVuZCBvZiB0aGUgYmluZGluZyBzb3VyY2VzIHJlZ2lvblxuICogICAgZm9yIHRoYXQgcGFydGljdWxhciBwcm9wZXJ0eS5cbiAqXG4gKiAgICAtIElmIHRoZSBiaW5kaW5nIHZhbHVlIGlzIGEgbnVtYmVyIHRoZW4gaXQgd2lsbCBiZSBhZGRlZCBhcyBhIG5ld1xuICogICAgICBiaW5kaW5nIGluZGV4IHNvdXJjZSBuZXh0IHRvIHRoZSBvdGhlciBiaW5kaW5nIHNvdXJjZXMgZm9yIHRoZSBwcm9wZXJ0eS5cbiAqXG4gKiAgICAtIE90aGVyd2lzZSwgaWYgdGhlIGJpbmRpbmcgdmFsdWUgaXMgYSBzdHJpbmcvYm9vbGVhbi9udWxsIHR5cGUgdGhlbiBpdCB3aWxsXG4gKiAgICAgIHJlcGxhY2UgdGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSBwcm9wZXJ0eSBpZiB0aGUgZGVmYXVsdCB2YWx1ZSBpcyBgbnVsbGAuXG4gKlxuICogMikgSWYgdGhlIHByb3BlcnR5IGRvZXMgbm90IGV4aXN0IHRoZW4gaXQgd2lsbCBiZSBpbnNlcnRlZCBpbnRvIHRoZSBjb250ZXh0LlxuICogICAgVGhlIHN0eWxpbmcgY29udGV4dCByZWxpZXMgb24gYWxsIHByb3BlcnRpZXMgYmVpbmcgc3RvcmVkIGluIGFscGhhYmV0aWNhbFxuICogICAgb3JkZXIsIHNvIGl0IGtub3dzIGV4YWN0bHkgd2hlcmUgdG8gc3RvcmUgaXQuXG4gKlxuICogICAgV2hlbiBpbnNlcnRlZCwgYSBkZWZhdWx0IGBudWxsYCB2YWx1ZSBpcyBjcmVhdGVkIGZvciB0aGUgcHJvcGVydHkgd2hpY2ggZXhpc3RzXG4gKiAgICBhcyB0aGUgZGVmYXVsdCB2YWx1ZSBmb3IgdGhlIGJpbmRpbmcuIElmIHRoZSBiaW5kaW5nVmFsdWUgcHJvcGVydHkgaXMgaW5zZXJ0ZWRcbiAqICAgIGFuZCBpdCBpcyBlaXRoZXIgYSBzdHJpbmcsIG51bWJlciBvciBudWxsIHZhbHVlIHRoZW4gdGhhdCB3aWxsIHJlcGxhY2UgdGhlIGRlZmF1bHRcbiAqICAgIHZhbHVlLlxuICpcbiAqIE5vdGUgdGhhdCB0aGlzIGZ1bmN0aW9uIGlzIGFsc28gdXNlZCBmb3IgbWFwLWJhc2VkIHN0eWxpbmcgYmluZGluZ3MuIFRoZXkgYXJlIHRyZWF0ZWRcbiAqIG11Y2ggdGhlIHNhbWUgYXMgcHJvcC1iYXNlZCBiaW5kaW5ncywgYnV0LCBiZWNhdXNlIHRoZXkgZG8gbm90IGhhdmUgYSBwcm9wZXJ0eSB2YWx1ZVxuICogKHNpbmNlIGl0J3MgYSBtYXApLCBhbGwgbWFwLWJhc2VkIGVudHJpZXMgYXJlIHN0b3JlZCBpbiBhbiBhbHJlYWR5IHBvcHVsYXRlZCBhcmVhIG9mXG4gKiB0aGUgY29udGV4dCBhdCB0aGUgdG9wICh3aGljaCBpcyByZXNlcnZlZCBmb3IgbWFwLWJhc2VkIGVudHJpZXMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJCaW5kaW5nKFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgY291bnRJZDogbnVtYmVyLCBwcm9wOiBzdHJpbmcgfCBudWxsLFxuICAgIGJpbmRpbmdWYWx1ZTogbnVtYmVyIHwgbnVsbCB8IHN0cmluZyB8IGJvb2xlYW4sIHNhbml0aXphdGlvblJlcXVpcmVkPzogYm9vbGVhbikge1xuICAvLyBwcm9wLWJhc2VkIGJpbmRpbmdzIChlLmcgYDxkaXYgW3N0eWxlLndpZHRoXT1cIndcIiBbY2xhc3MuZm9vXT1cImZcIj5gKVxuICBpZiAocHJvcCkge1xuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGxldCBpID0gZ2V0UHJvcFZhbHVlc1N0YXJ0UG9zaXRpb24oY29udGV4dCk7XG4gICAgd2hpbGUgKGkgPCBjb250ZXh0Lmxlbmd0aCkge1xuICAgICAgY29uc3QgdmFsdWVzQ291bnQgPSBnZXRWYWx1ZXNDb3VudChjb250ZXh0LCBpKTtcbiAgICAgIGNvbnN0IHAgPSBnZXRQcm9wKGNvbnRleHQsIGkpO1xuICAgICAgZm91bmQgPSBwcm9wIDw9IHA7XG4gICAgICBpZiAoZm91bmQpIHtcbiAgICAgICAgLy8gYWxsIHN0eWxlL2NsYXNzIGJpbmRpbmdzIGFyZSBzb3J0ZWQgYnkgcHJvcGVydHkgbmFtZVxuICAgICAgICBpZiAocHJvcCA8IHApIHtcbiAgICAgICAgICBhbGxvY2F0ZU5ld0NvbnRleHRFbnRyeShjb250ZXh0LCBpLCBwcm9wLCBzYW5pdGl6YXRpb25SZXF1aXJlZCk7XG4gICAgICAgIH1cbiAgICAgICAgYWRkQmluZGluZ0ludG9Db250ZXh0KGNvbnRleHQsIGZhbHNlLCBpLCBiaW5kaW5nVmFsdWUsIGNvdW50SWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGkgKz0gVFN0eWxpbmdDb250ZXh0SW5kZXguQmluZGluZ3NTdGFydE9mZnNldCArIHZhbHVlc0NvdW50O1xuICAgIH1cblxuICAgIGlmICghZm91bmQpIHtcbiAgICAgIGFsbG9jYXRlTmV3Q29udGV4dEVudHJ5KGNvbnRleHQsIGNvbnRleHQubGVuZ3RoLCBwcm9wLCBzYW5pdGl6YXRpb25SZXF1aXJlZCk7XG4gICAgICBhZGRCaW5kaW5nSW50b0NvbnRleHQoY29udGV4dCwgZmFsc2UsIGksIGJpbmRpbmdWYWx1ZSwgY291bnRJZCk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIG1hcC1iYXNlZCBiaW5kaW5ncyAoZS5nIGA8ZGl2IFtzdHlsZV09XCJzXCIgW2NsYXNzXT1cIntjbGFzc05hbWU6dHJ1ZX1cIj5gKVxuICAgIC8vIHRoZXJlIGlzIG5vIG5lZWQgdG8gYWxsb2NhdGUgdGhlIG1hcC1iYXNlZCBiaW5kaW5nIHJlZ2lvbiBpbnRvIHRoZSBjb250ZXh0XG4gICAgLy8gc2luY2UgaXQgaXMgYWxyZWFkeSB0aGVyZSB3aGVuIHRoZSBjb250ZXh0IGlzIGZpcnN0IGNyZWF0ZWQuXG4gICAgYWRkQmluZGluZ0ludG9Db250ZXh0KFxuICAgICAgICBjb250ZXh0LCB0cnVlLCBUU3R5bGluZ0NvbnRleHRJbmRleC5NYXBCaW5kaW5nc1Bvc2l0aW9uLCBiaW5kaW5nVmFsdWUsIGNvdW50SWQpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGFsbG9jYXRlTmV3Q29udGV4dEVudHJ5KFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgaW5kZXg6IG51bWJlciwgcHJvcDogc3RyaW5nLCBzYW5pdGl6YXRpb25SZXF1aXJlZD86IGJvb2xlYW4pIHtcbiAgLy8gMSwyOiBzcGxpY2UgaW5kZXggbG9jYXRpb25zXG4gIC8vIDM6IGVhY2ggZW50cnkgZ2V0cyBhIGNvbmZpZyB2YWx1ZSAoZ3VhcmQgbWFzayArIGZsYWdzKVxuICAvLyA0LiBlYWNoIGVudHJ5IGdldHMgYSBzaXplIHZhbHVlICh3aGljaCBpcyBhbHdheXMgb25lIGJlY2F1c2UgdGhlcmUgaXMgYWx3YXlzIGEgZGVmYXVsdCBiaW5kaW5nXG4gIC8vIHZhbHVlKVxuICAvLyA1LiB0aGUgcHJvcGVydHkgdGhhdCBpcyBnZXR0aW5nIGFsbG9jYXRlZCBpbnRvIHRoZSBjb250ZXh0XG4gIC8vIDYuIHRoZSBkZWZhdWx0IGJpbmRpbmcgdmFsdWUgKHVzdWFsbHkgYG51bGxgKVxuICBjb25zdCBjb25maWcgPSBzYW5pdGl6YXRpb25SZXF1aXJlZCA/IFRTdHlsaW5nQ29udGV4dFByb3BDb25maWdGbGFncy5TYW5pdGl6YXRpb25SZXF1aXJlZCA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFN0eWxpbmdDb250ZXh0UHJvcENvbmZpZ0ZsYWdzLkRlZmF1bHQ7XG4gIGNvbnRleHQuc3BsaWNlKGluZGV4LCAwLCBjb25maWcsIERFRkFVTFRfU0laRV9WQUxVRSwgcHJvcCwgREVGQVVMVF9CSU5ESU5HX1ZBTFVFKTtcbiAgc2V0R3VhcmRNYXNrKGNvbnRleHQsIGluZGV4LCBERUZBVUxUX0dVQVJEX01BU0tfVkFMVUUpO1xufVxuXG4vKipcbiAqIEluc2VydHMgYSBuZXcgYmluZGluZyB2YWx1ZSBpbnRvIGEgc3R5bGluZyBwcm9wZXJ0eSB0dXBsZSBpbiB0aGUgYFRTdHlsaW5nQ29udGV4dGAuXG4gKlxuICogQSBiaW5kaW5nVmFsdWUgaXMgaW5zZXJ0ZWQgaW50byBhIGNvbnRleHQgZHVyaW5nIHRoZSBmaXJzdCB1cGRhdGUgcGFzc1xuICogb2YgYSB0ZW1wbGF0ZSBvciBob3N0IGJpbmRpbmdzIGZ1bmN0aW9uLiBXaGVuIHRoaXMgb2NjdXJzLCB0d28gdGhpbmdzXG4gKiBoYXBwZW46XG4gKlxuICogLSBJZiB0aGUgYmluZGluZ1ZhbHVlIHZhbHVlIGlzIGEgbnVtYmVyIHRoZW4gaXQgaXMgdHJlYXRlZCBhcyBhIGJpbmRpbmdJbmRleFxuICogICB2YWx1ZSAoYSBpbmRleCBpbiB0aGUgYExWaWV3YCkgYW5kIGl0IHdpbGwgYmUgaW5zZXJ0ZWQgbmV4dCB0byB0aGUgb3RoZXJcbiAqICAgYmluZGluZyBpbmRleCBlbnRyaWVzLlxuICpcbiAqIC0gT3RoZXJ3aXNlIHRoZSBiaW5kaW5nIHZhbHVlIHdpbGwgdXBkYXRlIHRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgcHJvcGVydHlcbiAqICAgYW5kIHRoaXMgd2lsbCBvbmx5IGhhcHBlbiBpZiB0aGUgZGVmYXVsdCB2YWx1ZSBpcyBgbnVsbGAuXG4gKlxuICogTm90ZSB0aGF0IHRoaXMgZnVuY3Rpb24gYWxzbyBoYW5kbGVzIG1hcC1iYXNlZCBiaW5kaW5ncyBhbmQgd2lsbCBpbnNlcnQgdGhlbVxuICogYXQgdGhlIHRvcCBvZiB0aGUgY29udGV4dC5cbiAqL1xuZnVuY3Rpb24gYWRkQmluZGluZ0ludG9Db250ZXh0KFxuICAgIGNvbnRleHQ6IFRTdHlsaW5nQ29udGV4dCwgaXNNYXBCYXNlZDogYm9vbGVhbiwgaW5kZXg6IG51bWJlcixcbiAgICBiaW5kaW5nVmFsdWU6IG51bWJlciB8IHN0cmluZyB8IGJvb2xlYW4gfCBudWxsLCBjb3VudElkOiBudW1iZXIpIHtcbiAgY29uc3QgdmFsdWVzQ291bnQgPSBnZXRWYWx1ZXNDb3VudChjb250ZXh0LCBpbmRleCk7XG5cbiAgbGV0IGxhc3RWYWx1ZUluZGV4ID0gaW5kZXggKyBUU3R5bGluZ0NvbnRleHRJbmRleC5CaW5kaW5nc1N0YXJ0T2Zmc2V0ICsgdmFsdWVzQ291bnQ7XG4gIGlmICghaXNNYXBCYXNlZCkge1xuICAgIC8vIHByb3AtYmFzZWQgdmFsdWVzIGFsbCBoYXZlIGRlZmF1bHQgdmFsdWVzLCBidXQgbWFwLWJhc2VkIGVudHJpZXMgZG8gbm90LlxuICAgIC8vIHdlIHdhbnQgdG8gYWNjZXNzIHRoZSBpbmRleCBmb3IgdGhlIGRlZmF1bHQgdmFsdWUgaW4gdGhpcyBjYXNlIGFuZCBub3QganVzdFxuICAgIC8vIHRoZSBiaW5kaW5ncy4uLlxuICAgIGxhc3RWYWx1ZUluZGV4LS07XG4gIH1cblxuICBpZiAodHlwZW9mIGJpbmRpbmdWYWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICBjb250ZXh0LnNwbGljZShsYXN0VmFsdWVJbmRleCwgMCwgYmluZGluZ1ZhbHVlKTtcbiAgICAoY29udGV4dFtpbmRleCArIFRTdHlsaW5nQ29udGV4dEluZGV4LlZhbHVlc0NvdW50T2Zmc2V0XSBhcyBudW1iZXIpKys7XG5cbiAgICAvLyBub3cgdGhhdCBhIG5ldyBiaW5kaW5nIGluZGV4IGhhcyBiZWVuIGFkZGVkIHRvIHRoZSBwcm9wZXJ0eVxuICAgIC8vIHRoZSBndWFyZCBtYXNrIGJpdCB2YWx1ZSAoYXQgdGhlIGBjb3VudElkYCBwb3NpdGlvbikgbmVlZHNcbiAgICAvLyB0byBiZSBpbmNsdWRlZCBpbnRvIHRoZSBleGlzdGluZyBtYXNrIHZhbHVlLlxuICAgIGNvbnN0IGd1YXJkTWFzayA9IGdldEd1YXJkTWFzayhjb250ZXh0LCBpbmRleCkgfCAoMSA8PCBjb3VudElkKTtcbiAgICBzZXRHdWFyZE1hc2soY29udGV4dCwgaW5kZXgsIGd1YXJkTWFzayk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGJpbmRpbmdWYWx1ZSA9PT0gJ3N0cmluZycgJiYgY29udGV4dFtsYXN0VmFsdWVJbmRleF0gPT0gbnVsbCkge1xuICAgIGNvbnRleHRbbGFzdFZhbHVlSW5kZXhdID0gYmluZGluZ1ZhbHVlO1xuICB9XG59XG5cbi8qKlxuICogQXBwbGllcyBhbGwgY2xhc3MgZW50cmllcyBpbiB0aGUgcHJvdmlkZWQgY29udGV4dCB0byB0aGUgcHJvdmlkZWQgZWxlbWVudCBhbmQgcmVzZXRzXG4gKiBhbnkgY291bnRlciBhbmQvb3IgYml0TWFzayB2YWx1ZXMgYXNzb2NpYXRlZCB3aXRoIGNsYXNzIGJpbmRpbmdzLlxuICpcbiAqIEByZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBjbGFzc2VzIHdlcmUgZmx1c2hlZCB0byB0aGUgZWxlbWVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5Q2xhc3NlcyhcbiAgICByZW5kZXJlcjogUmVuZGVyZXIzIHwgUHJvY2VkdXJhbFJlbmRlcmVyMyB8IG51bGwsIGRhdGE6IExTdHlsaW5nRGF0YSwgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LFxuICAgIGVsZW1lbnQ6IFJFbGVtZW50LCBkaXJlY3RpdmVJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gIGxldCBjbGFzc2VzRmx1c2hlZCA9IGZhbHNlO1xuICBpZiAoYWxsb3dTdHlsaW5nRmx1c2goY29udGV4dCwgZGlyZWN0aXZlSW5kZXgpKSB7XG4gICAgY29uc3QgaXNGaXJzdFBhc3MgPSAhaXNDb250ZXh0TG9ja2VkKGNvbnRleHQpO1xuICAgIGlzRmlyc3RQYXNzICYmIGxvY2tDb250ZXh0KGNvbnRleHQpO1xuICAgIGlmIChjbGFzc2VzQml0TWFzaykge1xuICAgICAgLy8gdGhlcmUgaXMgbm8gd2F5IHRvIHNhbml0aXplIGEgY2xhc3MgdmFsdWUgdGhlcmVmb3JlIGBzYW5pdGl6ZXI9bnVsbGBcbiAgICAgIGFwcGx5U3R5bGluZyhjb250ZXh0LCByZW5kZXJlciwgZWxlbWVudCwgZGF0YSwgY2xhc3Nlc0JpdE1hc2ssIHNldENsYXNzLCBudWxsKTtcbiAgICAgIGNsYXNzZXNCaXRNYXNrID0gMDtcbiAgICAgIGNsYXNzZXNGbHVzaGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgY3VycmVudENsYXNzSW5kZXggPSBTVFlMSU5HX0lOREVYX1NUQVJUX1ZBTFVFO1xuICB9XG4gIHJldHVybiBjbGFzc2VzRmx1c2hlZDtcbn1cblxuLyoqXG4gKiBBcHBsaWVzIGFsbCBzdHlsZSBlbnRyaWVzIGluIHRoZSBwcm92aWRlZCBjb250ZXh0IHRvIHRoZSBwcm92aWRlZCBlbGVtZW50IGFuZCByZXNldHNcbiAqIGFueSBjb3VudGVyIGFuZC9vciBiaXRNYXNrIHZhbHVlcyBhc3NvY2lhdGVkIHdpdGggc3R5bGUgYmluZGluZ3MuXG4gKlxuICogQHJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHN0eWxlcyB3ZXJlIGZsdXNoZWQgdG8gdGhlIGVsZW1lbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVN0eWxlcyhcbiAgICByZW5kZXJlcjogUmVuZGVyZXIzIHwgUHJvY2VkdXJhbFJlbmRlcmVyMyB8IG51bGwsIGRhdGE6IExTdHlsaW5nRGF0YSwgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LFxuICAgIGVsZW1lbnQ6IFJFbGVtZW50LCBkaXJlY3RpdmVJbmRleDogbnVtYmVyLCBzYW5pdGl6ZXI6IFN0eWxlU2FuaXRpemVGbiB8IG51bGwpOiBib29sZWFuIHtcbiAgbGV0IHN0eWxlc0ZsdXNoZWQgPSBmYWxzZTtcbiAgaWYgKGFsbG93U3R5bGluZ0ZsdXNoKGNvbnRleHQsIGRpcmVjdGl2ZUluZGV4KSkge1xuICAgIGNvbnN0IGlzRmlyc3RQYXNzID0gIWlzQ29udGV4dExvY2tlZChjb250ZXh0KTtcbiAgICBpc0ZpcnN0UGFzcyAmJiBsb2NrQ29udGV4dChjb250ZXh0KTtcbiAgICBpZiAoc3R5bGVzQml0TWFzaykge1xuICAgICAgYXBwbHlTdHlsaW5nKGNvbnRleHQsIHJlbmRlcmVyLCBlbGVtZW50LCBkYXRhLCBzdHlsZXNCaXRNYXNrLCBzZXRTdHlsZSwgc2FuaXRpemVyKTtcbiAgICAgIHN0eWxlc0JpdE1hc2sgPSAwO1xuICAgICAgc3R5bGVzRmx1c2hlZCA9IHRydWU7XG4gICAgfVxuICAgIGN1cnJlbnRTdHlsZUluZGV4ID0gU1RZTElOR19JTkRFWF9TVEFSVF9WQUxVRTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gc3R5bGVzRmx1c2hlZDtcbn1cblxuLyoqXG4gKiBSdW5zIHRocm91Z2ggdGhlIHByb3ZpZGVkIHN0eWxpbmcgY29udGV4dCBhbmQgYXBwbGllcyBlYWNoIHZhbHVlIHRvXG4gKiB0aGUgcHJvdmlkZWQgZWxlbWVudCAodmlhIHRoZSByZW5kZXJlcikgaWYgb25lIG9yIG1vcmUgdmFsdWVzIGFyZSBwcmVzZW50LlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBpdGVyYXRlIG92ZXIgYWxsIGVudHJpZXMgcHJlc2VudCBpbiB0aGUgcHJvdmlkZWRcbiAqIGBUU3R5bGluZ0NvbnRleHRgIGFycmF5IChib3RoIHByb3AtYmFzZWQgYW5kIG1hcC1iYXNlZCBiaW5kaW5ncykuLVxuICpcbiAqIEVhY2ggZW50cnksIHdpdGhpbiB0aGUgYFRTdHlsaW5nQ29udGV4dGAgYXJyYXksIGlzIHN0b3JlZCBhbHBoYWJldGljYWxseVxuICogYW5kIHRoaXMgbWVhbnMgdGhhdCBlYWNoIHByb3AvdmFsdWUgZW50cnkgd2lsbCBiZSBhcHBsaWVkIGluIG9yZGVyXG4gKiAoc28gbG9uZyBhcyBpdCBpcyBtYXJrZWQgZGlydHkgaW4gdGhlIHByb3ZpZGVkIGBiaXRNYXNrYCB2YWx1ZSkuXG4gKlxuICogSWYgdGhlcmUgYXJlIGFueSBtYXAtYmFzZWQgZW50cmllcyBwcmVzZW50ICh3aGljaCBhcmUgYXBwbGllZCB0byB0aGVcbiAqIGVsZW1lbnQgdmlhIHRoZSBgW3N0eWxlXWAgYW5kIGBbY2xhc3NdYCBiaW5kaW5ncykgdGhlbiB0aG9zZSBlbnRyaWVzXG4gKiB3aWxsIGJlIGFwcGxpZWQgYXMgd2VsbC4gSG93ZXZlciwgdGhlIGNvZGUgZm9yIHRoYXQgaXMgbm90IGFwYXJ0IG9mXG4gKiB0aGlzIGZ1bmN0aW9uLiBJbnN0ZWFkLCBlYWNoIHRpbWUgYSBwcm9wZXJ0eSBpcyB2aXNpdGVkLCB0aGVuIHRoZVxuICogY29kZSBiZWxvdyB3aWxsIGNhbGwgYW4gZXh0ZXJuYWwgZnVuY3Rpb24gY2FsbGVkIGBzdHlsaW5nTWFwc1N5bmNGbmBcbiAqIGFuZCwgaWYgcHJlc2VudCwgaXQgd2lsbCBrZWVwIHRoZSBhcHBsaWNhdGlvbiBvZiBzdHlsaW5nIHZhbHVlcyBpblxuICogbWFwLWJhc2VkIGJpbmRpbmdzIHVwIHRvIHN5bmMgd2l0aCB0aGUgYXBwbGljYXRpb24gb2YgcHJvcC1iYXNlZFxuICogYmluZGluZ3MuXG4gKlxuICogVmlzaXQgYHN0eWxpbmdfbmV4dC9tYXBfYmFzZWRfYmluZGluZ3MudHNgIHRvIGxlYXJuIG1vcmUgYWJvdXQgaG93IHRoZVxuICogYWxnb3JpdGhtIHdvcmtzIGZvciBtYXAtYmFzZWQgc3R5bGluZyBiaW5kaW5ncy5cbiAqXG4gKiBOb3RlIHRoYXQgdGhpcyBmdW5jdGlvbiBpcyBub3QgZGVzaWduZWQgdG8gYmUgY2FsbGVkIGluIGlzb2xhdGlvbiAodXNlXG4gKiBgYXBwbHlDbGFzc2VzYCBhbmQgYGFwcGx5U3R5bGVzYCB0byBhY3R1YWxseSBhcHBseSBzdHlsaW5nIHZhbHVlcykuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVN0eWxpbmcoXG4gICAgY29udGV4dDogVFN0eWxpbmdDb250ZXh0LCByZW5kZXJlcjogUmVuZGVyZXIzIHwgUHJvY2VkdXJhbFJlbmRlcmVyMyB8IG51bGwsIGVsZW1lbnQ6IFJFbGVtZW50LFxuICAgIGJpbmRpbmdEYXRhOiBMU3R5bGluZ0RhdGEsIGJpdE1hc2tWYWx1ZTogbnVtYmVyIHwgYm9vbGVhbiwgYXBwbHlTdHlsaW5nRm46IEFwcGx5U3R5bGluZ0ZuLFxuICAgIHNhbml0aXplcjogU3R5bGVTYW5pdGl6ZUZuIHwgbnVsbCkge1xuICBkZWZlcnJlZEJpbmRpbmdRdWV1ZS5sZW5ndGggJiYgZmx1c2hEZWZlcnJlZEJpbmRpbmdzKCk7XG5cbiAgY29uc3QgYml0TWFzayA9IG5vcm1hbGl6ZUJpdE1hc2tWYWx1ZShiaXRNYXNrVmFsdWUpO1xuICBjb25zdCBzdHlsaW5nTWFwc1N5bmNGbiA9IGdldFN0eWxpbmdNYXBzU3luY0ZuKCk7XG4gIGNvbnN0IG1hcHNHdWFyZE1hc2sgPSBnZXRHdWFyZE1hc2soY29udGV4dCwgVFN0eWxpbmdDb250ZXh0SW5kZXguTWFwQmluZGluZ3NQb3NpdGlvbik7XG4gIGNvbnN0IGFwcGx5QWxsVmFsdWVzID0gKGJpdE1hc2sgJiBtYXBzR3VhcmRNYXNrKSA+IDA7XG4gIGNvbnN0IG1hcHNNb2RlID1cbiAgICAgIGFwcGx5QWxsVmFsdWVzID8gU3R5bGluZ01hcHNTeW5jTW9kZS5BcHBseUFsbFZhbHVlcyA6IFN0eWxpbmdNYXBzU3luY01vZGUuVHJhdmVyc2VWYWx1ZXM7XG5cbiAgbGV0IGkgPSBnZXRQcm9wVmFsdWVzU3RhcnRQb3NpdGlvbihjb250ZXh0KTtcbiAgd2hpbGUgKGkgPCBjb250ZXh0Lmxlbmd0aCkge1xuICAgIGNvbnN0IHZhbHVlc0NvdW50ID0gZ2V0VmFsdWVzQ291bnQoY29udGV4dCwgaSk7XG4gICAgY29uc3QgZ3VhcmRNYXNrID0gZ2V0R3VhcmRNYXNrKGNvbnRleHQsIGkpO1xuICAgIGlmIChiaXRNYXNrICYgZ3VhcmRNYXNrKSB7XG4gICAgICBsZXQgdmFsdWVBcHBsaWVkID0gZmFsc2U7XG4gICAgICBjb25zdCBwcm9wID0gZ2V0UHJvcChjb250ZXh0LCBpKTtcbiAgICAgIGNvbnN0IHZhbHVlc0NvdW50VXBUb0RlZmF1bHQgPSB2YWx1ZXNDb3VudCAtIDE7XG4gICAgICBjb25zdCBkZWZhdWx0VmFsdWUgPSBnZXRCaW5kaW5nVmFsdWUoY29udGV4dCwgaSwgdmFsdWVzQ291bnRVcFRvRGVmYXVsdCkgYXMgc3RyaW5nIHwgbnVsbDtcblxuICAgICAgLy8gY2FzZSAxOiBhcHBseSBwcm9wLWJhc2VkIHZhbHVlc1xuICAgICAgLy8gdHJ5IHRvIGFwcGx5IHRoZSBiaW5kaW5nIHZhbHVlcyBhbmQgc2VlIGlmIGEgbm9uLW51bGxcbiAgICAgIC8vIHZhbHVlIGdldHMgc2V0IGZvciB0aGUgc3R5bGluZyBiaW5kaW5nXG4gICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHZhbHVlc0NvdW50VXBUb0RlZmF1bHQ7IGorKykge1xuICAgICAgICBjb25zdCBiaW5kaW5nSW5kZXggPSBnZXRCaW5kaW5nVmFsdWUoY29udGV4dCwgaSwgaikgYXMgbnVtYmVyO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGJpbmRpbmdEYXRhW2JpbmRpbmdJbmRleF07XG4gICAgICAgIGlmIChpc1N0eWxpbmdWYWx1ZURlZmluZWQodmFsdWUpKSB7XG4gICAgICAgICAgY29uc3QgZmluYWxWYWx1ZSA9IHNhbml0aXplciAmJiBpc1Nhbml0aXphdGlvblJlcXVpcmVkKGNvbnRleHQsIGkpID9cbiAgICAgICAgICAgICAgc2FuaXRpemVyKHByb3AsIHZhbHVlLCBTdHlsZVNhbml0aXplTW9kZS5TYW5pdGl6ZU9ubHkpIDpcbiAgICAgICAgICAgICAgdmFsdWU7XG4gICAgICAgICAgYXBwbHlTdHlsaW5nRm4ocmVuZGVyZXIsIGVsZW1lbnQsIHByb3AsIGZpbmFsVmFsdWUsIGJpbmRpbmdJbmRleCk7XG4gICAgICAgICAgdmFsdWVBcHBsaWVkID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBjYXNlIDI6IGFwcGx5IG1hcC1iYXNlZCB2YWx1ZXNcbiAgICAgIC8vIHRyYXZlcnNlIHRocm91Z2ggZWFjaCBtYXAtYmFzZWQgc3R5bGluZyBiaW5kaW5nIGFuZCB1cGRhdGUgYWxsIHZhbHVlcyB1cCB0b1xuICAgICAgLy8gdGhlIHByb3ZpZGVkIGBwcm9wYCB2YWx1ZS4gSWYgdGhlIHByb3BlcnR5IHdhcyBub3QgYXBwbGllZCBpbiB0aGUgbG9vcCBhYm92ZVxuICAgICAgLy8gdGhlbiBpdCB3aWxsIGJlIGF0dGVtcHRlZCB0byBiZSBhcHBsaWVkIGluIHRoZSBtYXBzIHN5bmMgY29kZSBiZWxvdy5cbiAgICAgIGlmIChzdHlsaW5nTWFwc1N5bmNGbikge1xuICAgICAgICAvLyBkZXRlcm1pbmUgd2hldGhlciBvciBub3QgdG8gYXBwbHkgdGhlIHRhcmdldCBwcm9wZXJ0eSBvciB0byBza2lwIGl0XG4gICAgICAgIGNvbnN0IG1vZGUgPSBtYXBzTW9kZSB8ICh2YWx1ZUFwcGxpZWQgPyBTdHlsaW5nTWFwc1N5bmNNb2RlLlNraXBUYXJnZXRQcm9wIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0eWxpbmdNYXBzU3luY01vZGUuQXBwbHlUYXJnZXRQcm9wKTtcbiAgICAgICAgY29uc3QgdmFsdWVBcHBsaWVkV2l0aGluTWFwID0gc3R5bGluZ01hcHNTeW5jRm4oXG4gICAgICAgICAgICBjb250ZXh0LCByZW5kZXJlciwgZWxlbWVudCwgYmluZGluZ0RhdGEsIGFwcGx5U3R5bGluZ0ZuLCBzYW5pdGl6ZXIsIG1vZGUsIHByb3AsXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWUpO1xuICAgICAgICB2YWx1ZUFwcGxpZWQgPSB2YWx1ZUFwcGxpZWQgfHwgdmFsdWVBcHBsaWVkV2l0aGluTWFwO1xuICAgICAgfVxuXG4gICAgICAvLyBjYXNlIDM6IGFwcGx5IHRoZSBkZWZhdWx0IHZhbHVlXG4gICAgICAvLyBpZiB0aGUgdmFsdWUgaGFzIG5vdCB5ZXQgYmVlbiBhcHBsaWVkIHRoZW4gYSB0cnV0aHkgdmFsdWUgZG9lcyBub3QgZXhpc3QgaW4gdGhlXG4gICAgICAvLyBwcm9wLWJhc2VkIG9yIG1hcC1iYXNlZCBiaW5kaW5ncyBjb2RlLiBJZiBhbmQgd2hlbiB0aGlzIGhhcHBlbnMsIGp1c3QgYXBwbHkgdGhlXG4gICAgICAvLyBkZWZhdWx0IHZhbHVlIChldmVuIGlmIHRoZSBkZWZhdWx0IHZhbHVlIGlzIGBudWxsYCkuXG4gICAgICBpZiAoIXZhbHVlQXBwbGllZCkge1xuICAgICAgICBhcHBseVN0eWxpbmdGbihyZW5kZXJlciwgZWxlbWVudCwgcHJvcCwgZGVmYXVsdFZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpICs9IFRTdHlsaW5nQ29udGV4dEluZGV4LkJpbmRpbmdzU3RhcnRPZmZzZXQgKyB2YWx1ZXNDb3VudDtcbiAgfVxuXG4gIC8vIHRoZSBtYXAtYmFzZWQgc3R5bGluZyBlbnRyaWVzIG1heSBoYXZlIG5vdCBhcHBsaWVkIGFsbCB0aGVpclxuICAvLyB2YWx1ZXMuIEZvciB0aGlzIHJlYXNvbiwgb25lIG1vcmUgY2FsbCB0byB0aGUgc3luYyBmdW5jdGlvblxuICAvLyBuZWVkcyB0byBiZSBpc3N1ZWQgYXQgdGhlIGVuZC5cbiAgaWYgKHN0eWxpbmdNYXBzU3luY0ZuKSB7XG4gICAgc3R5bGluZ01hcHNTeW5jRm4oY29udGV4dCwgcmVuZGVyZXIsIGVsZW1lbnQsIGJpbmRpbmdEYXRhLCBhcHBseVN0eWxpbmdGbiwgc2FuaXRpemVyLCBtYXBzTW9kZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplQml0TWFza1ZhbHVlKHZhbHVlOiBudW1iZXIgfCBib29sZWFuKTogbnVtYmVyIHtcbiAgLy8gaWYgcGFzcyA9PiBhcHBseSBhbGwgdmFsdWVzICgtMSBpbXBsaWVzIHRoYXQgYWxsIGJpdHMgYXJlIGZsaXBwZWQgdG8gdHJ1ZSlcbiAgaWYgKHZhbHVlID09PSB0cnVlKSByZXR1cm4gLTE7XG5cbiAgLy8gaWYgcGFzcyA9PiBza2lwIGFsbCB2YWx1ZXNcbiAgaWYgKHZhbHVlID09PSBmYWxzZSkgcmV0dXJuIDA7XG5cbiAgLy8gcmV0dXJuIHRoZSBiaXQgbWFzayB2YWx1ZSBhcyBpc1xuICByZXR1cm4gdmFsdWU7XG59XG5cbmxldCBfYWN0aXZlU3R5bGluZ01hcEFwcGx5Rm46IFN5bmNTdHlsaW5nTWFwc0ZufG51bGwgPSBudWxsO1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0eWxpbmdNYXBzU3luY0ZuKCkge1xuICByZXR1cm4gX2FjdGl2ZVN0eWxpbmdNYXBBcHBseUZuO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0U3R5bGluZ01hcHNTeW5jRm4oZm46IFN5bmNTdHlsaW5nTWFwc0ZuKSB7XG4gIF9hY3RpdmVTdHlsaW5nTWFwQXBwbHlGbiA9IGZuO1xufVxuXG4vKipcbiAqIEFzc2lnbnMgYSBzdHlsZSB2YWx1ZSB0byBhIHN0eWxlIHByb3BlcnR5IGZvciB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAqL1xuY29uc3Qgc2V0U3R5bGU6IEFwcGx5U3R5bGluZ0ZuID1cbiAgICAocmVuZGVyZXI6IFJlbmRlcmVyMyB8IG51bGwsIG5hdGl2ZTogYW55LCBwcm9wOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcgfCBudWxsKSA9PiB7XG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgLy8gb3BhY2l0eSwgei1pbmRleCBhbmQgZmxleGJveCBhbGwgaGF2ZSBudW1iZXIgdmFsdWVzXG4gICAgICAgIC8vIGFuZCB0aGVzZSBuZWVkIHRvIGJlIGNvbnZlcnRlZCBpbnRvIHN0cmluZ3Mgc28gdGhhdFxuICAgICAgICAvLyB0aGV5IGNhbiBiZSBhc3NpZ25lZCBwcm9wZXJseS5cbiAgICAgICAgdmFsdWUgPSB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgICBuZ0Rldk1vZGUgJiYgbmdEZXZNb2RlLnJlbmRlcmVyU2V0U3R5bGUrKztcbiAgICAgICAgcmVuZGVyZXIgJiYgaXNQcm9jZWR1cmFsUmVuZGVyZXIocmVuZGVyZXIpID9cbiAgICAgICAgICAgIHJlbmRlcmVyLnNldFN0eWxlKG5hdGl2ZSwgcHJvcCwgdmFsdWUsIFJlbmRlcmVyU3R5bGVGbGFnczMuRGFzaENhc2UpIDpcbiAgICAgICAgICAgIG5hdGl2ZS5zdHlsZS5zZXRQcm9wZXJ0eShwcm9wLCB2YWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZ0Rldk1vZGUgJiYgbmdEZXZNb2RlLnJlbmRlcmVyUmVtb3ZlU3R5bGUrKztcbiAgICAgICAgcmVuZGVyZXIgJiYgaXNQcm9jZWR1cmFsUmVuZGVyZXIocmVuZGVyZXIpID9cbiAgICAgICAgICAgIHJlbmRlcmVyLnJlbW92ZVN0eWxlKG5hdGl2ZSwgcHJvcCwgUmVuZGVyZXJTdHlsZUZsYWdzMy5EYXNoQ2FzZSkgOlxuICAgICAgICAgICAgbmF0aXZlLnN0eWxlLnJlbW92ZVByb3BlcnR5KHByb3ApO1xuICAgICAgfVxuICAgIH07XG5cbi8qKlxuICogQWRkcy9yZW1vdmVzIHRoZSBwcm92aWRlZCBjbGFzc05hbWUgdmFsdWUgdG8gdGhlIHByb3ZpZGVkIGVsZW1lbnQuXG4gKi9cbmNvbnN0IHNldENsYXNzOiBBcHBseVN0eWxpbmdGbiA9XG4gICAgKHJlbmRlcmVyOiBSZW5kZXJlcjMgfCBudWxsLCBuYXRpdmU6IGFueSwgY2xhc3NOYW1lOiBzdHJpbmcsIHZhbHVlOiBhbnkpID0+IHtcbiAgICAgIGlmIChjbGFzc05hbWUgIT09ICcnKSB7XG4gICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgIG5nRGV2TW9kZSAmJiBuZ0Rldk1vZGUucmVuZGVyZXJBZGRDbGFzcysrO1xuICAgICAgICAgIHJlbmRlcmVyICYmIGlzUHJvY2VkdXJhbFJlbmRlcmVyKHJlbmRlcmVyKSA/IHJlbmRlcmVyLmFkZENsYXNzKG5hdGl2ZSwgY2xhc3NOYW1lKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF0aXZlLmNsYXNzTGlzdC5hZGQoY2xhc3NOYW1lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZ0Rldk1vZGUgJiYgbmdEZXZNb2RlLnJlbmRlcmVyUmVtb3ZlQ2xhc3MrKztcbiAgICAgICAgICByZW5kZXJlciAmJiBpc1Byb2NlZHVyYWxSZW5kZXJlcihyZW5kZXJlcikgPyByZW5kZXJlci5yZW1vdmVDbGFzcyhuYXRpdmUsIGNsYXNzTmFtZSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdGl2ZS5jbGFzc0xpc3QucmVtb3ZlKGNsYXNzTmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuIl19
|