@sapui5/sap.fe.base 1.132.0 → 1.133.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.
@@ -2,7 +2,7 @@ import ObjectPath from "sap/base/util/ObjectPath";
2
2
  import deepClone from "sap/base/util/deepClone";
3
3
  import merge from "sap/base/util/merge";
4
4
  import uid from "sap/base/util/uid";
5
- import { hookable } from "sap/fe/base/HookSupport";
5
+ import { hookable, propagateHookFromMixin } from "sap/fe/base/HookSupport";
6
6
  import type { Ref } from "sap/fe/base/jsx-runtime/jsx";
7
7
  import type UI5Event from "sap/ui/base/Event";
8
8
  import type ManagedObject from "sap/ui/base/ManagedObject";
@@ -34,7 +34,7 @@ type UI5PropertyMetadata = {
34
34
  defaultValue?: unknown;
35
35
  byValue?: boolean;
36
36
  isBindingInfo?: boolean;
37
- bindToState?: string;
37
+ bindToState?: boolean;
38
38
  expectedAnnotations?: string[];
39
39
  expectedTypes?: string[];
40
40
  allowedValues?: string[];
@@ -529,20 +529,14 @@ export function mixin<T extends IInterfaceWithMixin>(interfaceClass: Constructor
529
529
  throw new Error("The mixinInterface decorator must be placed after `defineUi5Class`");
530
530
  }
531
531
  const metadata = ensureMetadata(baseCtor.prototype);
532
- const interfaceName = interfaceClass.prototype.getInterfaceName?.();
533
- if (interfaceName) {
534
- metadata.interfaces.push(interfaceName);
532
+
533
+ let interfaceProtoTypeToMix = interfaceClass.prototype;
534
+ while (interfaceProtoTypeToMix) {
535
+ baseCtor = _addInterfaceProtoTypesToBaseClass(baseCtor, metadata, interfaceProtoTypeToMix);
536
+ interfaceProtoTypeToMix = Object.getPrototypeOf(interfaceProtoTypeToMix);
535
537
  }
538
+ propagateHookFromMixin(baseCtor, interfaceClass);
536
539
 
537
- Object.getOwnPropertyNames(interfaceClass.prototype).forEach((name) => {
538
- if (name !== "constructor" && name !== "setupMixin") {
539
- Object.defineProperty(
540
- baseCtor.prototype,
541
- name,
542
- Object.getOwnPropertyDescriptor(interfaceClass.prototype, name) || Object.create(null)
543
- );
544
- }
545
- });
546
540
  // Hook to add potentially more logic to the mixin
547
541
  interfaceClass.prototype.setupMixin?.(baseCtor);
548
542
  return baseCtor;
@@ -594,6 +588,34 @@ export function defineReference(): PropertyDecorator {
594
588
  } as unknown as PropertyDecorator; // This is technically an accessor decorator, but somehow the compiler doesn't like it if i declare it as such.;
595
589
  }
596
590
 
591
+ function _addInterfaceProtoTypesToBaseClass(
592
+ baseCtor: UI5ControlAndMore,
593
+ baseClassMetadata: UI5ControlMetadataDefinition,
594
+ interfaceClassPrototype: Function["prototype"]
595
+ ): UI5ControlAndMore {
596
+ const interfaceName = interfaceClassPrototype?.getInterfaceName?.();
597
+ if (interfaceName) {
598
+ baseClassMetadata.interfaces.push(interfaceName);
599
+ }
600
+
601
+ Object.getOwnPropertyNames(interfaceClassPrototype).forEach((name) => {
602
+ if (name !== "constructor" && name !== "setupMixin" && name !== "metadata") {
603
+ if (!baseCtor.prototype[name]) {
604
+ // The base class "wins" over the mixin
605
+ Object.defineProperty(
606
+ baseCtor.prototype,
607
+ name,
608
+ Object.getOwnPropertyDescriptor(interfaceClassPrototype, name) || Object.create(null)
609
+ );
610
+ }
611
+ }
612
+ if (name === "metadata") {
613
+ baseCtor.prototype.metadata = merge(baseCtor.prototype.metadata, interfaceClassPrototype.metadata);
614
+ }
615
+ });
616
+ return baseCtor;
617
+ }
618
+
597
619
  function _getHandlerForStateProperty(jsonModel: JSONModel, prop: string): unknown {
598
620
  const pathInModel = `/${prop.toString()}`;
599
621
  const oObj = deepClone(jsonModel.getObject(pathInModel));
@@ -635,10 +657,68 @@ function _getHandlerForStateProperty(jsonModel: JSONModel, prop: string): unknow
635
657
  }
636
658
  return oTarget;
637
659
  }
660
+ const boundProperties = Symbol("boundProperties");
661
+
662
+ function createStateProxy(
663
+ targetControl: Control & {
664
+ [boundProperties]: string[];
665
+ __stateCreated: boolean;
666
+ _updateState: Function;
667
+ _updateStateDebounced: Function;
668
+ _ignoreStatePropertyUpdate: boolean;
669
+ _updateStateTimer: unknown;
670
+ _changedProps?: string[];
671
+ },
672
+ statePropertyName: string,
673
+ boundToStateProps: string[],
674
+ initialData?: object
675
+ ): JSONModel {
676
+ // Lazy initialization of the state property
677
+ targetControl.setModel(new JSONModel(initialData), "$componentState");
678
+ const stateModel = targetControl.getModel("$componentState") as JSONModel;
679
+ stateModel.attachPropertyChange((evt: Model$PropertyChangeEvent) => {
680
+ const path = evt.getParameter("path")?.substring(1); // to remove the first /
681
+ if (path && boundToStateProps.includes(path)) {
682
+ targetControl.setProperty(path, evt.getParameter("value"));
683
+ }
684
+ });
685
+ targetControl.__stateCreated = true;
686
+ const proxy = new Proxy(stateModel, {
687
+ get: (target: JSONModel, prop: string): unknown => {
688
+ return _getHandlerForStateProperty(target, prop);
689
+ },
690
+ set: (setStateModel: JSONModel, prop, value): boolean => {
691
+ // we need to check whether the property is a known bound property in any of the related classes
692
+ const knownBoundProperties = targetControl[boundProperties];
693
+ if (knownBoundProperties.includes(prop.toString())) {
694
+ targetControl._ignoreStatePropertyUpdate = true;
695
+ targetControl.setProperty(prop.toString(), value);
696
+ targetControl._ignoreStatePropertyUpdate = false;
697
+ }
698
+ const setResult = setStateModel.setProperty(`/${prop.toString()}`, value);
699
+ targetControl._updateStateDebounced(prop.toString());
700
+ return setResult;
701
+ }
702
+ });
703
+ Object.defineProperty(targetControl, statePropertyName, {
704
+ configurable: true,
705
+ get: () => {
706
+ return proxy;
707
+ },
708
+ set(value) {
709
+ // Replacing the complete state
710
+ stateModel.setProperty(`/`, value);
711
+ }
712
+ });
713
+ return proxy;
714
+ }
638
715
 
