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

  var BaseActiveExpression, frameBasedAExpr, Stack, CompositeKey, InjectiveMap, BidirectionalMultiMap, DualKeyMap, isFunction, lively, _, AExprRegistry, DebuggingCache, Preferences;

  return {
    setters: [function (_lang) {}, function (_activeExpression) {
      BaseActiveExpression = _activeExpression.BaseActiveExpression;
    }, function (_activeExpressionFrameBased) {
      frameBasedAExpr = _activeExpressionFrameBased;
    }, function (_utilsStackJs) {
      Stack = _utilsStackJs.default;
    }, function (_compositeKeyJs) {
      CompositeKey = _compositeKeyJs.default;
    }, function (_injectiveMapJs) {
      InjectiveMap = _injectiveMapJs.default;
    }, function (_bidirectionalMultiMapJs) {
      BidirectionalMultiMap = _bidirectionalMultiMapJs.default;
    }, function (_dualKeyMapJs) {
      DualKeyMap = _dualKeyMapJs.default;
    }, function (_utils) {
      isFunction = _utils.isFunction;
    }, function (_srcClientLivelyJs) {
      lively = _srcClientLivelyJs.default;
    }, function (_srcExternalLodashLodashJs) {
      _ = _srcExternalLodashLodashJs.default;
    }, function (_srcClientReactiveActiveExpressionAeRegistryJs) {
      AExprRegistry = _srcClientReactiveActiveExpressionAeRegistryJs.AExprRegistry;
    }, function (_srcClientReactiveActiveExpressionAeDebuggingCacheJs) {
      DebuggingCache = _srcClientReactiveActiveExpressionAeDebuggingCacheJs.DebuggingCache;
    }, function (_srcClientPreferencesJs) {
      Preferences = _srcClientPreferencesJs.default;
    }],
    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, 'updateMember', {
        get() {
          return updateMember;
        },

        set(thisIsVererySecretVariableName) {
          _export('updateMember', updateMember = 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, 'getHooksInFile', {
        get() {
          return getHooksInFile;
        },

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

          return true;
        },

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

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

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

        set(thisIsVererySecretVariableName) {
          _export('getAEDataForFile', getAEDataForFile = 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, 'DualKeyMap', {
        get() {
          return DualKeyMap;
        },

        set(thisIsVererySecretVariableName) {
          DualKeyMap = 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, 'lively', {
        get() {
          return lively;
        },

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

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

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

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

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

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

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

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

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

        enumerable: true,
        configurable: true
      });

      /*MD # Dependency Analysis MD*/

      const analysisStack = new Stack();

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

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

        enumerable: true,
        configurable: true
      });
      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;

      class ExpressionAnalysis {

        static recalculateDependencies(aexpr) {
          if (analysisStack.findUp(({ currentAExpr }) => currentAExpr === aexpr)) {
            throw new Error('Attempt to recalculate an Active Expression while it is already recalculating dependencies');
          }

          try {
            _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode = true;
            window.__expressionAnalysisMode__ = expressionAnalysisMode;

            // Do the function execution in ExpressionAnalysisMode
            analysisStack.withElement({ currentAExpr: aexpr, dependencies: new Set() }, () => {
              try {
                const { value, isError } = aexpr.evaluateToCurrentValue();
              } catch (e) {
                console.error("Error during AE Dependency Calculation", e.message);
              } finally {
                this.applyDependencies();
              }
            });
          } finally {
            _recorder_._src_client_reactive_active_expression_rewriting_active_expression_rewriting_js.expressionAnalysisMode = !!analysisStack.top();
            window.__expressionAnalysisMode__ = expressionAnalysisMode;
          }
        }

        static associateDependency(dependency) {
          const { dependencies } = analysisStack.top();
          dependencies.add(dependency);
        }

        static applyDependencies() {
          const { currentAExpr, dependencies } = analysisStack.top();

          const currentDependencies = currentAExpr.dependencies().all();
          const currentSet = new Set(currentDependencies);
          let removedDependencies = currentDependencies.filter(dependency => !dependencies.has(dependency));
          const newDependencies = [...dependencies].filter(dependency => !currentSet.has(dependency));

          removedDependencies.forEach(dependency => DependenciesToAExprs.disassociate(dependency, currentAExpr));
          dependencies.forEach(dependency => {
            DependenciesToAExprs.associate(dependency, currentAExpr);
          });

          const matching = [];
          removedDependencies = removedDependencies.filter(dependency => {
            const index = newDependencies.findIndex(dependency2 => this.equalish(dependency, dependency2));
            if (index >= 0) {
              matching.push({ removed: dependency.getKey(), added: newDependencies[index].getKey() });
              dependency.currentVersion = newDependencies[index];
              newDependencies.splice(index, 1);
              return false;
            }
            return true;
          });
          if (newDependencies.length > 0 || removedDependencies.length > 0 || matching.length > 0) {
            currentAExpr.logEvent('dependencies changed', { added: newDependencies.map(d => d.getKey()), removed: removedDependencies.map(d => d.getKey()), matching });
          }
        }

        static equalish(d1, d2) {
          if (d1.type() !== d2.type()) return false;
          return _.isEqual(d1.getKey(), d2.getKey());
        }

      }

      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) {
          return ContextAndIdentifierToDependencies.getOrCreate(context, identifier, () => new Dependency(context, identifier, type));
        }

        // Generates a key for this dependency. This allows this dependency to be found again at a later time, after the originial dependency might have already been deleted.
        getKey() {
          return new DependencyKey(this.context, this.identifier);
        }

        // #TODO: compute and cache isGlobal
        constructor(context, identifier, type) {
          this._type = type;
          // this.classFilePath = context.__classFilePath__;
          this.isTracked = false;
          this.hooks = [];
          this.context = context;
          this.identifier = identifier;
        }

        updateTracking() {
          if (this.isTracked === DependenciesToAExprs.hasAExprsForDep(this)) {
            return;
          }
          if (this.isTracked) {
            this.untrack();
          } else {
            this.track();
          }
          for (const hook of this.getHooks()) {
            hook.getLocations().then(locations => DebuggingCache.updateFiles(locations.map(loc => loc.file)));
          }
          for (const ae of DependenciesToAExprs.getAExprsForDep(this)) {
            if (ae.meta().has("location")) {
              DebuggingCache.updateFiles([ae.meta().get("location").file]);
            }
          }
        }

        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
          this.sourceCodeHook = new SourceCodeHook(context, identifier);
          this.associateWithHook(this.sourceCodeHook);

          /*HTML <span style="font-weight: bold;">Data Structure Hook</span>: for <span style="color: green; font-weight: bold;">Sets, Arrays, Maps</span> HTML*/
          let dataStructure;
          if (this._type === 'member') {
            dataStructure = context;
          } else if (this._type === 'local') {
            dataStructure = value;
          }
          if (dataStructure instanceof Array || dataStructure instanceof Set || dataStructure instanceof Map) {
            this.associateWithHook(DataStructureHook.getOrCreateForDataStructure(dataStructure));
          }

          /*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);
            this.associateWithHook(wrappingHook);
          }

          /*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 !== 'LIVELY-TABLE' && !(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!
              this.associateWithHook(MutationObserverHook.getOrCreateForElement(context));
            }
          }

          /*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) {
            // #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);
            this.associateWithHook(EventBasedHook.getOrCreateForElement(context));
          }

          /*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') {
            //TODO: This violates the each Hook belongs to one Dependency Rule
            this.associateWithHook(FrameBasedHook.instance);
          }
        }

        associateWithHook(hook) {
          this.hooks.push(hook);
          hook.addDependency(this);
        }

        untrack() {
          this.isTracked = false;
          ContextAndIdentifierToDependencies.removeSecondary(this.context, this.identifier);

          // Track affected files
          for (const hook of this.hooks) {
            hook.removeDependency(this);
            hook.getLocations().then(locations => DebuggingCache.updateFiles(locations.map(loc => loc.file)));
          }
          for (const ae of DependenciesToAExprs.getAExprsForDep(this)) {
            if (ae.meta().has("location")) {
              DebuggingCache.updateFiles([ae.meta().get("location").file]);
            }
          }
        }

        //Todo: Replace
        contextIdentifierValue() {
          const value = this.context !== undefined ? this.context[this.identifier] : undefined;

          return [this.context, this.identifier, value];
        }

        notifyAExprs(location, hook) {
          const aexprs = DependenciesToAExprs.getAExprsForDep(this);
          DependencyManager.checkAndNotifyAExprs(aexprs, location, this, hook);
        }

        type() {
          if (this.isGlobal()) return "global";
          return this._type;
        }

        isMemberDependency() {
          return this._type === 'member' && !this.isGlobal();
        }
        isGlobalDependency() {
          return this._type === 'member' && this.isGlobal();
        }
        isLocalDependency() {
          return this._type === 'local';
        }
        isGlobal() {
          return this.context === self;
        }

        getHooks() {
          return this.hooks;
        }

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

          if (this.isGlobalDependency()) {
            return identifier.toString();
          }
          return (context ? context.constructor.name : "") + "." + identifier;
        }

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

          if (this.isMemberDependency()) {
            return {
              object: context,
              property: identifier,
              value
            };
          }

          if (this.isGlobalDependency()) {
            return {
              name: identifier,
              value
            };
          }

          if (this.isLocalDependency()) {
            return {
              scope: context,
              name: identifier,
              value
            };
          }

          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) {
          if (this._depsToAExprs.has(dep, aexpr)) return;
          const location = aexpr.meta().get("location");
          if (location && location.file) {
            DebuggingCache.updateFiles([location.file]);
          }
          this._depsToAExprs.associate(dep, aexpr);
          dep.updateTracking();

          // Track affected files
          for (const hook of dep.getHooks()) {
            hook.getLocations().then(locations => DebuggingCache.updateFiles(locations.map(loc => loc.file)));
          }
        },

        disassociate(dep, aexpr) {
          this._depsToAExprs.remove(dep, aexpr);
          dep.updateTracking();
          for (const hook of dep.getHooks()) {
            hook.getLocations().then(locations => DebuggingCache.updateFiles(locations.map(loc => loc.file)));
          }
          //TODO: Remove AE from assiciated file, if it was the last dependency?
        },

        disconnectAllForAExpr(aexpr) {
          const location = aexpr.meta().get("location");
          const deps = [...this.getDepsForAExpr(aexpr)];
          this._depsToAExprs.removeAllLeftFor(aexpr);
          deps.forEach(dep => {
            dep.updateTracking();
          });
          if (deps.length > 0) {
            aexpr.logEvent('dependencies changed', { added: [], removed: deps.map(d => d.getKey()), matching: [] });
          }
          if (location && location.file) {
            DebuggingCache.updateFiles([location.file]);
          }

          // Track affected files
          for (const dep of deps) {
            for (const hook of dep.getHooks()) {
              hook.getLocations().then(locations => DebuggingCache.updateFiles(locations.map(loc => loc.file)));
            }
          }
        },

        getAExprsForDep(dep) {
          if (!this._depsToAExprs.hasLeft(dep)) return [];
          return Array.from(this._depsToAExprs.getRightsFor(dep));
        },
        getDepsForAExpr(aexpr) {
          if (!this._depsToAExprs.hasRight(aexpr)) return [];
          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
      });
      async function getAEDataForFile(url) {
        let result = new Map();
        for (const ae of AExprRegistry.getLocationCache().getAEsInFile(url)) {
          result.set(ae, getDependenciesAndHooksForAE(ae));
        }
        for (const hook of await getHooksInFile(url)) {
          for (const dependency of hook.getDependencies()) {
            for (const ae of DependenciesToAExprs.getAExprsForDep(dependency)) {
              const location = ae.meta().get("location");
              if (!location) continue; // maybe if the ae has no location, we actually want to add it here?
              const file = location.file;
              // if the AE is also in this file, we already covered it with the previous loop
              if (!file.includes(url)) {
                result.getOrCreate(ae, () => []).push({ hook, dependency: dependency.getKey() });
              }
            }
          }
        }
        return result;
      }

      _export('getAEDataForFile', getAEDataForFile);

      function getDependenciesAndHooksForAE(ae) {
        const result = [];
        for (const dependency of DependenciesToAExprs.getDepsForAExpr(ae)) {
          for (const hook of dependency.getHooks()) {
            result.push({ hook, dependency: dependency.getKey() });
          }
        }
        return result;
      }

      async function getHooksInFile(url) {
        const allHooks = ContextAndIdentifierToDependencies.allValues().flatMap(dep => dep.getHooks());
        const hooksWithLocations = await Promise.all(allHooks.map(hook => {
          return hook.getLocations().then(locations => {
            return { hook, locations };
          });
        }));
        return hooksWithLocations.filter(({ hook, locations }) => {
          return locations.some(loc => loc && loc.file && loc.file.includes(url));
        }).map(({ hook, locations }) => hook);
      }

      _export('getHooksInFile', getHooksInFile);

      class DependencyKey {
        constructor(context, identifier) {
          this.context = context;
          this.identifier = identifier;
        }

        getDependency() {
          return ContextAndIdentifierToDependencies.get(this.context, this.identifier);
        }

        equals(other) {
          if (other.context === this.context) {
            // Handle weird edgecase to deal with array[0] being the same as array["0"]
            if (Array.isArray(this.context)) {
              if (typeof this.identifier !== typeof other.identifier) {
                if (typeof this.identifier === "string") {
                  return this.identifier === other.identifier + "";
                }
                if (typeof other.identifier === "string") {
                  return other.identifier === this.identifier + "";
                }
              }
            }
            return other.identifier === this.identifier;
          }
          return false;
        }

        getCurrentVersion() {
          if (!this.currentVersion) {
            return this;
          } else {
            this.currentVersion = this.currentVersion.getCurrentVersion();
          }
          return this.currentVersion;
        }

        getValue() {
          if (this.context instanceof Map) {
            return this.context.get(this.identifier);
          } else if (this.context instanceof Set) {
            return [...this.context][this.identifer];
          } else {
            return this.context[this.identifier];
          }
        }
      }

      // 1. Two step map with (obj|scope) as primary key and (prop|name) as secondary key mapping to the dependencies

      _export('DependencyKey', DependencyKey);

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

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

          return true;
        },

        enumerable: true,
        configurable: true
      });
      const ContextAndIdentifierToDependencies = new DualKeyMap();

      //const ContextToIdentifier = new MultiMap();
      //const IdentifierToDependency = new InjectiveMap();
      // 1. (obj, prop) or (scope, name) -> ContextAndIdentifierCompositeKey
      // - given via ContextAndIdentifierCompositeKey

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

      /** Source Code Hooks */
      // 3.1. ContextAndIdentifierCompositeKey 1<->1 SourceCodeHook
      // - CompositeKeyToSourceCodeHook
      //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, 'ContextAndIdentifierToDependencies', {
        get() {
          return ContextAndIdentifierToDependencies;
        },

        set(thisIsVererySecretVariableName) {
          ContextAndIdentifierToDependencies = 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.dependencies = new Set();
          this.installed = false;
          this.locations = [];
          this.locationPromises = new Set();
        }

        addLocation(location) {
          if (!location) return;
          const addToMember = l => {
            if (l && !this.locations.some(loc => _.isEqual(loc, l))) {
              this.locations.push(l);
            }
          };
          if (location.then) {
            this.locationPromises.add(location);
            location.then(resolved => {
              this.locationPromises.delete(location);
              addToMember(resolved);
            });
          } else {
            addToMember(location);
          }
        }

        getDependencies() {
          return this.dependencies;
        }

        addDependency(dependency) {
          this.dependencies.add(dependency);
        }

        removeDependency(dependency) {
          this.dependencies.delete(dependency);
        }

        async getLocations() {
          await Promise.all(this.locationPromises);
          return this.locations;
        }

        informationString() {
          return "Generic Hook";
        }

        notifyDependencies(location) {
          const debugging = Preferences.get("EnableAEDebugging");
          let loc;
          if (debugging) {
            loc = location || TracingHandler.findRegistrationLocation();
            this.addLocation(loc);

            this.getLocations().then(locations => DebuggingCache.updateFiles(locations.map(loc => loc.file)));
          }
          for (const dep of [...this.dependencies]) {
            if (debugging) {
              for (const ae of DependenciesToAExprs.getAExprsForDep(dep)) {
                if (ae.meta().has("location")) {
                  DebuggingCache.updateFiles([ae.meta().get("location").file]);
                }
              }
            }
            dep.notifyAExprs(loc, this);
          }
        }
      }

      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 {

        informationString() {
          return "SourceCodeHook: " + this.context + "." + this.identifier;
        }

        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 getOrCreateForDataStructure(dataStructure) {
          return DataStructureHookByDataStructure.getOrCreate(dataStructure, () => new DataStructureHook(dataStructure));
        }
        constructor(dataStructure) {
          super();
          this.monitorProperties(dataStructure);

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

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

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

        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);
              }
            }
          }));
        }

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

          // the property constructor needs to be a constructor if called (as in cloneDeep in lodash);
          // We can also leave out functions that do not change the state
          const ignoredDescriptorKeys = new Set(["at", "get", "constructor", "concat", "entries", "every", "filter", "find", "findIndex", "forEach", "includes", "indexOf", "join", "keys", "lastIndexOf", "reduce", "reduceRight", "slice", "toString", "toLocaleString", "values"]);

          prototypeDescriptors.filter(descriptor => !ignoredDescriptorKeys.has(descriptor.key)).forEach(addDescriptor => {
            // var addDescriptor = prototypeDescriptors.find(d => d.key === 'add')
            if (addDescriptor.value) {
              if (isFunction(addDescriptor.value)) {
                this.wrapProperty(obj, addDescriptor, function () {
                  // #HACK #TODO we need an `withoutLayer` equivalent here
                  if (window.__compareAExprResults__) {
                    return;
                  }

                  this; // references the modified container
                  myself.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.`)
              }
          });
        }

        informationString() {
          return "DataStructureHook";
        }
      }

      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.property = property;
          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;
            }
          });
        }

        informationString() {
          return "PropertyWrappingHook: " + this.property;
        }
      }

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

        informationString() {
          return "MutationObserverHook: " + this._element;
        }
      }

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

        informationString() {
          return "EventBasedHook: " + this._element;
        }
      }

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

        informationString() {
          return "FrameBasedHook";
        }
      }

      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
      });
      class RewritingActiveExpression extends BaseActiveExpression {
        constructor(func, ...args) {
          super(func, ...args);
          this.meta({ strategy: 'Rewriting' });
          this.updateDependencies();
        }

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

        // #TODO: why is this defined here, and not in the superclass?
        asAExpr() {
          return this;
        }

        updateDependencies() {
          if (this.isDisabled()) {
            return;
          }

          ExpressionAnalysis.recalculateDependencies(this);
        }
        supportsDependencies() {
          return true;
        }

        dependencies() {
          return new DependencyAPI(this);
        }

        getDataBindingDependencyKey() {
          if (!this.isDataBinding()) return undefined;

          if (!this.dataBindingDependencyKey) {
            const { context, identifier } = this.meta().get('conceptInfo');
            this.dataBindingDependencyKey = new DependencyKey(context, identifier);
          }
          return this.dataBindingDependencyKey;
        }

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

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

        enumerable: true,
        configurable: true
      });
      class DependencyManager {
        // #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, location, dependency, hook) {
          const cbStack = AExprRegistry.callbackStack;
          const cbTop = cbStack[cbStack.length - 1];
          const info = Promise.resolve(location).then(resolvedLoc => {
            return { location: resolvedLoc, dependency: dependency.getKey(), hook, parentAE: cbTop && cbTop.ae, parentCallback: cbTop && cbTop.callback };
          });
          aexprs.slice().reverse().forEach(ae => {
            if (new Set(AExprRegistry.evaluationStack).has(ae)) return;
            const infos = [info];
            const index = notificationQueue.findIndex(stackItem => stackItem.ae === ae);
            if (index > -1) {
              infos.push(...notificationQueue[index].infos);
              notificationQueue.splice(index, 1);
            }
            //#ToDo: Insert in order of AE creation, to guarantee a topologically sorted graph for Signals. Signals before everything else?
            notificationQueue.push({ ae, infos });
            notificationQueue.sort((a, b) => {
              if (a.ae.isDataBinding() !== b.ae.isDataBinding()) {
                return b.ae.isDataBinding() ? 1 : -1;
              } else {
                return a.ae.id > b.ae.id ? 1 : -1;
              }
            });
          });

          while (notificationQueue.length > 0) {
            const { ae, infos } = notificationQueue[0];
            //if(!aexprs.includes(ae)) return;
            notificationQueue.splice(0, 1);
            if (new Set(AExprRegistry.evaluationStack).has(ae)) continue;
            ae.updateDependencies();
            ae.checkAndNotify(infos);
          }
        }

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

        static associateGlobal(globalName) {
          const dependency = Dependency.getOrCreateFor(globalRef, globalName, 'member');
          ExpressionAnalysis.associateDependency(dependency);
        }

        static associateLocal(scope, varName) {
          const dependency = Dependency.getOrCreateFor(scope, varName, 'local');
          ExpressionAnalysis.associateDependency(dependency);
        }

      }

      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, location) {
          const dependency = ContextAndIdentifierToDependencies.get(obj, prop);
          if (!dependency || !dependency.sourceCodeHook) return;
          dependency.sourceCodeHook.notifyDependencies(location);
        }

        static globalUpdated(globalName, location) {
          const dependency = ContextAndIdentifierToDependencies.get(globalRef, globalName);
          if (!dependency || !dependency.sourceCodeHook) return;
          dependency.sourceCodeHook.notifyDependencies(location);
        }

        static localUpdated(scope, varName, location) {
          const dependency = ContextAndIdentifierToDependencies.get(scope, varName);
          if (!dependency || !dependency.sourceCodeHook) return;
          dependency.sourceCodeHook.notifyDependencies(location);
        }

        static async findRegistrationLocation() {
          if (lively === undefined) return undefined;
          const stack = lively.stack();
          const frames = stack.frames;

          for (let frame of frames.slice()) {
            if (!frame.file.includes("active-expression") && !frame.file.includes("ContextJS") && !frame.file.includes("<anonymous>")) {
              return await frame.getSourceLocBabelStyle();
            }
          }

          const notificationFrame = frames.findIndex(frame => frame.func.includes(".notifyDependencies"));
          if (notificationFrame >= 0 && notificationFrame < frames.length - 1) {
            return await frames[notificationFrame + 1].getSourceLocBabelStyle();
          }
          // lively.warn("findRegistrationLocation problem", stack);
          return frames[0];
        }

      }

      /*
       * 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() {
        ContextAndIdentifierToDependencies.clear();
        DependenciesToAExprs.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 updateMember(obj, prop, location) {
        TracingHandler.memberUpdated(obj, prop, location);
      }

      _export('updateMember', updateMember);

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

      _export('setMember', setMember);

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

      _export('setMemberAddition', setMemberAddition);

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

      _export('setMemberSubtraction', setMemberSubtraction);

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

      _export('setMemberMultiplication', setMemberMultiplication);

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

      _export('setMemberDivision', setMemberDivision);

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

      _export('setMemberRemainder', setMemberRemainder);

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

      _export('setMemberExponentiation', setMemberExponentiation);

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

      _export('setMemberLeftShift', setMemberLeftShift);

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

      _export('setMemberRightShift', setMemberRightShift);

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

      _export('setMemberUnsignedRightShift', setMemberUnsignedRightShift);

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

      _export('setMemberBitwiseAND', setMemberBitwiseAND);

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

      _export('setMemberBitwiseXOR', setMemberBitwiseXOR);

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

      _export('setMemberBitwiseOR', setMemberBitwiseOR);

      function deleteMember(obj, prop, location) {
        const result = delete obj[prop];
        TracingHandler.memberUpdated(obj, prop, location);
        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, location) {
        scope[varName] = value;
        TracingHandler.localUpdated(scope, varName, location);
      }

      _export('setLocal', setLocal);

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

      _export('getGlobal', getGlobal);

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

      _export('setGlobal', setGlobal);

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