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 () {
      const __SystemJSRewritingHack = {};
      _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js = _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js || {};
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setGlobal', {
        get() {
          return setGlobal;
        },

        set(thisIsVererySecretVariableName) {
          _export('setGlobal', setGlobal = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'getGlobal', {
        get() {
          return getGlobal;
        },

        set(thisIsVererySecretVariableName) {
          _export('getGlobal', getGlobal = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setLocal', {
        get() {
          return setLocal;
        },

        set(thisIsVererySecretVariableName) {
          _export('setLocal', setLocal = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'getLocal', {
        get() {
          return getLocal;
        },

        set(thisIsVererySecretVariableName) {
          _export('getLocal', getLocal = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'deleteMember', {
        get() {
          return deleteMember;
        },

        set(thisIsVererySecretVariableName) {
          _export('deleteMember', deleteMember = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberBitwiseOR', {
        get() {
          return setMemberBitwiseOR;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberBitwiseOR', setMemberBitwiseOR = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberBitwiseXOR', {
        get() {
          return setMemberBitwiseXOR;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberBitwiseXOR', setMemberBitwiseXOR = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberBitwiseAND', {
        get() {
          return setMemberBitwiseAND;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberBitwiseAND', setMemberBitwiseAND = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberUnsignedRightShift', {
        get() {
          return setMemberUnsignedRightShift;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberUnsignedRightShift', setMemberUnsignedRightShift = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberRightShift', {
        get() {
          return setMemberRightShift;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberRightShift', setMemberRightShift = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberLeftShift', {
        get() {
          return setMemberLeftShift;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberLeftShift', setMemberLeftShift = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberExponentiation', {
        get() {
          return setMemberExponentiation;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberExponentiation', setMemberExponentiation = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberRemainder', {
        get() {
          return setMemberRemainder;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberRemainder', setMemberRemainder = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberDivision', {
        get() {
          return setMemberDivision;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberDivision', setMemberDivision = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberMultiplication', {
        get() {
          return setMemberMultiplication;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberMultiplication', setMemberMultiplication = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberSubtraction', {
        get() {
          return setMemberSubtraction;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberSubtraction', setMemberSubtraction = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMemberAddition', {
        get() {
          return setMemberAddition;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMemberAddition', setMemberAddition = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'setMember', {
        get() {
          return setMember;
        },

        set(thisIsVererySecretVariableName) {
          _export('setMember', setMember = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'getAndCallMember', {
        get() {
          return getAndCallMember;
        },

        set(thisIsVererySecretVariableName) {
          _export('getAndCallMember', getAndCallMember = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'getMember', {
        get() {
          return getMember;
        },

        set(thisIsVererySecretVariableName) {
          _export('getMember', getMember = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'traceMember', {
        get() {
          return traceMember;
        },

        set(thisIsVererySecretVariableName) {
          _export('traceMember', traceMember = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'reset', {
        get() {
          return reset;
        },

        set(thisIsVererySecretVariableName) {
          _export('reset', reset = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'aexpr', {
        get() {
          return aexpr;
        },

        set(thisIsVererySecretVariableName) {
          _export('aexpr', aexpr = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'BaseActiveExpression', {
        get() {
          return BaseActiveExpression;
        },

        set(thisIsVererySecretVariableName) {
          BaseActiveExpression = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'frameBasedAExpr', {
        get() {
          return frameBasedAExpr;
        },

        set(thisIsVererySecretVariableName) {
          frameBasedAExpr = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'Stack', {
        get() {
          return Stack;
        },

        set(thisIsVererySecretVariableName) {
          Stack = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'CompositeKey', {
        get() {
          return CompositeKey;
        },

        set(thisIsVererySecretVariableName) {
          CompositeKey = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'InjectiveMap', {
        get() {
          return InjectiveMap;
        },

        set(thisIsVererySecretVariableName) {
          InjectiveMap = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'BidirectionalMultiMap', {
        get() {
          return BidirectionalMultiMap;
        },

        set(thisIsVererySecretVariableName) {
          BidirectionalMultiMap = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'isFunction', {
        get() {
          return isFunction;
        },

        set(thisIsVererySecretVariableName) {
          isFunction = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'using', {
        get() {
          return using;
        },

        set(thisIsVererySecretVariableName) {
          using = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });

      /*MD # Dependency Analysis MD*/
      let expressionAnalysisMode = false;
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'expressionAnalysisMode', {
        get() {
          return expressionAnalysisMode;
        },

        set(thisIsVererySecretVariableName) {
          expressionAnalysisMode = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      window.__expressionAnalysisMode__ = false;

      const analysisModeManager = {
        __enter__() {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode = true;
          window.__expressionAnalysisMode__ = expressionAnalysisMode;
        },
        __exit__() {
          _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode = !!aexprStack.top();
          window.__expressionAnalysisMode__ = expressionAnalysisMode;
        }
      };
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'analysisModeManager', {
        get() {
          return analysisModeManager;
        },

        set(thisIsVererySecretVariableName) {
          analysisModeManager = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class ExpressionAnalysis {

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

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

      }

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'ExpressionAnalysis', {
        get() {
          return ExpressionAnalysis;
        },

        set(thisIsVererySecretVariableName) {
          ExpressionAnalysis = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class Dependency {
        static getOrCreateFor(context, identifier, type) {
          const key = ContextAndIdentifierCompositeKey.for(context, identifier);
          return CompositeKeyToDependencies.getOrCreateRightFor(key, () => new Dependency(context, identifier, type));
        }

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

          this.isTracked = false;
        }

        updateTracking() {
          if (this.isTracked === 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
          HooksToDependencies.associate(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 = DataStructureHookByDataStructure.getOrCreate(dataStructure, dataStructure => DataStructureHook.forStructure(dataStructure));
            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 = PropertyWrappingHook.getOrCreateForProperty(identifier);
            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')) && !context.tagName.endsWith('-rp19')) {
              // TODO: the member also influences what kind of observer we want to use!
              const mutationObserverHook = MutationObserverHook.getOrCreateForElement(context);
              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 = 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);
            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') {
            HooksToDependencies.associate(FrameBasedHook.instance, this);
          }
        }

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

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

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

          return [context, identifier, value];
        }

        notifyAExprs() {
          const aexprs = DependenciesToAExprs.getAExprsForDep(this);
          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 = CompositeKeyToDependencies.getLeftFor(this);
          if (!compKey) {
            return false;
          }
          const [object] = 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.');
          }
        }

      }

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'Dependency', {
        get() {
          return Dependency;
        },

        set(thisIsVererySecretVariableName) {
          Dependency = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const DependenciesToAExprs = {
        _depsToAExprs: new 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());
        }
      };

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'DependenciesToAExprs', {
        get() {
          return DependenciesToAExprs;
        },

        set(thisIsVererySecretVariableName) {
          DependenciesToAExprs = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const HooksToDependencies = {
        _hooksToDeps: new 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
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'HooksToDependencies', {
        get() {
          return HooksToDependencies;
        },

        set(thisIsVererySecretVariableName) {
          HooksToDependencies = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const ContextAndIdentifierCompositeKey = new CompositeKey();

      // 2.1. ContextAndIdentifierCompositeKey 1<->1 Dependency
      // - CompositeKeyToDependencies
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'ContextAndIdentifierCompositeKey', {
        get() {
          return ContextAndIdentifierCompositeKey;
        },

        set(thisIsVererySecretVariableName) {
          ContextAndIdentifierCompositeKey = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const CompositeKeyToDependencies = new InjectiveMap();
      // 2.2. Dependency *<->* AExpr
      // - DependenciesToAExprs

      /** Source Code Hooks */
      // 3.1. ContextAndIdentifierCompositeKey 1<->1 SourceCodeHook
      // - CompositeKeyToSourceCodeHook
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'CompositeKeyToDependencies', {
        get() {
          return CompositeKeyToDependencies;
        },

        set(thisIsVererySecretVariableName) {
          CompositeKeyToDependencies = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const CompositeKeyToSourceCodeHook = new InjectiveMap();
      // 3.2. SourceCodeHook *<->* Dependency
      // - HooksToDependencies

      /** Data Structure Hooks */
      // 4.1 DataStructureHookByDataStructure
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'CompositeKeyToSourceCodeHook', {
        get() {
          return CompositeKeyToSourceCodeHook;
        },

        set(thisIsVererySecretVariableName) {
          CompositeKeyToSourceCodeHook = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const DataStructureHookByDataStructure = new WeakMap(); // WeakMap<(Set/Array/Map), DataStructureHook>
      /** Wrapping Hooks */
      // 4.2 PropertyWrappingHookByProperty
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'DataStructureHookByDataStructure', {
        get() {
          return DataStructureHookByDataStructure;
        },

        set(thisIsVererySecretVariableName) {
          DataStructureHookByDataStructure = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const PropertyWrappingHookByProperty = new Map(); // Map<(String/Symbol), PropertyWrappingHook>
      /** Mutation Observer Hooks */
      // 4.3 DataStructureHookByDataStructure
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'PropertyWrappingHookByProperty', {
        get() {
          return PropertyWrappingHookByProperty;
        },

        set(thisIsVererySecretVariableName) {
          PropertyWrappingHookByProperty = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const MutationObserverHookByHTMLElement = new WeakMap(); // WeakMap<HTMLElement, MutationObserverHook>
      /** XXX */
      // 4.4 XXX
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'MutationObserverHookByHTMLElement', {
        get() {
          return MutationObserverHookByHTMLElement;
        },

        set(thisIsVererySecretVariableName) {
          MutationObserverHookByHTMLElement = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const EventBasedHookByHTMLElement = new WeakMap(); // WeakMap<HTMLElement, EventBasedHook>


      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'EventBasedHookByHTMLElement', {
        get() {
          return EventBasedHookByHTMLElement;
        },

        set(thisIsVererySecretVariableName) {
          EventBasedHookByHTMLElement = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class Hook {
        constructor() {
          this.installed = false;
        }

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

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'Hook', {
        get() {
          return Hook;
        },

        set(thisIsVererySecretVariableName) {
          Hook = thisIsVererySecretVariableName;
          return true;
        },

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

        constructor(context, identifier) {
          super();

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

        install() {}
        uninstall() {}
      }

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'SourceCodeHook', {
        get() {
          return SourceCodeHook;
        },

        set(thisIsVererySecretVariableName) {
          SourceCodeHook = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class DataStructureHook extends Hook {
        static forStructure(dataStructure) {
          const hook = new 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 (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;
        }
      }

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'DataStructureHook', {
        get() {
          return DataStructureHook;
        },

        set(thisIsVererySecretVariableName) {
          DataStructureHook = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class PropertyWrappingHook extends Hook {
        static getOrCreateForProperty(property) {
          return PropertyWrappingHookByProperty.getOrCreate(property, () => new 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;
            }
          });
        }
      }

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'PropertyWrappingHook', {
        get() {
          return PropertyWrappingHook;
        },

        set(thisIsVererySecretVariableName) {
          PropertyWrappingHook = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class MutationObserverHook extends Hook {
        static getOrCreateForElement(element) {
          return MutationObserverHookByHTMLElement.getOrCreate(element, () => new 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();
        }
      }

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'MutationObserverHook', {
        get() {
          return MutationObserverHook;
        },

        set(thisIsVererySecretVariableName) {
          MutationObserverHook = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class EventBasedHook extends Hook {
        static getOrCreateForElement(element) {
          return EventBasedHookByHTMLElement.getOrCreate(element, () => new 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.tagName === 'TEXTAREA') {
            this._element.addEventListener('input', () => {
              this.changeHappened();
            });
          } else if (this._element.tagName === 'LIVELY-CODE-MIRROR') {
            this._element.editor.on('changes', () => {
              this.changeHappened();
            });
          }
        }

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

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'EventBasedHook', {
        get() {
          return EventBasedHook;
        },

        set(thisIsVererySecretVariableName) {
          EventBasedHook = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class FrameBasedHook extends Hook {
        static get instance() {
          if (!this._instance) {
            this._instance = new FrameBasedHook();
            //Initialization is split to avoid endless recursion
            this._instance.initializeAe();
          }
          return this._instance;
        }

        initializeAe() {
          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 = frameBasedAExpr.aexpr(() => x++);
          ae.isMeta(true);
          ae.onChange(() => {
            this.changeHappened();
          });
        }

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

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'FrameBasedHook', {
        get() {
          return FrameBasedHook;
        },

        set(thisIsVererySecretVariableName) {
          FrameBasedHook = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const aexprStack = new Stack();

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'aexprStack', {
        get() {
          return aexprStack;
        },

        set(thisIsVererySecretVariableName) {
          aexprStack = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class RewritingActiveExpression extends BaseActiveExpression {
        constructor(func, ...args) {
          super(func, ...args);
          this.meta({ strategy: 'Rewriting' });
          ExpressionAnalysis.recalculateDependencies(this);

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

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

        asAExpr() {
          return this;
        }

        supportsDependencies() {
          return true;
        }

        dependencies() {
          return new 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);

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'RewritingActiveExpression', {
        get() {
          return RewritingActiveExpression;
        },

        set(thisIsVererySecretVariableName) {
          _export('RewritingActiveExpression', RewritingActiveExpression = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      class DependencyAPI {
        constructor(aexpr) {
          this._aexpr = aexpr;
        }

        getDependencies() {
          return 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());
        }
      }

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'DependencyAPI', {
        get() {
          return DependencyAPI;
        },

        set(thisIsVererySecretVariableName) {
          DependencyAPI = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      function aexpr(func, ...args) {
        return new RewritingActiveExpression(func, ...args);
      }

      _export('aexpr', aexpr);

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

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'globalRef', {
        get() {
          return globalRef;
        },

        set(thisIsVererySecretVariableName) {
          globalRef = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class DependencyManager {
        static get currentAExpr() {
          return aexprStack.top();
        }

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

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

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

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

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

      }

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'DependencyManager', {
        get() {
          return DependencyManager;
        },

        set(thisIsVererySecretVariableName) {
          DependencyManager = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class TracingHandler {

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

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

        static localUpdated(scope, varName) {
          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!
       */
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js, 'TracingHandler', {
        get() {
          return TracingHandler;
        },

        set(thisIsVererySecretVariableName) {
          TracingHandler = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      function reset() {
        ContextAndIdentifierCompositeKey.clear();

        CompositeKeyToDependencies.clear();
        DependenciesToAExprs.clear();

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

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

      _export('reset', reset);

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

      _export('traceMember', traceMember);

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

      _export('getMember', getMember);

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

      _export('getAndCallMember', getAndCallMember);

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

      _export('setMember', setMember);

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

      _export('setMemberAddition', setMemberAddition);

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

      _export('setMemberSubtraction', setMemberSubtraction);

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

      _export('setMemberMultiplication', setMemberMultiplication);

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

      _export('setMemberDivision', setMemberDivision);

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

      _export('setMemberRemainder', setMemberRemainder);

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

      _export('setMemberExponentiation', setMemberExponentiation);

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

      _export('setMemberLeftShift', setMemberLeftShift);

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

      _export('setMemberRightShift', setMemberRightShift);

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

      _export('setMemberUnsignedRightShift', setMemberUnsignedRightShift);

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

      _export('setMemberBitwiseAND', setMemberBitwiseAND);

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

      _export('setMemberBitwiseXOR', setMemberBitwiseXOR);

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

      _export('setMemberBitwiseOR', setMemberBitwiseOR);

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

      _export('deleteMember', deleteMember);

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

      _export('getLocal', getLocal);

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

      _export('setLocal', setLocal);

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

      _export('getGlobal', getGlobal);

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

      _export('setGlobal', setGlobal);

      _export('default', aexpr);
    }
  };
});