System.register(['lang', 'active-expression', 'active-expression-frame-based', 'src/client/reactive/utils/stack.js', './composite-key.js', './injective-map.js', './bidirectional-multi-map.js', 'utils'], function (_export, _context) {
  "use strict";

  var BaseActiveExpression, frameBasedAExpr, Stack, CompositeKey, InjectiveMap, BidirectionalMultiMap, using, isFunction;
  return {
    setters: [function (_lang) {}, function (_activeExpression) {
      BaseActiveExpression = _activeExpression.BaseActiveExpression;
    }, function (_activeExpressionFrameBased) {
      frameBasedAExpr = _activeExpressionFrameBased;
    }, function (_srcClientReactiveUtilsStackJs) {
      Stack = _srcClientReactiveUtilsStackJs.default;
    }, function (_compositeKeyJs) {
      CompositeKey = _compositeKeyJs.default;
    }, function (_injectiveMapJs) {
      InjectiveMap = _injectiveMapJs.default;
    }, function (_bidirectionalMultiMapJs) {
      BidirectionalMultiMap = _bidirectionalMultiMapJs.default;
    }, function (_utils) {
      using = _utils.using;
      isFunction = _utils.isFunction;
    }],
    execute: function () {
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js || {};
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setGlobal = setGlobal;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.getGlobal = getGlobal;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setLocal = setLocal;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.getLocal = getLocal;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.deleteMember = deleteMember;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberBitwiseOR = setMemberBitwiseOR;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberBitwiseXOR = setMemberBitwiseXOR;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberBitwiseAND = setMemberBitwiseAND;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberUnsignedRightShift = setMemberUnsignedRightShift;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberRightShift = setMemberRightShift;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberLeftShift = setMemberLeftShift;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberExponentiation = setMemberExponentiation;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberRemainder = setMemberRemainder;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberDivision = setMemberDivision;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberMultiplication = setMemberMultiplication;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberSubtraction = setMemberSubtraction;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMemberAddition = setMemberAddition;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.setMember = setMember;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.getAndCallMember = getAndCallMember;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.getMember = getMember;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.traceMember = traceMember;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.reset = reset;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.aexpr = aexpr;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.BaseActiveExpression = BaseActiveExpression;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.frameBasedAExpr = frameBasedAExpr;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Stack = Stack;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.CompositeKey = CompositeKey;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.InjectiveMap = InjectiveMap;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.BidirectionalMultiMap = BidirectionalMultiMap;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.isFunction = isFunction;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.using = using;

      /*HTML <div style="background-color: green">hoo</div> HTML*/
      /*MD # Dependency Analysis MD*/
      let expressionAnalysisMode = false;
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode = expressionAnalysisMode;
      window.__expressionAnalysisMode__ = false;

      const analysisModeManager = {
        __enter__() {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode = true;
          window.__expressionAnalysisMode__ = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode;
        },
        __exit__() {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode = !!_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.aexprStack.top();
          window.__expressionAnalysisMode__ = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode;
        }
      };
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.analysisModeManager = analysisModeManager;
      class ExpressionAnalysis {

        static recalculateDependencies(aexpr) {
          // #TODO: compute diff of Dependencies
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyManager.disconnectAllFor(aexpr);
          this.check(aexpr);
        }

        static check(aexpr) {
          let value, isError;
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.using([_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.analysisModeManager], () => {
            // Do the function execution in ExpressionAnalysisMode
            _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.aexprStack.withElement(aexpr, () => {
              const result = aexpr.evaluateToCurrentValue();
              value = result.value;
              isError = result.isError;
            });
          });
        }

      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.ExpressionAnalysis = ExpressionAnalysis;
      class Dependency {
        static getOrCreateFor(context, identifier, type) {
          const key = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.ContextAndIdentifierCompositeKey.for(context, identifier);
          return _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.CompositeKeyToDependencies.getOrCreateRightFor(key, () => new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Dependency(context, identifier, type));
        }

        // #TODO: compute and cache isGlobal
        constructor(context, identifier, type) {
          this._type = type;

          this.isTracked = false;
        }

        updateTracking() {
          if (this.isTracked === _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependenciesToAExprs.hasAExprsForDep(this)) {
            return;
          }
          if (this.isTracked) {
            this.untrack();
          } else {
            this.track();
          }
        }

        track() {
          this.isTracked = true;

          const [context, identifier, value] = this.contextIdentifierValue();
          const isGlobal = this.isGlobalDependency();

          /*HTML <span style="font-weight: bold;">Source Code Hook</span>: for anything <span style="color: green; font-weight: bold;">members or locals</span> HTML*/
          // always employ the source code hook
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.HooksToDependencies.associate(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.SourceCodeHook.getOrCreateFor(context, identifier), this);

          /*HTML <span style="font-weight: bold;">Data Structure Hook</span>: for <span style="color: green; font-weight: bold;">Sets, Arrays, Maps</span> HTML*/
          var dataStructure;
          if (this._type === 'member') {
            dataStructure = context;
          } else if (this._type === 'local') {
            dataStructure = value;
          }
          if (dataStructure instanceof Array || dataStructure instanceof Set || dataStructure instanceof Map) {
            const dataHook = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DataStructureHookByDataStructure.getOrCreate(dataStructure, dataStructure => _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DataStructureHook.forStructure(dataStructure));
            _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.HooksToDependencies.associate(dataHook, this);
          }

          /*HTML <span style="font-weight: bold;">Wrapping Hook</span>: only for <span style="color: green; font-weight: bold;">"that"</span> HTML*/
          if (isGlobal && identifier === 'that') {
            const wrappingHook = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.PropertyWrappingHook.getOrCreateForProperty(identifier);
            _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.HooksToDependencies.associate(wrappingHook, this);
          }

          /*HTML <span style="font-weight: bold;">Mutation Observer Hook</span>: handling <span style="color: green; font-weight: bold;">HTMLElements</span> HTML*/
          if (this._type === 'member' && context instanceof HTMLElement) {
            // #HACK #TODO: for now, ignore Knotview if unused for Mutations -> need to better separate those hooks, e.g. do not recursively check ALL attribute change, etc.
            if (!(context.tagName === 'KNOT-VIEW' && (identifier === 'knot' || identifier === 'knotLabel'))) {
              // TODO: the member also influences what kind of observer we want to use!
              const mutationObserverHook = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.MutationObserverHook.getOrCreateForElement(context);
              _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.HooksToDependencies.associate(mutationObserverHook, this);
            }
          }

          /*HTML <span style="font-weight: bold;">Event-based Change Hook</span>: handling <span style="color: green; font-weight: bold;">HTMLElements</span> HTML*/
          if (this._type === 'member' && context instanceof HTMLElement) {
            const eventBasedHook = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.EventBasedHook.getOrCreateForElement(context);
            // #TODO: we have to acknowledge that different properties require different events to listen on
            //  e.g. code-mirror might have 'value' (so need to listen for 'change') or 'getCursor' (so need to listen for 'cursorActivity')
            // eventBasedHook.listenFor(identifier);
            _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.HooksToDependencies.associate(eventBasedHook, this);
          }

          /*HTML <span style="font-weight: bold;">Frame-based Change Hook</span>: handling <span style="color: green; font-weight: bold;">Date</span> HTML*/
          // -    if ((this._type === 'member' && context === Date && identifier === 'now') ||
          if (isGlobal && identifier === 'Date') {
            _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.HooksToDependencies.associate(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.FrameBasedHook.instance, this);
          }
        }

        untrack() {
          this.isTracked = false;
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.HooksToDependencies.disconnectAllForDependency(this);
        }

        contextIdentifierValue() {
          const compKey = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.CompositeKeyToDependencies.getLeftFor(this);

          const [context, identifier] = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.ContextAndIdentifierCompositeKey.keysFor(compKey);
          const value = context !== undefined ? context[identifier] : undefined;

          return [context, identifier, value];
        }

        notifyAExprs() {
          const aexprs = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependenciesToAExprs.getAExprsForDep(this);
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyManager.checkAndNotifyAExprs(aexprs);
        }

        isMemberDependency() {
          return this._type === 'member' && !this.isGlobal();
        }
        isGlobalDependency() {
          return this._type === 'member' && this.isGlobal();
        }
        isLocalDependency() {
          return this._type === 'local';
        }
        isGlobal() {
          const compKey = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.CompositeKeyToDependencies.getLeftFor(this);
          if (!compKey) {
            return false;
          }
          const [object] = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.ContextAndIdentifierCompositeKey.keysFor(compKey);
          return object === self;
        }

        getAsDependencyDescription() {
          const [context, identifier, value] = this.contextIdentifierValue();

          if (this.isMemberDependency()) {
            return {
              object: context,
              property: identifier,
              value
            };
          } else if (this.isGlobalDependency()) {
            return {
              name: identifier,
              value
            };
          } else if (this.isLocalDependency()) {
            return {
              scope: context,
              name: identifier,
              value
            };
          } else {
            throw new Error('Dependency is neighter local, member, nor global.');
          }
        }

      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Dependency = Dependency;
      const DependenciesToAExprs = {
        _depsToAExprs: new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.BidirectionalMultiMap(),

        associate(dep, aexpr) {
          this._depsToAExprs.associate(dep, aexpr);
          dep.updateTracking();
        },

        disconnectAllForAExpr(aexpr) {
          const deps = this.getDepsForAExpr(aexpr);
          this._depsToAExprs.removeAllLeftFor(aexpr);
          deps.forEach(dep => dep.updateTracking());
        },

        getAExprsForDep(dep) {
          return Array.from(this._depsToAExprs.getRightsFor(dep));
        },
        getDepsForAExpr(aexpr) {
          return Array.from(this._depsToAExprs.getLeftsFor(aexpr));
        },

        hasAExprsForDep(dep) {
          return this.getAExprsForDep(dep).length >= 1;
        },
        hasDepsForAExpr(aexpr) {
          return this.getDepsForAExpr(aexpr).length >= 1;
        },

        /*
         * Removes all associations.
         */
        clear() {
          this._depsToAExprs.clear();
          this._depsToAExprs.getAllLeft().forEach(dep => dep.updateTracking());
        }
      };

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependenciesToAExprs = DependenciesToAExprs;
      const HooksToDependencies = {
        _hooksToDeps: new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.BidirectionalMultiMap(),

        associate(hook, dep) {
          this._hooksToDeps.associate(hook, dep);
        },
        remove(hook, dep) {
          this._hooksToDeps.remove(hook, dep);
        },

        disconnectAllForDependency(dep) {
          this._hooksToDeps.removeAllLeftFor(dep);
        },

        getDepsForHook(hook) {
          return Array.from(this._hooksToDeps.getRightsFor(hook));
        },
        getHooksForDep(dep) {
          return Array.from(this._hooksToDeps.getLeftsFor(dep));
        },

        hasDepsForHook(hook) {
          return this.getDepsForHook(hook).length >= 1;
        },
        hasHooksForDep(dep) {
          return this.getHooksForDep(dep).length >= 1;
        },

        /*
         * Removes all associations.
         */
        clear() {
          this._hooksToDeps.clear();
        }
      };

      // 1. (obj, prop) or (scope, name) -> ContextAndIdentifierCompositeKey
      // - given via ContextAndIdentifierCompositeKey
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.HooksToDependencies = HooksToDependencies;
      const ContextAndIdentifierCompositeKey = new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.CompositeKey();

      // 2.1. ContextAndIdentifierCompositeKey 1<->1 Dependency
      // - CompositeKeyToDependencies
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.ContextAndIdentifierCompositeKey = ContextAndIdentifierCompositeKey;
      const CompositeKeyToDependencies = new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.InjectiveMap();
      // 2.2. Dependency *<->* AExpr
      // - DependenciesToAExprs

      /** Source Code Hooks */
      // 3.1. ContextAndIdentifierCompositeKey 1<->1 SourceCodeHook
      // - CompositeKeyToSourceCodeHook
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.CompositeKeyToDependencies = CompositeKeyToDependencies;
      const CompositeKeyToSourceCodeHook = new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.InjectiveMap();
      // 3.2. SourceCodeHook *<->* Dependency
      // - HooksToDependencies

      /** Data Structure Hooks */
      // 4.1 DataStructureHookByDataStructure
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.CompositeKeyToSourceCodeHook = CompositeKeyToSourceCodeHook;
      const DataStructureHookByDataStructure = new WeakMap(); // WeakMap<(Set/Array/Map), DataStructureHook>
      /** Wrapping Hooks */
      // 4.2 PropertyWrappingHookByProperty
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DataStructureHookByDataStructure = DataStructureHookByDataStructure;
      const PropertyWrappingHookByProperty = new Map(); // Map<(String/Symbol), PropertyWrappingHook>
      /** Mutation Observer Hooks */
      // 4.3 DataStructureHookByDataStructure
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.PropertyWrappingHookByProperty = PropertyWrappingHookByProperty;
      const MutationObserverHookByHTMLElement = new WeakMap(); // WeakMap<HTMLElement, MutationObserverHook>
      /** XXX */
      // 4.4 XXX
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.MutationObserverHookByHTMLElement = MutationObserverHookByHTMLElement;
      const EventBasedHookByHTMLElement = new WeakMap(); // WeakMap<HTMLElement, EventBasedHook>


      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.EventBasedHookByHTMLElement = EventBasedHookByHTMLElement;
      class Hook {
        constructor() {
          this.installed = false;
        }

        notifyDependencies() {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.HooksToDependencies.getDepsForHook(this).forEach(dep => dep.notifyAExprs());
        }
      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Hook = Hook;
      class SourceCodeHook extends _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Hook {
        static getOrCreateFor(context, identifier) {
          const compKey = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.ContextAndIdentifierCompositeKey.for(context, identifier);
          return _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.CompositeKeyToSourceCodeHook.getOrCreateRightFor(compKey, key => new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.SourceCodeHook());
        }

        constructor(context, identifier) {
          super();

          this.context = context;
          this.identifier = identifier;
        }

        install() {}
        uninstall() {}
      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.SourceCodeHook = SourceCodeHook;
      class DataStructureHook extends _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Hook {
        static forStructure(dataStructure) {
          const hook = new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DataStructureHook();

          function getPrototypeDescriptors(obj) {
            const proto = obj.constructor.prototype;

            const descriptors = Object.getOwnPropertyDescriptors(proto);
            return Object.entries(descriptors).map(([key, desc]) => (desc.key = key, desc));
          }

          function wrapProperty(obj, descriptor, after) {
            Object.defineProperty(obj, descriptor.key, Object.assign({}, descriptor, {
              value(...args) {
                try {
                  return descriptor.value.apply(this, args);
                } finally {
                  after.call(this, ...args);
                }
              }
            }));
          }

          function monitorProperties(obj) {
            const prototypeDescriptors = getPrototypeDescriptors(obj);
            Object.entries(Object.getOwnPropertyDescriptors(obj)); // unused -> need for array

            prototypeDescriptors.filter(descriptor => descriptor.key !== 'constructor' // the property constructor needs to be a constructor if called (as in cloneDeep in lodash); We leave it out explicitly as the constructor does not change any state #TODO
            ).forEach(addDescriptor => {
              // var addDescriptor = prototypeDescriptors.find(d => d.key === 'add')
              if (addDescriptor.value) {
                if (_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.isFunction(addDescriptor.value)) {
                  wrapProperty(obj, addDescriptor, function () {
                    // #HACK #TODO we need an `withoutLayer` equivalent here
                    if (window.__compareAExprResults__) {
                      return;
                    }

                    this; // references the modified container
                    hook.notifyDependencies();
                  });
                } else {
                  console.warn(`Property ${addDescriptor.key} has a value that is not a function, but ${addDescriptor.value}.`);
                }
              } else {
                console.warn(`Property ${addDescriptor.key} has no value.`);
              }
            });
          }

          monitorProperties(dataStructure);

          // set.add = function add(...args) {
          //   const result = Set.prototype.add.call(this, ...args);
          //   hook.notifyDependencies();
          //   return result;
          // }
          return hook;
        }
      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DataStructureHook = DataStructureHook;
      class PropertyWrappingHook extends _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Hook {
        static getOrCreateForProperty(property) {
          return _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.PropertyWrappingHookByProperty.getOrCreate(property, () => new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.PropertyWrappingHook(property));
        }

        constructor(property) {
          super();

          this.value = self[property];
          const { configurable, enumerable } = Object.getOwnPropertyDescriptor(self, property);

          // #TODO: keep old property accessors if present (otherwise, we do not interact with COP and ourselves, i.e. other property wrappers)
          Object.defineProperty(self, property, {
            configurable,
            enumerable,

            get: () => this.value,
            set: value => {
              const result = this.value = value;
              this.notifyDependencies();
              return result;
            }
          });
        }
      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.PropertyWrappingHook = PropertyWrappingHook;
      class MutationObserverHook extends _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Hook {
        static getOrCreateForElement(element) {
          return _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.MutationObserverHookByHTMLElement.getOrCreate(element, () => new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.MutationObserverHook(element));
        }

        constructor(element) {
          super();

          this._element = element;

          const o = new MutationObserver((mutations, observer) => {
            // const mutationRecords = o.takeRecords();
            // lively.notify(`mutation on ${this._element.tagName}; ${mutations
            //               .filter(m => m.type === "attributes")
            //               .map(m => m.attributeName).join(', ')}.`)
            this.changeHappened();
            // mutations.forEach(mutation => {
            //   if(mutation.type == "attributes") {
            //     lively.notify(
            //       `${mutation.oldValue} -> ${mutation.target.getAttribute(mutation.attributeName)}`,
            //       `attribute: ${mutation.attributeName}`
            //     );
            //   }
            //   if(mutation.type == "characterData") {
            //     lively.notify(
            //       `${mutation.oldValue}}`,
            //       `characterData`
            //     );
            //   }
            //   if(mutation.type == "childList") {
            //     lively.success(
            //       `${mutation.addedNodes.length} added, ${mutation.removedNodes.length} removed`,
            //       `childList`
            //     );
            //   }
            // });
          });

          o.observe(this._element, {
            attributes: true,
            attributeFilter: undefined,
            attributeOldValue: true,

            characterData: true,
            characterDataOldValue: true,

            childList: true,

            subtree: true
          });

          // o.disconnect();
        }

        changeHappened() {
          this.notifyDependencies();
        }
      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.MutationObserverHook = MutationObserverHook;
      class EventBasedHook extends _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Hook {
        static getOrCreateForElement(element) {
          return _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.EventBasedHookByHTMLElement.getOrCreate(element, () => new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.EventBasedHook(element));
        }

        constructor(element) {
          super();

          this._element = element;

          // #TODO: when the type of an input element changes, 'value' or 'checked' become unavailable
          if (this._element.tagName === 'INPUT') {
            this._element.addEventListener('input', () => {
              this.changeHappened();
            });
          } else if (this._element.tagName === 'LIVELY-CODE-MIRROR') {
            this._element.editor.on('changes', () => {
              this.changeHappened();
            });
          }
        }

        changeHappened() {
          this.notifyDependencies();
        }
      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.EventBasedHook = EventBasedHook;
      class FrameBasedHook extends _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Hook {
        static get instance() {
          return this._instance = this._instance || new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.FrameBasedHook();
        }

        constructor() {
          super();

          let x = 0;
          // #TODO: caution, we currently use a side-effect function! How can we mitigate this? E.g. using `Date.now()` as expression
          let ae = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.frameBasedAExpr.aexpr(() => x++);
          ae.onChange(() => {
            this.changeHappened();
          });
        }

        changeHappened() {
          this.notifyDependencies();
        }
      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.FrameBasedHook = FrameBasedHook;
      const aexprStack = new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Stack();

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.aexprStack = aexprStack;
      class RewritingActiveExpression extends _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.BaseActiveExpression {
        constructor(func, ...args) {
          super(func, ...args);
          this.meta({ strategy: 'Rewriting' });
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.ExpressionAnalysis.recalculateDependencies(this);

          if (new.target === _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.RewritingActiveExpression) {
            this.addToRegistry();
          }
        }

        dispose() {
          super.dispose();
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyManager.disconnectAllFor(this);
        }

        asAExpr() {
          return this;
        }

        supportsDependencies() {
          return true;
        }

        dependencies() {
          return new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyAPI(this);
        }

        sharedDependenciesWith(otherAExpr) {
          const ownDependencies = this.dependencies().all();
          const otherDependencies = otherAExpr.dependencies().all();
          const [own, shared, other] = ownDependencies.computeDiff(otherDependencies);
          return shared;
        }
      }

      _export('RewritingActiveExpression', RewritingActiveExpression);

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.RewritingActiveExpression = RewritingActiveExpression;
      class DependencyAPI {
        constructor(aexpr) {
          this._aexpr = aexpr;
        }

        getDependencies() {
          return _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependenciesToAExprs.getDepsForAExpr(this._aexpr);
        }

        all() {
          return Array.from(this.getDependencies());
        }

        locals() {
          return this.getDependencies().filter(dependency => dependency.isLocalDependency()).map(dependency => dependency.getAsDependencyDescription());
        }

        members() {
          return this.getDependencies().filter(dependency => dependency.isMemberDependency()).map(dependency => dependency.getAsDependencyDescription());
        }

        globals() {
          return this.getDependencies().filter(dependency => dependency.isGlobalDependency()).map(dependency => dependency.getAsDependencyDescription());
        }
      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyAPI = DependencyAPI;
      function aexpr(func, ...args) {
        return new _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.RewritingActiveExpression(func, ...args);
      }

      _export('aexpr', aexpr);

      const globalRef = typeof window !== "undefined" ? window : // browser tab
      typeof self !== "undefined" ? self : // web worker
      global; // node.js

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.globalRef = globalRef;
      class DependencyManager {
        static get currentAExpr() {
          return _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.aexprStack.top();
        }

        // #TODO, #REFACTOR: extract into own method; remove from this class
        static disconnectAllFor(aexpr) {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependenciesToAExprs.disconnectAllForAExpr(aexpr);
        }

        // #TODO, #REFACTOR: extract into configurable dispatcher class
        static checkAndNotifyAExprs(aexprs) {
          aexprs.forEach(aexpr => {
            _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.ExpressionAnalysis.recalculateDependencies(aexpr);
          });
          aexprs.forEach(aexpr => aexpr.checkAndNotify());
        }

        /**
         * **************************************************************
         * ********************** associate *****************************
         * **************************************************************
         */
        static associateMember(obj, prop) {
          const dependency = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Dependency.getOrCreateFor(obj, prop, 'member');
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependenciesToAExprs.associate(dependency, this.currentAExpr);
        }

        static associateGlobal(globalName) {
          const dependency = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Dependency.getOrCreateFor(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.globalRef, globalName, 'member');
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependenciesToAExprs.associate(dependency, this.currentAExpr);
        }

        static associateLocal(scope, varName) {
          const dependency = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.Dependency.getOrCreateFor(scope, varName, 'local');
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependenciesToAExprs.associate(dependency, this.currentAExpr);
        }

      }

      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyManager = DependencyManager;
      class TracingHandler {

        /**
         * **************************************************************
         * ********************** update ********************************
         * **************************************************************
         */
        static memberUpdated(obj, prop) {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.SourceCodeHook.getOrCreateFor(obj, prop).notifyDependencies();
        }

        static globalUpdated(globalName) {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.SourceCodeHook.getOrCreateFor(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.globalRef, globalName).notifyDependencies();
        }

        static localUpdated(scope, varName) {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.SourceCodeHook.getOrCreateFor(scope, varName).notifyDependencies();
        }

      }

      /*
       * Disconnects all associations between active expressions and object properties
       * As a result no currently enable active expression will be notified again,
       * effectively removing them from the system.
       *
       * #TODO: Caution, this might break with some semantics, if we still have references to an aexpr!
       */
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler = TracingHandler;
      function reset() {
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.ContextAndIdentifierCompositeKey.clear();

        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.CompositeKeyToDependencies.clear();
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependenciesToAExprs.clear();

        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.CompositeKeyToSourceCodeHook.clear();
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.HooksToDependencies.clear();
      }

      /*MD # Source Code Point Cuts MD*/
      /**
       * (C)RUD for member attributes
       */

      _export('reset', reset);

      function traceMember(obj, prop) {
        if (_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode) {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyManager.associateMember(obj, prop);
        }
      }

      _export('traceMember', traceMember);

      function getMember(obj, prop) {
        if (_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode) {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyManager.associateMember(obj, prop);
        }
        const result = obj[prop];
        return result;
      }

      _export('getMember', getMember);

      function getAndCallMember(obj, prop, args = []) {
        if (_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode) {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyManager.associateMember(obj, prop);
        }
        const result = obj[prop](...args);
        return result;
      }

      _export('getAndCallMember', getAndCallMember);

      function setMember(obj, prop, val) {
        const result = obj[prop] = val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMember', setMember);

      function setMemberAddition(obj, prop, val) {
        const result = obj[prop] += val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberAddition', setMemberAddition);

      function setMemberSubtraction(obj, prop, val) {
        const result = obj[prop] -= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberSubtraction', setMemberSubtraction);

      function setMemberMultiplication(obj, prop, val) {
        const result = obj[prop] *= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberMultiplication', setMemberMultiplication);

      function setMemberDivision(obj, prop, val) {
        const result = obj[prop] /= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberDivision', setMemberDivision);

      function setMemberRemainder(obj, prop, val) {
        const result = obj[prop] %= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberRemainder', setMemberRemainder);

      function setMemberExponentiation(obj, prop, val) {
        const result = obj[prop] **= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberExponentiation', setMemberExponentiation);

      function setMemberLeftShift(obj, prop, val) {
        const result = obj[prop] <<= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberLeftShift', setMemberLeftShift);

      function setMemberRightShift(obj, prop, val) {
        const result = obj[prop] >>= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberRightShift', setMemberRightShift);

      function setMemberUnsignedRightShift(obj, prop, val) {
        const result = obj[prop] >>>= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberUnsignedRightShift', setMemberUnsignedRightShift);

      function setMemberBitwiseAND(obj, prop, val) {
        const result = obj[prop] &= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberBitwiseAND', setMemberBitwiseAND);

      function setMemberBitwiseXOR(obj, prop, val) {
        const result = obj[prop] ^= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberBitwiseXOR', setMemberBitwiseXOR);

      function setMemberBitwiseOR(obj, prop, val) {
        const result = obj[prop] |= val;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('setMemberBitwiseOR', setMemberBitwiseOR);

      function deleteMember(obj, prop) {
        const result = delete obj[prop];
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.memberUpdated(obj, prop);
        return result;
      }

      _export('deleteMember', deleteMember);

      function getLocal(scope, varName, value) {
        if (_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode) {
          scope[varName] = value;
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyManager.associateLocal(scope, varName);
        }
      }

      _export('getLocal', getLocal);

      function setLocal(scope, varName, value) {
        scope[varName] = value;
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.localUpdated(scope, varName);
      }

      _export('setLocal', setLocal);

      function getGlobal(globalName) {
        if (_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode) {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.DependencyManager.associateGlobal(globalName);
        }
      }

      _export('getGlobal', getGlobal);

      function setGlobal(globalName) {
        _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.TracingHandler.globalUpdated(globalName);
      }

      _export('setGlobal', setGlobal);

      _export('default', _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.aexpr);
    }
  };
});