639
716
  function _createStateProperty(
640
717
  obj: UI5ControlDefinition,
641
718
  targetControl: Control & {
719
+ [boundProperties]: string[];
720
+ __stateCreated: boolean;
721
+ __stateName: string;
642
722
  _updateState: Function;
643
723
  _updateStateDebounced: Function;
644
724
  _ignoreStatePropertyUpdate: boolean;
@@ -646,12 +726,7 @@ function _createStateProperty(
646
726
  _changedProps?: string[];
647
727
  }
648
728
  ): void {
649
- if (obj.metadata?.stateProperty || (targetControl?.getModel && targetControl.getModel("$componentState"))) {
650
- if (obj.metadata?.stateProperty) {
651
- targetControl.setModel(new JSONModel(), "$componentState");
652
- }
653
- const stateModel = targetControl.getModel("$componentState") as JSONModel;
654
-
729
+ if (obj.metadata?.stateProperty || targetControl[boundProperties]) {
655
730
  let updatingState = false;
656
731
  const boundToStateProps: string[] = [];
657
732
  for (const propertyName in obj.metadata?.properties) {
@@ -661,15 +736,9 @@ function _createStateProperty(
661
736
  }
662
737
  }
663
738
  // as we may have bound properties in parent classes and subclasses, we keep track of those in the model itself
664
- const initialBoundProperties = stateModel.getProperty("/__boundProperties") ?? [];
665
- stateModel.setProperty("/__boundProperties", [...initialBoundProperties, ...boundToStateProps]);
739
+ targetControl[boundProperties] ??= [];
740
+ targetControl[boundProperties] = [...targetControl[boundProperties], ...boundToStateProps];
666
741
 
667
- stateModel.attachPropertyChange((evt: Model$PropertyChangeEvent) => {
668
- const path = evt.getParameter("path")?.substring(1); // to remove the first /
669
- if (path && boundToStateProps.includes(path)) {
670
- targetControl.setProperty(path, evt.getParameter("value"));
671
- }
672
- });
673
742
  if (obj.metadata?.stateProperty) {
674
743
  // This method can be used to force the state to be applied and wait for it to be applied in tests
675
744
  targetControl._updateState = async function (): Promise<void> {
@@ -692,33 +761,16 @@ function _createStateProperty(
692
761
  }, 200);
693
762
  }
694
763
  };
695
- Object.defineProperty(targetControl, obj.metadata.stateProperty, {
764
+ const statePropertyName = obj.metadata.stateProperty;
765
+ targetControl.__stateCreated = false;
766
+ targetControl.__stateName = statePropertyName;
767
+ Object.defineProperty(targetControl, statePropertyName, {
696
768
  configurable: true,
697
769
  get: () => {
698
- return new Proxy(stateModel, {
699
- get: (target: JSONModel, prop: string): unknown => {
700
- return _getHandlerForStateProperty(target, prop);
701
- },
702
- set: (setStateModel: JSONModel, prop, value): boolean => {
703
- // we need to check whether the property is a known bound property in any of the related classes
704
- const knownBoundProperties = setStateModel.getProperty("/__boundProperties") ?? [];
705
- if (knownBoundProperties.includes(prop.toString())) {
706
- targetControl._ignoreStatePropertyUpdate = true;
707
- targetControl.setProperty(prop.toString(), value);
708
- targetControl._ignoreStatePropertyUpdate = false;
709
- }
710
- const setResult = setStateModel.setProperty(`/${prop.toString()}`, value);
711
- targetControl._updateStateDebounced(prop.toString());
712
- return setResult;
713
- }
714
- });
770
+ return createStateProxy(targetControl, statePropertyName, targetControl[boundProperties]);
715
771
  },
716
- set: function (value) {
717
- const knownBoundProperties = stateModel.getProperty("/__boundProperties") ?? [];
718
- // Replacing the complete state
719
- stateModel.setProperty(`/`, value);
720
- // restoring the boundProperties references
721
- stateModel.setProperty("/__boundProperties", knownBoundProperties);
772
+ set: (value) => {
773
+ createStateProxy(targetControl, statePropertyName, targetControl[boundProperties], value);
722
774
  }
723
775
  });
724
776
  if (obj.metadata.statePropertyDefaultValue) {
@@ -731,11 +783,13 @@ function _createStateProperty(
731
783
  };
732
784
  }
733
785
  const fnSetProperty = targetControl.setProperty;
734
-
735
- if (boundToStateProps.length > 0) {
786
+ if (targetControl[boundProperties].length > 0) {
736
787
  targetControl.setProperty = function (sPropertyName: string, oValue: unknown, bSuppressInvalidate): typeof targetControl {
737
- if (boundToStateProps.includes(sPropertyName) && !this._ignoreStatePropertyUpdate) {
738
- stateModel.setProperty(`/${sPropertyName}`, oValue);
788
+ if (targetControl[boundProperties].includes(sPropertyName) && !this._ignoreStatePropertyUpdate) {
789
+ if (!this.__stateCreated) {
790
+ createStateProxy(targetControl, targetControl.__stateName, targetControl[boundProperties]);
791
+ }
792
+ (this.getModel("$componentState") as JSONModel).setProperty(`/${sPropertyName}`, oValue);
739
793
  targetControl._updateStateDebounced(sPropertyName);
740
794
  }
741
795
  return fnSetProperty.call(this, sPropertyName, oValue, bSuppressInvalidate);
@@ -2,14 +2,16 @@
2
2
  * SAP UI development toolkit for HTML5 (SAPUI5)
3
3
  * (c) Copyright 2009-2024 SAP SE. All rights reserved
4
4
  */
5
- sap.ui.define([], function () {
5
+ sap.ui.define(["sap/base/util/deepClone"], function (deepClone) {
6
6
  "use strict";
7
7
 
8
8
  var _exports = {};
9
9
  /**
10
10
  * This type is to be extended with all controller extensions and methods that are hookable.
11
11
  */
12
+
12
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+
13
15
  // Use two arrays as we cannot index a map through an arbitrary object instance
14
16
  const registeredInstances = [];
15
17
  const registeredHandlers = [];
@@ -87,6 +89,7 @@ sap.ui.define([], function () {
87
89
  function isAlreadyRegistered(existingRegistrations, newRegistration) {
88
90
  return !!existingRegistrations.find(r => r.name === newRegistration.name && r.method === newRegistration.method && r.targetMethod === newRegistration.targetMethod);
89
91
  }
92
+ const hooks = Symbol("hooks");
90
93
 
91
94
  /**
92
95
  * Registers a method as controller extension hook handler.
@@ -96,6 +99,7 @@ sap.ui.define([], function () {
96
99
  * @param method Method to hook into
97
100
  * @returns A method decorator
98
101
  */
102
+ _exports.hooks = hooks;
99
103
  function controllerExtensionHandler(name, method) {
100
104
  return function (target, propertyKey) {
101
105
  const newRegistration = {
@@ -104,7 +108,12 @@ sap.ui.define([], function () {
104
108
  targetMethod: propertyKey
105
109
  };
106
110
  const index = registeredInstances.indexOf(target.constructor);
107
-
111
+ if (!target.constructor[hooks]) {
112
+ Object.defineProperty(target.constructor, hooks, {
113
+ value: []
114
+ });
115
+ }
116
+ target.constructor[hooks]?.push(newRegistration);
108
117
  // We need to check if this exact handler is already registered as handlers are registered statically (on the constructor)
109
118
  if (index !== -1 && !isAlreadyRegistered(registeredHandlers[index], newRegistration)) {
110
119
  registeredHandlers[index].push(newRegistration);
@@ -123,20 +132,42 @@ sap.ui.define([], function () {
123
132
  */
124
133
  _exports.controllerExtensionHandler = controllerExtensionHandler;
125
134
  function initControllerExtensionHookHandlers(target, controller) {
126
- const index = registeredInstances.indexOf(target.constructor);
127
- if (index !== -1) {
128
- const indexableController = controller;
135
+ if (target.constructor[hooks]) {
136
+ let registeredHooks = target.constructor[hooks];
137
+ target[hooks] = deepClone(registeredHooks);
138
+ registeredHooks = target[hooks];
129
139
  const indexableTarget = target;
130
- for (const registeredHandler of registeredHandlers[index]) {
131
- const handlerFunction = indexableTarget[registeredHandler.targetMethod].bind(target);
132
- indexableController[registeredHandler.name][`attach${String(registeredHandler.method)}`](handlerFunction);
140
+ const indexableController = controller;
141
+ for (const registeredHook of registeredHooks) {
142
+ registeredHook.handlerFunction = indexableTarget[registeredHook.targetMethod].bind(target);
143
+ indexableController[registeredHook.name][`attach${String(registeredHook.method)}`](registeredHook.handlerFunction);
133
144
  controller.getView()?.attachBeforeExit(() => {
134
- indexableController[registeredHandler.name][`detach${String(registeredHandler.method)}`](handlerFunction);
145
+ indexableController[registeredHook.name][`detach${String(registeredHook.method)}`](registeredHook.handlerFunction);
135
146
  });
136
147
  }
137
148
  }
138
149
  }
139
150
  _exports.initControllerExtensionHookHandlers = initControllerExtensionHookHandlers;
151
+ function removeControllerExtensionHookHandlers(target, controller) {
152
+ if (target[hooks]) {
153
+ const registeredHooks = target[hooks];
154
+ const indexableController = controller;
155
+ for (const registeredHook of registeredHooks) {
156
+ indexableController[registeredHook.name]?.[`detach${String(registeredHook.method)}`]?.(registeredHook.handlerFunction);
157
+ }
158
+ }
159
+ }
160
+ _exports.removeControllerExtensionHookHandlers = removeControllerExtensionHookHandlers;
161
+ function propagateHookFromMixin(target, source) {
162
+ if (source[hooks]) {
163
+ if (target[hooks]) {
164
+ target[hooks].splice(0, 0, ...source[hooks]);
165
+ } else {
166
+ Object.defineProperty(target, hooks, Object.getOwnPropertyDescriptor(source, hooks) || Object.create([]));
167
+ }
168
+ }
169
+ }
170
+ _exports.propagateHookFromMixin = propagateHookFromMixin;
140
171
  function xmlViewPreprocessor(source, _caller, _settings) {
141
172
  const sourceView = source;
142
173
  const controller = sourceView.getController();
@@ -150,4 +181,4 @@ sap.ui.define([], function () {
150
181
  _exports.xmlViewPreprocessor = xmlViewPreprocessor;
151
182
  return _exports;
152
183
  }, false);
153
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJyZWdpc3RlcmVkSW5zdGFuY2VzIiwicmVnaXN0ZXJlZEhhbmRsZXJzIiwiaG9va2FibGUiLCJleGVjdXRpb24iLCJ0YXJnZXQiLCJwcm9wZXJ0eUtleSIsImRlc2NyaXB0b3IiLCJpbmRleGFibGVUYXJnZXQiLCJ0b1N0cmluZyIsImZuIiwiY0V4VEluc3RhbmNlSG9va01hcCIsImhvb2tlZEhhbmRsZXJzIiwicHVzaCIsImhhbmRsZXJzIiwiaW5kZXgiLCJpbmRleE9mIiwic3BsaWNlIiwib2xkVmFsdWUiLCJ2YWx1ZSIsInJldHVyblZhbHVlIiwiYmluZCIsImFyZ3VtZW50cyIsImhhbmRsZXIiLCJfZXhwb3J0cyIsImlzQWxyZWFkeVJlZ2lzdGVyZWQiLCJleGlzdGluZ1JlZ2lzdHJhdGlvbnMiLCJuZXdSZWdpc3RyYXRpb24iLCJmaW5kIiwiciIsIm5hbWUiLCJtZXRob2QiLCJ0YXJnZXRNZXRob2QiLCJjb250cm9sbGVyRXh0ZW5zaW9uSGFuZGxlciIsIlN0cmluZyIsImNvbnN0cnVjdG9yIiwiaW5pdENvbnRyb2xsZXJFeHRlbnNpb25Ib29rSGFuZGxlcnMiLCJjb250cm9sbGVyIiwiaW5kZXhhYmxlQ29udHJvbGxlciIsInJlZ2lzdGVyZWRIYW5kbGVyIiwiaGFuZGxlckZ1bmN0aW9uIiwiZ2V0VmlldyIsImF0dGFjaEJlZm9yZUV4aXQiLCJ4bWxWaWV3UHJlcHJvY2Vzc29yIiwic291cmNlIiwiX2NhbGxlciIsIl9zZXR0aW5ncyIsInNvdXJjZVZpZXciLCJnZXRDb250cm9sbGVyIiwibWFjcm9BUElDaGlsZCIsImZpbmRBZ2dyZWdhdGVkT2JqZWN0cyIsInMiLCJpc0EiLCJtYW5hZ2VkT2JqZWN0Il0sInNvdXJjZVJvb3QiOiIuIiwic291cmNlcyI6WyJIb29rU3VwcG9ydC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IEV4dGVuc2lvbk92ZXJyaWRlRXhlY3V0aW9uIH0gZnJvbSBcInNhcC9mZS9iYXNlL0NsYXNzU3VwcG9ydFwiO1xuaW1wb3J0IHR5cGUgQ29udHJvbGxlciBmcm9tIFwic2FwL3VpL2NvcmUvbXZjL0NvbnRyb2xsZXJcIjtcbmltcG9ydCB0eXBlIFhNTFZpZXcgZnJvbSBcInNhcC91aS9jb3JlL212Yy9YTUxWaWV3XCI7XG5cbi8qKlxuICogVGhpcyB0eXBlIGlzIHRvIGJlIGV4dGVuZGVkIHdpdGggYWxsIGNvbnRyb2xsZXIgZXh0ZW5zaW9ucyBhbmQgbWV0aG9kcyB0aGF0IGFyZSBob29rYWJsZS5cbiAqL1xudHlwZSBIb29rYWJsZUNvbnRyb2xsZXJFeHRlbnNpb25zID0ge1xuXHRlZGl0Rmxvdzoge1xuXHRcdG9uQWZ0ZXJTYXZlOiB0cnVlO1xuXHRcdG9uQmVmb3JlU2F2ZTogdHJ1ZTtcblx0fTtcblx0Y29sbGFib3JhdGlvbk1hbmFnZXI6IHtcblx0XHRjb2xsZWN0QXZhaWxhYmxlQ2FyZHM6IHRydWU7XG5cdH07XG5cdHBhZ2luYXRvcjoge1xuXHRcdGluaXRpYWxpemU6IHRydWU7XG5cdH07XG5cdHJvdXRpbmc6IHtcblx0XHRvbkFmdGVyQmluZGluZzogdHJ1ZTtcblx0fTtcbn07XG5cbnR5cGUgSGFuZGxlckNvbmZpZ3VyYXRpb248Q0V4dE5hbWUgZXh0ZW5kcyBrZXlvZiBIb29rYWJsZUNvbnRyb2xsZXJFeHRlbnNpb25zPiA9IHtcblx0bmFtZTogQ0V4dE5hbWU7XG5cdG1ldGhvZDoga2V5b2YgSG9va2FibGVDb250cm9sbGVyRXh0ZW5zaW9uc1tDRXh0TmFtZV07XG59O1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbnR5cGUgSGFuZGxlclJlZ2lzdHJhdGlvbiA9IEhhbmRsZXJDb25maWd1cmF0aW9uPGFueT4gJiB7IHRhcmdldE1ldGhvZDogc3RyaW5nIH07XG5cbnR5cGUgRnVuY3Rpb25NYXAgPSB7XG5cdFtrZXk6IHN0cmluZ106IEZ1bmN0aW9uO1xufTtcbnR5cGUgRGVlcEZ1bmN0aW9uTWFwID0ge1xuXHRba2V5OiBzdHJpbmddOiBGdW5jdGlvbk1hcDtcbn07XG50eXBlIEhvb2tNYXAgPSB7XG5cdGhvb2tlZEhhbmRsZXJzOiB7XG5cdFx0W2tleTogc3RyaW5nXTogRnVuY3Rpb25bXTtcblx0fTtcbn07XG5cbi8vIFVzZSB0d28gYXJyYXlzIGFzIHdlIGNhbm5vdCBpbmRleCBhIG1hcCB0aHJvdWdoIGFuIGFyYml0cmFyeSBvYmplY3QgaW5zdGFuY2VcbmNvbnN0IHJlZ2lzdGVyZWRJbnN0YW5jZXM6IEZ1bmN0aW9uW10gPSBbXTtcbmNvbnN0IHJlZ2lzdGVyZWRIYW5kbGVyczogSGFuZGxlclJlZ2lzdHJhdGlvbltdW10gPSBbXTtcblxuLyoqXG4gKiBNYXJrcyBhIGNvbnRyb2xsZXIgZXh0ZW5zaW9uIG1ldGhvZCB0byBiZSBob29rYWJsZSBieSBnZW5lcmF0aW5nIGFkZGl0aW9uYWwgbWV0aG9kcyB0aGF0IGNhbiBiZSB1c2VkIHRvIGF0dGFjaCBhbmQgZGV0YWNoIGhhbmRsZXJzIGF0IHJ1bnRpbWUuXG4gKiBAcGFyYW0gZXhlY3V0aW9uXG4gKiBAcmV0dXJucyBBIG1ldGhvZCBkZWNvcmF0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhvb2thYmxlKGV4ZWN1dGlvbjogRXh0ZW5zaW9uT3ZlcnJpZGVFeGVjdXRpb24pOiBNZXRob2REZWNvcmF0b3Ige1xuXHRyZXR1cm4gZnVuY3Rpb24gKHRhcmdldDogdW5rbm93biwgcHJvcGVydHlLZXk6IHN0cmluZyB8IHN5bWJvbCwgZGVzY3JpcHRvcjogUHJvcGVydHlEZXNjcmlwdG9yKSB7XG5cdFx0Y29uc3QgaW5kZXhhYmxlVGFyZ2V0ID0gdGFyZ2V0IGFzIEZ1bmN0aW9uTWFwO1xuXG5cdFx0aW5kZXhhYmxlVGFyZ2V0W2BhdHRhY2gke3Byb3BlcnR5S2V5LnRvU3RyaW5nKCl9YF0gPSBmdW5jdGlvbiAoZm46IEZ1bmN0aW9uKTogdm9pZCB7XG5cdFx0XHRjb25zdCBjRXhUSW5zdGFuY2VIb29rTWFwID0gdGhpcyBhcyB1bmtub3duIGFzIEhvb2tNYXA7XG5cdFx0XHRpZiAoIWNFeFRJbnN0YW5jZUhvb2tNYXAuaG9va2VkSGFuZGxlcnMpIHtcblx0XHRcdFx0Y0V4VEluc3RhbmNlSG9va01hcC5ob29rZWRIYW5kbGVycyA9IHt9O1xuXHRcdFx0fVxuXHRcdFx0aWYgKCFjRXhUSW5zdGFuY2VIb29rTWFwLmhvb2tlZEhhbmRsZXJzW3Byb3BlcnR5S2V5LnRvU3RyaW5nKCldKSB7XG5cdFx0XHRcdGNFeFRJbnN0YW5jZUhvb2tNYXAuaG9va2VkSGFuZGxlcnNbcHJvcGVydHlLZXkudG9TdHJpbmcoKV0gPSBbXTtcblx0XHRcdH1cblx0XHRcdGNFeFRJbnN0YW5jZUhvb2tNYXAuaG9va2VkSGFuZGxlcnNbcHJvcGVydHlLZXkudG9TdHJpbmcoKV0ucHVzaChmbik7XG5cdFx0fTtcblx0XHRpbmRleGFibGVUYXJnZXRbYGRldGFjaCR7cHJvcGVydHlLZXkudG9TdHJpbmcoKX1gXSA9IGZ1bmN0aW9uIChmbjogRnVuY3Rpb24pOiB2b2lkIHtcblx0XHRcdGNvbnN0IGNFeFRJbnN0YW5jZUhvb2tNYXAgPSB0aGlzIGFzIHVua25vd24gYXMgSG9va01hcDtcblx0XHRcdGNvbnN0IGhhbmRsZXJzID0gY0V4VEluc3RhbmNlSG9va01hcC5ob29rZWRIYW5kbGVyc1twcm9wZXJ0eUtleS50b1N0cmluZygpXTtcblx0XHRcdGNvbnN0IGluZGV4ID0gaGFuZGxlcnMuaW5kZXhPZihmbik7XG5cdFx0XHRpZiAoaW5kZXggIT09IC0xKSB7XG5cdFx0XHRcdGhhbmRsZXJzLnNwbGljZShpbmRleCwgMSk7XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdGNvbnN0IG9sZFZhbHVlID0gZGVzY3JpcHRvci52YWx1ZTtcblx0XHRpZiAoZXhlY3V0aW9uID09PSBcIkJlZm9yZUFzeW5jXCIgfHwgZXhlY3V0aW9uID09PSBcIkFmdGVyQXN5bmNcIikge1xuXHRcdFx0ZGVzY3JpcHRvci52YWx1ZSA9IGFzeW5jIGZ1bmN0aW9uICguLi5hcmdzOiB1bmtub3duW10pOiBQcm9taXNlPHVua25vd24+IHtcblx0XHRcdFx0Y29uc3QgY0V4VEluc3RhbmNlSG9va01hcCA9IHRoaXMgYXMgdW5rbm93biBhcyBIb29rTWFwO1xuXHRcdFx0XHRjb25zdCBoYW5kbGVycyA9IChjRXhUSW5zdGFuY2VIb29rTWFwPy5ob29rZWRIYW5kbGVycyAmJiBjRXhUSW5zdGFuY2VIb29rTWFwPy5ob29rZWRIYW5kbGVyc1twcm9wZXJ0eUtleS50b1N0cmluZygpXSkgfHwgW107XG5cdFx0XHRcdGxldCByZXR1cm5WYWx1ZTogdW5rbm93bjtcblx0XHRcdFx0aWYgKGV4ZWN1dGlvbiA9PT0gXCJBZnRlckFzeW5jXCIpIHtcblx0XHRcdFx0XHRyZXR1cm5WYWx1ZSA9IGF3YWl0IG9sZFZhbHVlLmJpbmQodGhpcykoLi4uYXJncyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Zm9yIChjb25zdCBoYW5kbGVyIG9mIGhhbmRsZXJzKSB7XG5cdFx0XHRcdFx0YXdhaXQgaGFuZGxlci5iaW5kKHRoaXMpKC4uLmFyZ3MpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChleGVjdXRpb24gPT09IFwiQmVmb3JlQXN5bmNcIikge1xuXHRcdFx0XHRcdHJldHVyblZhbHVlID0gYXdhaXQgb2xkVmFsdWUuYmluZCh0aGlzKSguLi5hcmdzKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gcmV0dXJuVmFsdWU7XG5cdFx0XHR9O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRkZXNjcmlwdG9yLnZhbHVlID0gZnVuY3Rpb24gKC4uLmFyZ3M6IHVua25vd25bXSk6IHVua25vd24ge1xuXHRcdFx0XHRjb25zdCBjRXhUSW5zdGFuY2VIb29rTWFwID0gdGhpcyBhcyB1bmtub3duIGFzIEhvb2tNYXA7XG5cdFx0XHRcdGNvbnN0IGhhbmRsZXJzID0gKGNFeFRJbnN0YW5jZUhvb2tNYXA/Lmhvb2tlZEhhbmRsZXJzICYmIGNFeFRJbnN0YW5jZUhvb2tNYXA/Lmhvb2tlZEhhbmRsZXJzW3Byb3BlcnR5S2V5LnRvU3RyaW5nKCldKSB8fCBbXTtcblx0XHRcdFx0bGV0IHJldHVyblZhbHVlOiB1bmtub3duO1xuXHRcdFx0XHRpZiAoZXhlY3V0aW9uID09PSBcIkFmdGVyXCIpIHtcblx0XHRcdFx0XHRyZXR1cm5WYWx1ZSA9IG9sZFZhbHVlLmJpbmQodGhpcykoLi4uYXJncyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Zm9yIChjb25zdCBoYW5kbGVyIG9mIGhhbmRsZXJzKSB7XG5cdFx0XHRcdFx0aGFuZGxlci5iaW5kKHRoaXMpKC4uLmFyZ3MpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChleGVjdXRpb24gPT09IFwiQmVmb3JlXCIpIHtcblx0XHRcdFx0XHRyZXR1cm5WYWx1ZSA9IG9sZFZhbHVlLmJpbmQodGhpcykoLi4uYXJncyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHJldHVyblZhbHVlO1xuXHRcdFx0fTtcblx0XHR9XG5cdH07XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBuZXdSZWdpc3RyYXRpb24gaXMgYWxyZWFkeSBpbmNsdWRlZCBpbiBzb21lIGV4aXN0aW5nUmVnaXN0cmF0aW9ucyBieSBjb21wYXJpbmcgYWxsIHJlbGV2YW50IGF0dHJpYnV0ZXMuXG4gKiBAcGFyYW0gZXhpc3RpbmdSZWdpc3RyYXRpb25zXG4gKiBAcGFyYW0gbmV3UmVnaXN0cmF0aW9uXG4gKiBAcmV0dXJucyBSZXN1bHQgb2YgdGhlIGNoZWNrXG4gKi9cbmZ1bmN0aW9uIGlzQWxyZWFkeVJlZ2lzdGVyZWQoZXhpc3RpbmdSZWdpc3RyYXRpb25zOiBIYW5kbGVyUmVnaXN0cmF0aW9uW10sIG5ld1JlZ2lzdHJhdGlvbjogSGFuZGxlclJlZ2lzdHJhdGlvbik6IGJvb2xlYW4ge1xuXHRyZXR1cm4gISFleGlzdGluZ1JlZ2lzdHJhdGlvbnMuZmluZChcblx0XHQocikgPT4gci5uYW1lID09PSBuZXdSZWdpc3RyYXRpb24ubmFtZSAmJiByLm1ldGhvZCA9PT0gbmV3UmVnaXN0cmF0aW9uLm1ldGhvZCAmJiByLnRhcmdldE1ldGhvZCA9PT0gbmV3UmVnaXN0cmF0aW9uLnRhcmdldE1ldGhvZFxuXHQpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhIG1ldGhvZCBhcyBjb250cm9sbGVyIGV4dGVuc2lvbiBob29rIGhhbmRsZXIuXG4gKlxuICogQ3VycmVudGx5LCBvbmx5IG1ldGhvZHMgb2YgcnVudGltZSBidWlsZGluZyBibG9ja3MgYXJlIHN1cHBvcnRlZC5cbiAqIEBwYXJhbSBuYW1lIENvbnRyb2xsZXIgZXh0ZW5zaW9uIHRvIGhvb2sgaW50b1xuICogQHBhcmFtIG1ldGhvZCBNZXRob2QgdG8gaG9vayBpbnRvXG4gKiBAcmV0dXJucyBBIG1ldGhvZCBkZWNvcmF0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbnRyb2xsZXJFeHRlbnNpb25IYW5kbGVyPENFeHROYW1lIGV4dGVuZHMga2V5b2YgSG9va2FibGVDb250cm9sbGVyRXh0ZW5zaW9ucz4oXG5cdG5hbWU6IENFeHROYW1lLFxuXHRtZXRob2Q6IGtleW9mIEhvb2thYmxlQ29udHJvbGxlckV4dGVuc2lvbnNbQ0V4dE5hbWVdXG4pOiBNZXRob2REZWNvcmF0b3Ige1xuXHRyZXR1cm4gZnVuY3Rpb24gKHRhcmdldDogeyBjb25zdHJ1Y3RvcjogRnVuY3Rpb24gfSwgcHJvcGVydHlLZXk6IHN0cmluZykge1xuXHRcdGNvbnN0IG5ld1JlZ2lzdHJhdGlvbiA9IHsgbmFtZSwgbWV0aG9kOiBTdHJpbmcobWV0aG9kKSwgdGFyZ2V0TWV0aG9kOiBwcm9wZXJ0eUtleSB9O1xuXHRcdGNvbnN0IGluZGV4ID0gcmVnaXN0ZXJlZEluc3RhbmNlcy5pbmRleE9mKHRhcmdldC5jb25zdHJ1Y3Rvcik7XG5cblx0XHQvLyBXZSBuZWVkIHRvIGNoZWNrIGlmIHRoaXMgZXhhY3QgaGFuZGxlciBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgYXMgaGFuZGxlcnMgYXJlIHJlZ2lzdGVyZWQgc3RhdGljYWxseSAob24gdGhlIGNvbnN0cnVjdG9yKVxuXHRcdGlmIChpbmRleCAhPT0gLTEgJiYgIWlzQWxyZWFkeVJlZ2lzdGVyZWQocmVnaXN0ZXJlZEhhbmRsZXJzW2luZGV4XSwgbmV3UmVnaXN0cmF0aW9uKSkge1xuXHRcdFx0cmVnaXN0ZXJlZEhhbmRsZXJzW2luZGV4XS5wdXNoKG5ld1JlZ2lzdHJhdGlvbik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlZ2lzdGVyZWRJbnN0YW5jZXMucHVzaCh0YXJnZXQuY29uc3RydWN0b3IpO1xuXHRcdFx0cmVnaXN0ZXJlZEhhbmRsZXJzLnB1c2goW25ld1JlZ2lzdHJhdGlvbl0pO1xuXHRcdH1cblx0fSBhcyBNZXRob2REZWNvcmF0b3I7XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZXMgYWxsIGNvbnRyb2xsZXIgZXh0ZW5zaW9uIGhhbmRsZXJzIHJlZ2lzdGVyZWQgZm9yIGEgZ2l2ZW4gdGFyZ2V0LlxuICogQHBhcmFtIHRhcmdldCBUYXJnZXQgY2xhc3MgdG8gaW5pdGlhbGl6ZSB0aGUgaGFuZGxlcnMgZm9yXG4gKiBAcGFyYW0gdGFyZ2V0LmNvbnN0cnVjdG9yXG4gKiBAcGFyYW0gY29udHJvbGxlciBQYWdlQ29udHJvbGxlciBpbnN0YW5jZSB0byBnZXQgdGhlIGNvbnRyb2xsZXIgZXh0ZW5zaW9ucyBpbnN0YW5jZXMgZnJvbVxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdENvbnRyb2xsZXJFeHRlbnNpb25Ib29rSGFuZGxlcnModGFyZ2V0OiB7IGNvbnN0cnVjdG9yOiBGdW5jdGlvbiB9LCBjb250cm9sbGVyOiBDb250cm9sbGVyKTogdm9pZCB7XG5cdGNvbnN0IGluZGV4ID0gcmVnaXN0ZXJlZEluc3RhbmNlcy5pbmRleE9mKHRhcmdldC5jb25zdHJ1Y3Rvcik7XG5cdGlmIChpbmRleCAhPT0gLTEpIHtcblx0XHRjb25zdCBpbmRleGFibGVDb250cm9sbGVyID0gY29udHJvbGxlciBhcyB1bmtub3duIGFzIERlZXBGdW5jdGlvbk1hcDtcblx0XHRjb25zdCBpbmRleGFibGVUYXJnZXQgPSB0YXJnZXQgYXMgdW5rbm93biBhcyBGdW5jdGlvbk1hcDtcblxuXHRcdGZvciAoY29uc3QgcmVnaXN0ZXJlZEhhbmRsZXIgb2YgcmVnaXN0ZXJlZEhhbmRsZXJzW2luZGV4XSkge1xuXHRcdFx0Y29uc3QgaGFuZGxlckZ1bmN0aW9uID0gaW5kZXhhYmxlVGFyZ2V0W3JlZ2lzdGVyZWRIYW5kbGVyLnRhcmdldE1ldGhvZF0uYmluZCh0YXJnZXQpO1xuXG5cdFx0XHRpbmRleGFibGVDb250cm9sbGVyW3JlZ2lzdGVyZWRIYW5kbGVyLm5hbWVdW2BhdHRhY2gke1N0cmluZyhyZWdpc3RlcmVkSGFuZGxlci5tZXRob2QpfWBdKGhhbmRsZXJGdW5jdGlvbik7XG5cdFx0XHRjb250cm9sbGVyLmdldFZpZXcoKT8uYXR0YWNoQmVmb3JlRXhpdCgoKSA9PiB7XG5cdFx0XHRcdGluZGV4YWJsZUNvbnRyb2xsZXJbcmVnaXN0ZXJlZEhhbmRsZXIubmFtZV1bYGRldGFjaCR7U3RyaW5nKHJlZ2lzdGVyZWRIYW5kbGVyLm1ldGhvZCl9YF0oaGFuZGxlckZ1bmN0aW9uKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZnVuY3Rpb24geG1sVmlld1ByZXByb2Nlc3Nvcihzb3VyY2U6IG9iamVjdCwgX2NhbGxlcj86IHVua25vd24sIF9zZXR0aW5ncz86IG9iamVjdCk6IHZvaWQge1xuXHRjb25zdCBzb3VyY2VWaWV3ID0gc291cmNlIGFzIFhNTFZpZXc7XG5cdGNvbnN0IGNvbnRyb2xsZXIgPSBzb3VyY2VWaWV3LmdldENvbnRyb2xsZXIoKSBhcyBDb250cm9sbGVyIHwgdW5kZWZpbmVkO1xuXHRpZiAoY29udHJvbGxlcikge1xuXHRcdGNvbnN0IG1hY3JvQVBJQ2hpbGQgPSBzb3VyY2VWaWV3LmZpbmRBZ2dyZWdhdGVkT2JqZWN0cyh0cnVlLCAocykgPT4gcy5pc0EoXCJzYXAuZmUubWFjcm9zLk1hY3JvQVBJXCIpKTtcblx0XHRmb3IgKGNvbnN0IG1hbmFnZWRPYmplY3Qgb2YgbWFjcm9BUElDaGlsZCkge1xuXHRcdFx0aW5pdENvbnRyb2xsZXJFeHRlbnNpb25Ib29rSGFuZGxlcnMo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
184
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJyZWdpc3RlcmVkSW5zdGFuY2VzIiwicmVnaXN0ZXJlZEhhbmRsZXJzIiwiaG9va2FibGUiLCJleGVjdXRpb24iLCJ0YXJnZXQiLCJwcm9wZXJ0eUtleSIsImRlc2NyaXB0b3IiLCJpbmRleGFibGVUYXJnZXQiLCJ0b1N0cmluZyIsImZuIiwiY0V4VEluc3RhbmNlSG9va01hcCIsImhvb2tlZEhhbmRsZXJzIiwicHVzaCIsImhhbmRsZXJzIiwiaW5kZXgiLCJpbmRleE9mIiwic3BsaWNlIiwib2xkVmFsdWUiLCJ2YWx1ZSIsInJldHVyblZhbHVlIiwiYmluZCIsImFyZ3VtZW50cyIsImhhbmRsZXIiLCJfZXhwb3J0cyIsImlzQWxyZWFkeVJlZ2lzdGVyZWQiLCJleGlzdGluZ1JlZ2lzdHJhdGlvbnMiLCJuZXdSZWdpc3RyYXRpb24iLCJmaW5kIiwiciIsIm5hbWUiLCJtZXRob2QiLCJ0YXJnZXRNZXRob2QiLCJob29rcyIsIlN5bWJvbCIsImNvbnRyb2xsZXJFeHRlbnNpb25IYW5kbGVyIiwiU3RyaW5nIiwiY29uc3RydWN0b3IiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImluaXRDb250cm9sbGVyRXh0ZW5zaW9uSG9va0hhbmRsZXJzIiwiY29udHJvbGxlciIsInJlZ2lzdGVyZWRIb29rcyIsImRlZXBDbG9uZSIsImluZGV4YWJsZUNvbnRyb2xsZXIiLCJyZWdpc3RlcmVkSG9vayIsImhhbmRsZXJGdW5jdGlvbiIsImdldFZpZXciLCJhdHRhY2hCZWZvcmVFeGl0IiwicmVtb3ZlQ29udHJvbGxlckV4dGVuc2lvbkhvb2tIYW5kbGVycyIsInByb3BhZ2F0ZUhvb2tGcm9tTWl4aW4iLCJzb3VyY2UiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJjcmVhdGUiLCJ4bWxWaWV3UHJlcHJvY2Vzc29yIiwiX2NhbGxlciIsIl9zZXR0aW5ncyIsInNvdXJjZVZpZXciLCJnZXRDb250cm9sbGVyIiwibWFjcm9BUElDaGlsZCIsImZpbmRBZ2dyZWdhdGVkT2JqZWN0cyIsInMiLCJpc0EiLCJtYW5hZ2VkT2JqZWN0Il0sInNvdXJjZVJvb3QiOiIuIiwic291cmNlcyI6WyJIb29rU3VwcG9ydC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZGVlcENsb25lIGZyb20gXCJzYXAvYmFzZS91dGlsL2RlZXBDbG9uZVwiO1xuaW1wb3J0IHR5cGUgeyBFeHRlbnNpb25PdmVycmlkZUV4ZWN1dGlvbiB9IGZyb20gXCJzYXAvZmUvYmFzZS9DbGFzc1N1cHBvcnRcIjtcbmltcG9ydCB0eXBlIENvbnRyb2xsZXIgZnJvbSBcInNhcC91aS9jb3JlL212Yy9Db250cm9sbGVyXCI7XG5pbXBvcnQgdHlwZSBYTUxWaWV3IGZyb20gXCJzYXAvdWkvY29yZS9tdmMvWE1MVmlld1wiO1xuLyoqXG4gKiBUaGlzIHR5cGUgaXMgdG8gYmUgZXh0ZW5kZWQgd2l0aCBhbGwgY29udHJvbGxlciBleHRlbnNpb25zIGFuZCBtZXRob2RzIHRoYXQgYXJlIGhvb2thYmxlLlxuICovXG50eXBlIEhvb2thYmxlQ29udHJvbGxlckV4dGVuc2lvbnMgPSB7XG5cdGVkaXRGbG93OiB7XG5cdFx0aW5saW5lRWRpdEVuZDogdHJ1ZTtcblx0XHRpbmxpbmVFZGl0U3RhcnQ6IHRydWU7XG5cdFx0b25BZnRlclNhdmU6IHRydWU7XG5cdFx0b25CZWZvcmVTYXZlOiB0cnVlO1xuXHR9O1xuXHRjb2xsYWJvcmF0aW9uTWFuYWdlcjoge1xuXHRcdGNvbGxlY3RBdmFpbGFibGVDYXJkczogdHJ1ZTtcblx0fTtcblx0cGFnaW5hdG9yOiB7XG5cdFx0aW5pdGlhbGl6ZTogdHJ1ZTtcblx0fTtcblx0cm91dGluZzoge1xuXHRcdG9uQWZ0ZXJCaW5kaW5nOiB0cnVlO1xuXHR9O1xufTtcblxudHlwZSBIYW5kbGVyQ29uZmlndXJhdGlvbjxDRXh0TmFtZSBleHRlbmRzIGtleW9mIEhvb2thYmxlQ29udHJvbGxlckV4dGVuc2lvbnM+ID0ge1xuXHRuYW1lOiBDRXh0TmFtZTtcblx0bWV0aG9kOiBrZXlvZiBIb29rYWJsZUNvbnRyb2xsZXJFeHRlbnNpb25zW0NFeHROYW1lXTtcbn07XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxudHlwZSBIYW5kbGVyUmVnaXN0cmF0aW9uID0gSGFuZGxlckNvbmZpZ3VyYXRpb248YW55PiAmIHsgdGFyZ2V0TWV0aG9kOiBzdHJpbmc7IGhhbmRsZXJGdW5jdGlvbj86IEZ1bmN0aW9uIH07XG5cbnR5cGUgRnVuY3Rpb25NYXAgPSB7XG5cdFtrZXk6IHN0cmluZ106IEZ1bmN0aW9uO1xufTtcbnR5cGUgRGVlcEZ1bmN0aW9uTWFwID0ge1xuXHRba2V5OiBzdHJpbmddOiBGdW5jdGlvbk1hcDtcbn07XG50eXBlIEhvb2tNYXAgPSB7XG5cdGhvb2tlZEhhbmRsZXJzOiB7XG5cdFx0W2tleTogc3RyaW5nXTogRnVuY3Rpb25bXTtcblx0fTtcbn07XG5cbi8vIFVzZSB0d28gYXJyYXlzIGFzIHdlIGNhbm5vdCBpbmRleCBhIG1hcCB0aHJvdWdoIGFuIGFyYml0cmFyeSBvYmplY3QgaW5zdGFuY2VcbmNvbnN0IHJlZ2lzdGVyZWRJbnN0YW5jZXM6IEZ1bmN0aW9uW10gPSBbXTtcbmNvbnN0IHJlZ2lzdGVyZWRIYW5kbGVyczogSGFuZGxlclJlZ2lzdHJhdGlvbltdW10gPSBbXTtcblxuLyoqXG4gKiBNYXJrcyBhIGNvbnRyb2xsZXIgZXh0ZW5zaW9uIG1ldGhvZCB0byBiZSBob29rYWJsZSBieSBnZW5lcmF0aW5nIGFkZGl0aW9uYWwgbWV0aG9kcyB0aGF0IGNhbiBiZSB1c2VkIHRvIGF0dGFjaCBhbmQgZGV0YWNoIGhhbmRsZXJzIGF0IHJ1bnRpbWUuXG4gKiBAcGFyYW0gZXhlY3V0aW9uXG4gKiBAcmV0dXJucyBBIG1ldGhvZCBkZWNvcmF0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhvb2thYmxlKGV4ZWN1dGlvbjogRXh0ZW5zaW9uT3ZlcnJpZGVFeGVjdXRpb24pOiBNZXRob2REZWNvcmF0b3Ige1xuXHRyZXR1cm4gZnVuY3Rpb24gKHRhcmdldDogdW5rbm93biwgcHJvcGVydHlLZXk6IHN0cmluZyB8IHN5bWJvbCwgZGVzY3JpcHRvcjogUHJvcGVydHlEZXNjcmlwdG9yKSB7XG5cdFx0Y29uc3QgaW5kZXhhYmxlVGFyZ2V0ID0gdGFyZ2V0IGFzIEZ1bmN0aW9uTWFwO1xuXG5cdFx0aW5kZXhhYmxlVGFyZ2V0W2BhdHRhY2gke3Byb3BlcnR5S2V5LnRvU3RyaW5nKCl9YF0gPSBmdW5jdGlvbiAoZm46IEZ1bmN0aW9uKTogdm9pZCB7XG5cdFx0XHRjb25zdCBjRXhUSW5zdGFuY2VIb29rTWFwID0gdGhpcyBhcyB1bmtub3duIGFzIEhvb2tNYXA7XG5cdFx0XHRpZiAoIWNFeFRJbnN0YW5jZUhvb2tNYXAuaG9va2VkSGFuZGxlcnMpIHtcblx0XHRcdFx0Y0V4VEluc3RhbmNlSG9va01hcC5ob29rZWRIYW5kbGVycyA9IHt9O1xuXHRcdFx0fVxuXHRcdFx0aWYgKCFjRXhUSW5zdGFuY2VIb29rTWFwLmhvb2tlZEhhbmRsZXJzW3Byb3BlcnR5S2V5LnRvU3RyaW5nKCldKSB7XG5cdFx0XHRcdGNFeFRJbnN0YW5jZUhvb2tNYXAuaG9va2VkSGFuZGxlcnNbcHJvcGVydHlLZXkudG9TdHJpbmcoKV0gPSBbXTtcblx0XHRcdH1cblx0XHRcdGNFeFRJbnN0YW5jZUhvb2tNYXAuaG9va2VkSGFuZGxlcnNbcHJvcGVydHlLZXkudG9TdHJpbmcoKV0ucHVzaChmbik7XG5cdFx0fTtcblx0XHRpbmRleGFibGVUYXJnZXRbYGRldGFjaCR7cHJvcGVydHlLZXkudG9TdHJpbmcoKX1gXSA9IGZ1bmN0aW9uIChmbjogRnVuY3Rpb24pOiB2b2lkIHtcblx0XHRcdGNvbnN0IGNFeFRJbnN0YW5jZUhvb2tNYXAgPSB0aGlzIGFzIHVua25vd24gYXMgSG9va01hcDtcblx0XHRcdGNvbnN0IGhhbmRsZXJzID0gY0V4VEluc3RhbmNlSG9va01hcC5ob29rZWRIYW5kbGVyc1twcm9wZXJ0eUtleS50b1N0cmluZygpXTtcblx0XHRcdGNvbnN0IGluZGV4ID0gaGFuZGxlcnMuaW5kZXhPZihmbik7XG5cdFx0XHRpZiAoaW5kZXggIT09IC0xKSB7XG5cdFx0XHRcdGhhbmRsZXJzLnNwbGljZShpbmRleCwgMSk7XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdGNvbnN0IG9sZFZhbHVlID0gZGVzY3JpcHRvci52YWx1ZTtcblx0XHRpZiAoZXhlY3V0aW9uID09PSBcIkJlZm9yZUFzeW5jXCIgfHwgZXhlY3V0aW9uID09PSBcIkFmdGVyQXN5bmNcIikge1xuXHRcdFx0ZGVzY3JpcHRvci52YWx1ZSA9IGFzeW5jIGZ1bmN0aW9uICguLi5hcmdzOiB1bmtub3duW10pOiBQcm9taXNlPHVua25vd24+IHtcblx0XHRcdFx0Y29uc3QgY0V4VEluc3RhbmNlSG9va01hcCA9IHRoaXMgYXMgdW5rbm93biBhcyBIb29rTWFwO1xuXHRcdFx0XHRjb25zdCBoYW5kbGVycyA9IChjRXhUSW5zdGFuY2VIb29rTWFwPy5ob29rZWRIYW5kbGVycyAmJiBjRXhUSW5zdGFuY2VIb29rTWFwPy5ob29rZWRIYW5kbGVyc1twcm9wZXJ0eUtleS50b1N0cmluZygpXSkgfHwgW107XG5cdFx0XHRcdGxldCByZXR1cm5WYWx1ZTogdW5rbm93bjtcblx0XHRcdFx0aWYgKGV4ZWN1dGlvbiA9PT0gXCJBZnRlckFzeW5jXCIpIHtcblx0XHRcdFx0XHRyZXR1cm5WYWx1ZSA9IGF3YWl0IG9sZFZhbHVlLmJpbmQodGhpcykoLi4uYXJncyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Zm9yIChjb25zdCBoYW5kbGVyIG9mIGhhbmRsZXJzKSB7XG5cdFx0XHRcdFx0YXdhaXQgaGFuZGxlci5iaW5kKHRoaXMpKC4uLmFyZ3MpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChleGVjdXRpb24gPT09IFwiQmVmb3JlQXN5bmNcIikge1xuXHRcdFx0XHRcdHJldHVyblZhbHVlID0gYXdhaXQgb2xkVmFsdWUuYmluZCh0aGlzKSguLi5hcmdzKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gcmV0dXJuVmFsdWU7XG5cdFx0XHR9O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRkZXNjcmlwdG9yLnZhbHVlID0gZnVuY3Rpb24gKC4uLmFyZ3M6IHVua25vd25bXSk6IHVua25vd24ge1xuXHRcdFx0XHRjb25zdCBjRXhUSW5zdGFuY2VIb29rTWFwID0gdGhpcyBhcyB1bmtub3duIGFzIEhvb2tNYXA7XG5cdFx0XHRcdGNvbnN0IGhhbmRsZXJzID0gKGNFeFRJbnN0YW5jZUhvb2tNYXA/Lmhvb2tlZEhhbmRsZXJzICYmIGNFeFRJbnN0YW5jZUhvb2tNYXA/Lmhvb2tlZEhhbmRsZXJzW3Byb3BlcnR5S2V5LnRvU3RyaW5nKCldKSB8fCBbXTtcblx0XHRcdFx0bGV0IHJldHVyblZhbHVlOiB1bmtub3duO1xuXHRcdFx0XHRpZiAoZXhlY3V0aW9uID09PSBcIkFmdGVyXCIpIHtcblx0XHRcdFx0XHRyZXR1cm5WYWx1ZSA9IG9sZFZhbHVlLmJpbmQodGhpcykoLi4uYXJncyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Zm9yIChjb25zdCBoYW5kbGVyIG9mIGhhbmRsZXJzKSB7XG5cdFx0XHRcdFx0aGFuZGxlci5iaW5kKHRoaXMpKC4uLmFyZ3MpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChleGVjdXRpb24gPT09IFwiQmVmb3JlXCIpIHtcblx0XHRcdFx0XHRyZXR1cm5WYWx1ZSA9IG9sZFZhbHVlLmJpbmQodGhpcykoLi4uYXJncyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHJldHVyblZhbHVlO1xuXHRcdFx0fTtcblx0XHR9XG5cdH07XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBuZXdSZWdpc3RyYXRpb24gaXMgYWxyZWFkeSBpbmNsdWRlZCBpbiBzb21lIGV4aXN0aW5nUmVnaXN0cmF0aW9ucyBieSBjb21wYXJpbmcgYWxsIHJlbGV2YW50IGF0dHJpYnV0ZXMuXG4gKiBAcGFyYW0gZXhpc3RpbmdSZWdpc3RyYXRpb25zXG4gKiBAcGFyYW0gbmV3UmVnaXN0cmF0aW9uXG4gKiBAcmV0dXJucyBSZXN1bHQgb2YgdGhlIGNoZWNrXG4gKi9cbmZ1bmN0aW9uIGlzQWxyZWFkeVJlZ2lzdGVyZWQoZXhpc3RpbmdSZWdpc3RyYXRpb25zOiBIYW5kbGVyUmVnaXN0cmF0aW9uW10sIG5ld1JlZ2lzdHJhdGlvbjogSGFuZGxlclJlZ2lzdHJhdGlvbik6IGJvb2xlYW4ge1xuXHRyZXR1cm4gISFleGlzdGluZ1JlZ2lzdHJhdGlvbnMuZmluZChcblx0XHQocikgPT4gci5uYW1lID09PSBuZXdSZWdpc3RyYXRpb24ubmFtZSAmJiByLm1ldGhvZCA9PT0gbmV3UmVnaXN0cmF0aW9uLm1ldGhvZCAmJiByLnRhcmdldE1ldGhvZCA9PT0gbmV3UmVnaXN0cmF0aW9uLnRhcmdldE1ldGhvZFxuXHQpO1xufVxuXG5leHBvcnQgY29uc3QgaG9va3MgPSBTeW1ib2woXCJob29rc1wiKTtcblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBtZXRob2QgYXMgY29udHJvbGxlciBleHRlbnNpb24gaG9vayBoYW5kbGVyLlxuICpcbiAqIEN1cnJlbnRseSwgb25seSBtZXRob2RzIG9mIHJ1bnRpbWUgYnVpbGRpbmcgYmxvY2tzIGFyZSBzdXBwb3J0ZWQuXG4gKiBAcGFyYW0gbmFtZSBDb250cm9sbGVyIGV4dGVuc2lvbiB0byBob29rIGludG9cbiAqIEBwYXJhbSBtZXRob2QgTWV0aG9kIHRvIGhvb2sgaW50b1xuICogQHJldHVybnMgQSBtZXRob2QgZGVjb3JhdG9yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb250cm9sbGVyRXh0ZW5zaW9uSGFuZGxlcjxDRXh0TmFtZSBleHRlbmRzIGtleW9mIEhvb2thYmxlQ29udHJvbGxlckV4dGVuc2lvbnM+KFxuXHRuYW1lOiBDRXh0TmFtZSxcblx0bWV0aG9kOiBrZXlvZiBIb29rYWJsZUNvbnRyb2xsZXJFeHRlbnNpb25zW0NFeHROYW1lXVxuKTogTWV0aG9kRGVjb3JhdG9yIHtcblx0cmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQ6IHsgY29uc3RydWN0b3I6IEZ1bmN0aW9uICYgeyBbaG9va3NdPzogSGFuZGxlclJlZ2lzdHJhdGlvbltdIH0gfSwgcHJvcGVydHlLZXk6IHN0cmluZykge1xuXHRcdGNvbnN0IG5ld1JlZ2lzdHJhdGlvbiA9IHsgbmFtZSwgbWV0aG9kOiBTdHJpbmcobWV0aG9kKSwgdGFyZ2V0TWV0aG9kOiBwcm9wZXJ0eUtleSB9O1xuXHRcdGNvbnN0IGluZGV4ID0gcmVnaXN0ZXJlZEluc3RhbmNlcy5pbmRleE9mKHRhcmdldC5jb25zdHJ1Y3Rvcik7XG5cdFx0aWYgKCF0YXJnZXQuY29uc3RydWN0b3JbaG9va3NdKSB7XG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LmNvbnN0cnVjdG9yLCBob29rcywge1xuXHRcdFx0XHR2YWx1ZTogW11cblx0XHRcdH0pO1xuXHRcdH1cblx0XHR0YXJnZXQuY29uc3RydWN0b3JbaG9va3NdPy5wdXNoKG5ld1JlZ2lzdHJhdGlvbik7XG5cdFx0Ly8gV2UgbmVlZCB0byBjaGVjayBpZiB0aGlzIGV4YWN0IGhhbmRsZXIgaXMgYWxyZWFkeSByZWdpc3RlcmVkIGFzIGhhbmRsZXJzIGFyZSByZWdpc3RlcmVkIHN0YXRpY2FsbHkgKG9uIHRoZSBjb25zdHJ1Y3Rvcilcblx0XHRpZiAoaW5kZXggIT09IC0xICYmICFpc0FscmVhZHlSZWdpc3RlcmVkKHJlZ2lzdGVyZWRIYW5kbGVyc1tpbmRleF0sIG5ld1JlZ2lzdHJhdGlvbikpIHtcblx0XHRcdHJlZ2lzdGVyZWRIYW5kbGVyc1tpbmRleF0ucHVzaChuZXdSZWdpc3RyYXRpb24pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZWdpc3RlcmVkSW5zdGFuY2VzLnB1c2godGFyZ2V0LmNvbnN0cnVjdG9yKTtcblx0XHRcdHJlZ2lzdGVyZWRIYW5kbGVycy5wdXNoKFtuZXdSZWdpc3RyYXRpb25dKTtcblx0XHR9XG5cdH0gYXMgTWV0aG9kRGVjb3JhdG9yO1xufVxuXG4vKipcbiAqIEluaXRpYWxpemVzIGFsbCBjb250cm9sbGVyIGV4dGVuc2lvbiBoYW5kbGVycyByZWdpc3RlcmVkIGZvciBhIGdpdmVuIHRhcmdldC5cbiAqIEBwYXJhbSB0YXJnZXQgVGFyZ2V0IGNsYXNzIHRvIGluaXRpYWxpemUgdGhlIGhhbmRsZXJzIGZvclxuICogQHBhcmFtIHRhcmdldC5jb25zdHJ1Y3RvclxuICogQHBhcmFtIGNvbnRyb2xsZXIgUGFnZUNvbnRyb2xsZXIgaW5zdGFuY2UgdG8gZ2V0IHRoZSBjb250cm9sbGVyIGV4dGVuc2lvbnMgaW5zdGFuY2VzIGZyb21cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRDb250cm9sbGVyRXh0ZW5zaW9uSG9va0hhbmRsZXJzKFxuXHR0YXJnZXQ6IHsgY29uc3RydWN0b3I6IEZ1bmN0aW9uICYgeyBbaG9va3NdPzogSGFuZGxlclJlZ2lzdHJhdGlvbltdIH0gfSAmIHsgW2hvb2tzXT86IEhhbmRsZXJSZWdpc3RyYXRpb25bXSB9LFxuXHRjb250cm9sbGVyOiBDb250cm9sbGVyXG4pOiB2b2lkIHtcblx0aWYgKHRhcmdldC5jb25zdHJ1Y3Rvcltob29rc10pIHtcblx0XHRsZXQgcmVnaXN0ZXJlZEhvb2tzID0gdGFyZ2V0LmNvbnN0cnVjdG9yW2hvb2tzXTtcblx0XHR0YXJnZXRbaG9va3NdID0gZGVlcENsb25lKHJlZ2lzdGVyZWRIb29rcyk7XG5cdFx0cmVnaXN0ZXJlZEhvb2tzID0gdGFyZ2V0W2hvb2tzXSE7XG5cdFx0Y29uc3QgaW5kZXhhYmxlVGFyZ2V0ID0gdGFyZ2V0IGFzIHVua25vd24gYXMgRnVuY3Rpb25NYXA7XG5cdFx0Y29uc3QgaW5kZXhhYmxlQ29udHJvbGxlciA9IGNvbnRyb2xsZXIgYXMgdW5rbm93biBhcyBEZWVwRnVuY3Rpb25NYXA7XG5cdFx0Zm9yIChjb25zdCByZWdpc3RlcmVkSG9vayBvZiByZWdpc3RlcmVkSG9va3MpIHtcblx0XHRcdHJlZ2lzdGVyZWRIb29rLmhhbmRsZXJGdW5jdGlvbiA9IGluZGV4YWJsZVRhcmdldFtyZWdpc3RlcmVkSG9vay50YXJnZXRNZXRob2RdLmJpbmQodGFyZ2V0KTtcblx0XHRcdGluZGV4YWJsZUNvbnRyb2xsZXJbcmVnaXN0ZXJlZEhvb2submFtZV1bYGF0dGFjaCR7U3RyaW5nKHJlZ2lzdGVyZWRIb29rLm1ldGhvZCl9YF0ocmVnaXN0ZXJlZEhvb2suaGFuZGxlckZ1bmN0aW9uKTtcblx0XHRcdGNvbnRyb2xsZXIuZ2V0VmlldygpPy5hdHRhY2hCZWZvcmVFeGl0KCgpID0+IHtcblx0XHRcdFx0aW5kZXhhYmxlQ29udHJvbGxlcltyZWdpc3RlcmVkSG9vay5uYW1lXVtgZGV0YWNoJHtTdHJpbmcocmVnaXN0ZXJlZEhvb2subWV0aG9kKX1gXShyZWdpc3RlcmVkSG9vay5oYW5kbGVyRnVuY3Rpb24pO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmVDb250cm9sbGVyRXh0ZW5zaW9uSG9va0hhbmRsZXJzKFxuXHR0YXJnZXQ6IHsgY29uc3RydWN0b3I6IEZ1bmN0aW9uICYgeyBbaG9va3NdPzogSGFuZGxlclJlZ2lzdHJhdGlvbltdIH0gfSAmIHsgW2hvb2tzXT86IEhhbmRsZXJSZWdpc3RyYXRpb25bXSB9LFxuXHRjb250cm9sbGVyOiBDb250cm9sbGVyXG4pOiB2b2lkIHtcblx0aWYgKHRhcmdldFtob29rc10pIHtcblx0XHRjb25zdCByZWdpc3RlcmVkSG9va3MgPSB0YXJnZXRbaG9va3NdO1xuXHRcdGNvbnN0IGluZGV4YWJsZUNvbnRyb2xsZXIgPSBjb250cm9sbGVyIGFzIHVua25vd24gYXMgRGVlcEZ1bmN0aW9uTWFwO1xuXHRcdGZvciAoY29uc3QgcmVnaXN0ZXJlZEhvb2sgb2YgcmVnaXN0ZXJlZEhvb2tzKSB7XG5cdFx0XHRpbmRleGFibGVDb250cm9sbGVyW3JlZ2lzdGVyZWRIb29rLm5hbWVdPy5bYGRldGFjaCR7U3RyaW5nKHJlZ2lzdGVyZWRIb29rLm1ldGhvZCl9YF0/LihyZWdpc3RlcmVkSG9vay5oYW5kbGVyRnVuY3Rpb24pO1xuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJvcGFnYXRlSG9va0Zyb21NaXhpbihcblx0dGFyZ2V0OiBGdW5jdGlvbiAmIHsgW2hvb2tzXT86IEhhbmRsZXJSZWdpc3RyYXRpb25bXSB9LFxuXHRzb3VyY2U6IEZ1bmN0aW9uICYgeyBbaG9va3NdPzogSGFuZGxlclJlZ2lzdHJhdGlvbltdIH1cbik6IHZvaWQge1xuXHRpZiAoc291cmNlW2hvb2tzXSkge1xuXHRcdGlmICh0YXJnZXRbaG9va3NdKSB7XG5cdFx0XHR0YXJnZXRbaG9va3NdIS5zcGxpY2UoMCwgMCwgLi4uc291cmNlW2hvb2tzXSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGhvb2tzLCBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHNvdXJjZSwgaG9va3MpIHx8IE9iamVjdC5jcmVhdGUoW10pKTtcblx0XHR9XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHhtbFZpZXdQcmVwcm9jZXNzb3Ioc291cmNlOiBvYmplY3QsIF9jYWxsZXI/OiB1bmtub3duLCBfc2V0dGluZ3M/OiBvYmplY3QpOiB2b2lkIHtcblx0Y29uc3Qgc291cmNlVmlldyA9IHNvdXJjZSBhcyBYTUxWaWV3O1xuXHRjb25zdCBjb250cm9sbGVyID0gc291cmNlVmlldy5nZXRDb250cm9sbGVyKCkgYXMgQ29udHJvbGxlciB8IHVuZGVmaW5lZDtcblx0aWYgKGNvbnRyb2xsZXIpIHtcblx0XHRjb25zdCBtYWNyb0FQSUNoaWxkID0gc291cmNlVmlldy5maW5kQWdncmVnYXRlZE9iamVjdHModHJ1ZSwgKHMpID0+IHMuaXNBKFwic2FwLmZlLm1hY3Jvcy5NYWNyb0FQSVwiKSk7XG5cdFx0Zm9yIChjb25zdCBtYW5hZ2VkT2JqZWN0IG9mIG1hY3JvQVBJQ2hpbGQpIHtcblx0XHRcdGluaXRDb250cm9sbGVyRXh0ZW5zaW9uSG9va0hhbmRsZXJzKG1hbmFnZWRPYmplY3QsIGNvbnRyb2xsZXIpO1xuXHRcdH1cblx0fVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztFQUlBO0FBQ0E7QUFDQTs7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QUFLLE1BQU1JLGNBQWMsSUFBSUgsZUFBZSxFQUFFO1FBQzdDRSxtQkFBbUIsQ0FBQ0MsY0FBYyxDQUFDZixJQUFJLENBQUMsR0FBRyxTQUFTTSxNQUFNLENBQUNTLGNBQWMsQ0FBQ2QsTUFBTSxDQUFDLEVBQUUsQ0FBQyxHQUFHYyxjQUFjLENBQUNDLGVBQWUsQ0FBQztNQUN2SDtJQUNEO0VBQ0Q7RUFBQ3RCLFFBQUEsQ0FBQXlCLHFDQUFBLEdBQUFBLHFDQUFBO0VBRU0sU0FBU0Msc0JBQXNCQSxDQUNyQzdDLE1BQXNELEVBQ3REOEMsTUFBc0QsRUFDL0M7SUFDUCxJQUFJQSxNQUFNLENBQUNsQixLQUFLLENBQUMsRUFBRTtNQUNsQixJQUFJNUIsTUFBTSxDQUFDNEIsS0FBSyxDQUFDLEVBQUU7UUFDbEI1QixNQUFNLENBQUM0QixLQUFLLENBQUMsQ0FBRWhCLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUdrQyxNQUFNLENBQUNsQixLQUFLLENBQUMsQ0FBQztNQUM5QyxDQUFDLE1BQU07UUFDTkssTUFBTSxDQUFDQyxjQUFjLENBQUNsQyxNQUFNLEVBQUU0QixLQUFLLEVBQUVLLE1BQU0sQ0FBQ2Msd0JBQXdCLENBQUNELE1BQU0sRUFBRWxCLEtBQUssQ0FBQyxJQUFJSyxNQUFNLENBQUNlLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztNQUMxRztJQUNEO0VBQ0Q7RUFBQzdCLFFBQUEsQ0FBQTBCLHNCQUFBLEdBQUFBLHNCQUFBO0VBRU0sU0FBU0ksbUJBQW1CQSxDQUFDSCxNQUFjLEVBQUVJLE9BQWlCLEVBQUVDLFNBQWtCLEVBQVE7SUFDaEcsTUFBTUMsVUFBVSxHQUFHTixNQUFpQjtJQUNwQyxNQUFNVixVQUFVLEdBQUdnQixVQUFVLENBQUNDLGFBQWEsQ0FBQyxDQUEyQjtJQUN2RSxJQUFJakIsVUFBVSxFQUFFO01BQ2YsTUFBTWtCLGFBQWEsR0FBR0YsVUFBVSxDQUFDRyxxQkFBcUIsQ0FBQyxJQUFJLEVBQUdDLENBQUMsSUFBS0EsQ0FBQyxDQUFDQyxHQUFHLENBQUMsd0JBQXdCLENBQUMsQ0FBQztNQUNwRyxLQUFLLE1BQU1DLGFBQWEsSUFBSUosYUFBYSxFQUFFO1FBQzFDbkIsbUNBQW1DLENBQUN1QixhQUFhLEVBQUV0QixVQUFVLENBQUM7TUFDL0Q7SUFDRDtFQUNEO0VBQUNqQixRQUFBLENBQUE4QixtQkFBQSxHQUFBQSxtQkFBQTtFQUFBLE9BQUE5QixRQUFBO0FBQUEiLCJpZ25vcmVMaXN0IjpbXX0=
@@ -1,12 +1,14 @@
1
+ import deepClone from "sap/base/util/deepClone";
1
2
  import type { ExtensionOverrideExecution } from "sap/fe/base/ClassSupport";
2
3
  import type Controller from "sap/ui/core/mvc/Controller";
3
4
  import type XMLView from "sap/ui/core/mvc/XMLView";
4
-
5
5
  /**
6
6
  * This type is to be extended with all controller extensions and methods that are hookable.
7
7
  */
8
8
  type HookableControllerExtensions = {
9
9
  editFlow: {
10
+ inlineEditEnd: true;
11
+ inlineEditStart: true;
10
12
  onAfterSave: true;
11
13
  onBeforeSave: true;
12
14
  };
@@ -26,7 +28,7 @@ type HandlerConfiguration<CExtName extends keyof HookableControllerExtensions> =
26
28
  method: keyof HookableControllerExtensions[CExtName];
27
29
  };
28
30
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
- type HandlerRegistration = HandlerConfiguration<any> & { targetMethod: string };
31
+ type HandlerRegistration = HandlerConfiguration<any> & { targetMethod: string; handlerFunction?: Function };
30
32
 
31
33
  type FunctionMap = {
32
34
  [key: string]: Function;
@@ -121,6 +123,8 @@ function isAlreadyRegistered(existingRegistrations: HandlerRegistration[], newRe
121
123
  );
122
124
  }
123
125
 
126
+ export const hooks = Symbol("hooks");
127
+
124
128
  /**
125
129
  * Registers a method as controller extension hook handler.
126
130
  *
@@ -133,10 +137,15 @@ export function controllerExtensionHandler<CExtName extends keyof HookableContro
133
137
  name: CExtName,
134
138
  method: keyof HookableControllerExtensions[CExtName]
135
139
  ): MethodDecorator {
136
- return function (target: { constructor: Function }, propertyKey: string) {
140
+ return function (target: { constructor: Function & { [hooks]?: HandlerRegistration[] } }, propertyKey: string) {
137
141
  const newRegistration = { name, method: String(method), targetMethod: propertyKey };
138
142
  const index = registeredInstances.indexOf(target.constructor);
139
-
143
+ if (!target.constructor[hooks]) {
144
+ Object.defineProperty(target.constructor, hooks, {
145
+ value: []
146
+ });
147
+ }
148
+ target.constructor[hooks]?.push(newRegistration);
140
149
  // We need to check if this exact handler is already registered as handlers are registered statically (on the constructor)
141
150
  if (index !== -1 && !isAlreadyRegistered(registeredHandlers[index], newRegistration)) {
142
151
  registeredHandlers[index].push(newRegistration);
@@ -153,23 +162,52 @@ export function controllerExtensionHandler<CExtName extends keyof HookableContro
153
162
  * @param target.constructor
154
163
  * @param controller PageController instance to get the controller extensions instances from
155
164
  */
156
- export function initControllerExtensionHookHandlers(target: { constructor: Function }, controller: Controller): void {
157
- const index = registeredInstances.indexOf(target.constructor);
158
- if (index !== -1) {
159
- const indexableController = controller as unknown as DeepFunctionMap;
165
+ export function initControllerExtensionHookHandlers(
166
+ target: { constructor: Function & { [hooks]?: HandlerRegistration[] } } & { [hooks]?: HandlerRegistration[] },
167
+ controller: Controller
168
+ ): void {
169
+ if (target.constructor[hooks]) {
170
+ let registeredHooks = target.constructor[hooks];
171
+ target[hooks] = deepClone(registeredHooks);
172
+ registeredHooks = target[hooks]!;
160
173
  const indexableTarget = target as unknown as FunctionMap;
161
-
162
- for (const registeredHandler of registeredHandlers[index]) {
163
- const handlerFunction = indexableTarget[registeredHandler.targetMethod].bind(target);
164
-
165
- indexableController[registeredHandler.name][`attach${String(registeredHandler.method)}`](handlerFunction);
174
+ const indexableController = controller as unknown as DeepFunctionMap;
175
+ for (const registeredHook of registeredHooks) {
176
+ registeredHook.handlerFunction = indexableTarget[registeredHook.targetMethod].bind(target);
177
+ indexableController[registeredHook.name][`attach${String(registeredHook.method)}`](registeredHook.handlerFunction);
166
178
  controller.getView()?.attachBeforeExit(() => {
167
- indexableController[registeredHandler.name][`detach${String(registeredHandler.method)}`](handlerFunction);
179
+ indexableController[registeredHook.name][`detach${String(registeredHook.method)}`](registeredHook.handlerFunction);
168
180
  });
169
181
  }
170
182
  }
171
183
  }
172
184
 
185
+ export function removeControllerExtensionHookHandlers(
186
+ target: { constructor: Function & { [hooks]?: HandlerRegistration[] } } & { [hooks]?: HandlerRegistration[] },
187
+ controller: Controller
188
+ ): void {
189
+ if (target[hooks]) {
190
+ const registeredHooks = target[hooks];
191
+ const indexableController = controller as unknown as DeepFunctionMap;
192
+ for (const registeredHook of registeredHooks) {
193
+ indexableController[registeredHook.name]?.[`detach${String(registeredHook.method)}`]?.(registeredHook.handlerFunction);
194
+ }
195
+ }
196
+ }
197
+
198
+ export function propagateHookFromMixin(
199
+ target: Function & { [hooks]?: HandlerRegistration[] },
200
+ source: Function & { [hooks]?: HandlerRegistration[] }
201
+ ): void {
202
+ if (source[hooks]) {
203
+ if (target[hooks]) {
204
+ target[hooks]!.splice(0, 0, ...source[hooks]);
205
+ } else {
206
+ Object.defineProperty(target, hooks, Object.getOwnPropertyDescriptor(source, hooks) || Object.create([]));
207
+ }
208
+ }
209
+ }
210
+
173
211
  export function xmlViewPreprocessor(source: object, _caller?: unknown, _settings?: object): void {
174
212
  const sourceView = source as XMLView;
175
213
  const controller = sourceView.getController() as Controller | undefined;