 (defn- dom-node? [x]
   (and x (> (.-nodeType x) 0)))
 
+(defn managed? [elem]
+  (if (get-element-state elem) true false))
+
+(defn- ensure-unmanaged [elem]
+  (assert (dom-node? elem))
+  (assert (not (managed? elem)))
+  elem)
+
+(defn wrap-unmanaged-node [dom-node on-dispose]
+  (ensure-unmanaged dom-node)
+  (let [state (UnmanagedDOMNode. dom-node on-dispose nil)]
+    (set! (.-freactive-state dom-node) state)
+    state))
+
 (defn- as-velem [elem-spec]
   (cond
     (string? elem-spec)
     (DOMTextNode. elem-spec nil nil)
 
     (dom-node? elem-spec)
-    (UnmanagedDOMNode. elem-spec nil)
+    (if-let [state (get-element-state elem-spec)]
+      state
+      (UnmanagedDOMNode. elem-spec nil nil))
 
     (vector? elem-spec)
     (let [tag (first elem-spec)]

    (assert (instance? DOMElement velem) "Not a managed DOM element.")
    velem))

(defn managed? [elem]
  (or (get-element-state elem) (.-freactive-root elem)))

(defn- ensure-unmanaged [elem]
  (assert (dom-node? elem))
  (when (managed? elem) 
    (throw
     (ex-info
      "Can't safely do manual DOM manipulation within the managed element tree. Please do manual DOM manipulation only on top-level managed elements."
      {:managed-element elem}))))

(deftype RootElement [^:mutable root])

(defn- create-or-find-root-node [id]
  (if-let [root-node (.getElementById js/document id)]
    root-node
    (let [root-node (.createElement js/document "div")]
      (set! (.-id root-node) id)
      (.appendChild (.-body js/document) root-node))))

(defn- configure-root! [vroot root-node vdom]
  (set! (.-root vroot) (ui/velem-insert (as-velem vdom) (as-velem root-node) nil)))

(defn set-attrs!
  "Sets the attributes on a managed element to the new-attrs map
(unsetting previous values if not present in the new map)."

  (let [velem (get-managed-dom-element elem)]
    (.updateAttrs velem (apply f (.-attrs velem) args))))

(defn- find-by-id [id]
  (.getElementById js/document id))

(defn- create-or-find-root-node [id]
  (if-let [root-node (find-by-id id)]
    root-node
    (let [root-node (.createElement js/document "div")]
      (set! (.-id root-node) id)
      (.appendChild (.-body js/document) root-node))))

(defn- configure-root! [vroot vdom]
  (let [root (ui/velem-insert (as-velem vdom) vroot nil)]
    (set! (.-root vroot) root)
    (set! (.-on-dispose vroot) (fn [] (r/dispose root)))))

(defn mount! [mount-point vdom]
  "Makes the specified mount-point the root of a managed element tree, replacing
