System.register(['utils'], function (_export, _context) {
  "use strict";

  var PausableLoop;
  return {
    setters: [function (_utils) {
      PausableLoop = _utils.PausableLoop;
    }],
    execute: function () {

      const REMOVE_LISTENER_BY_CHECK_FUNCTION = new Map(); // nodeDetachedFromDOM -> removeListener

      function removeObsoleteListeners() {
        Array.from(REMOVE_LISTENER_BY_CHECK_FUNCTION).forEach(([nodeDetachedFromDOM, removeListener]) => {
          if (nodeDetachedFromDOM()) {
            removeListener();
            REMOVE_LISTENER_BY_CHECK_FUNCTION.delete(nodeDetachedFromDOM);
          }
        });
        if (REMOVE_LISTENER_BY_CHECK_FUNCTION.size === 0) {
          removeLoop.pause();
        }
      }

      // `this` is an ActiveExpression 
      function toDOMNode(builder = x => x) {
        const { value } = this.evaluateToCurrentValue();
        let currentNode = builder(value);

        function updateDOMNode(val) {
          // lively.notify("change aexpr result", val)
          const newNode = builder(val);
          currentNode.replaceWith(newNode);
          currentNode = newNode;
        };

        function nodeDetachedFromDOM() {
          return currentNode.getRootNode({ composed: true }) !== document;
        }

        const removeListener = () => this.offChange(updateDOMNode);

        this.onChange(updateDOMNode);

        REMOVE_LISTENER_BY_CHECK_FUNCTION.set(nodeDetachedFromDOM, removeListener);
        removeLoop.ensureRunning();

        return currentNode;
      }

      _export('toDOMNode', toDOMNode);

      const removeLoop = new PausableLoop(removeObsoleteListeners);

      function __unload__() {
        removeLoop.pause();
        //cancelAnimationFrame(checkRequest);
        // lively.notify("unload module", "UI AEXPR", undefined, null, "red");
      }

      _export('__unload__', __unload__);
    }
  };
});