diff --git a/viewfield.module b/viewfield.module
index d7278cc..cabe647 100644
--- a/viewfield.module
+++ b/viewfield.module
@@ -6,6 +6,17 @@
  */
 
 /**
+ * Implements hook_theme().
+ */
+function viewfield_theme() {
+  return array(
+    'viewfield_formatter_default' => array(
+      'render element' => 'element',
+    ),
+  );
+}
+
+/**
  * Implements hook_field_info().
  */
 function viewfield_field_info() {
@@ -119,16 +130,24 @@ function viewfield_field_formatter_info() {
  * Implements hook_field_formatter_view().
  */
 function viewfield_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
+  list($entity_id) = entity_extract_ids($entity_type, $entity);
   $elements = array();
   switch ($display['type']) {
     case 'viewfield_default':
       foreach ($items as $delta => $item) {
+        // @todo Store name and display separately.
+        list($view_name, $display) = explode('|', $item['vname'], 2);
         $elements[$delta] = array(
-          '#markup' => theme('viewfield_formatter_default', array(
-            'item' => $item,
-            'entity_type' => $entity_type,
-            'entity' => $entity,
-          )),
+          '#pre_render' => array('viewfield_pre_render'),
+          '#theme' => 'viewfield_formatter_default',
+          '#post_render' => array('viewfield_post_render'),
+          '#view_name' => $view_name,
+          '#view_display' => $display,
+          // @todo Store views arguments serialized.
+          '#view_arguments' => $item['vargs'],
+          '#entity_type' => $entity_type,
+          '#entity_id' => $entity_id,
+          '#entity' => $entity,
         );
       }
       break;
@@ -180,6 +199,68 @@ function theme_viewfield_formatter_default($variables) {
 }
 
 /**
+ * #pre_render callback for a viewfield field.
+ *
+ * @see viewfield_field_formatter_view()
+ * @see viewfield_post_render()
+ */
+function viewfield_pre_render($element) {
+  $stack = &drupal_static('viewfield_stack', array());
+
+  // During previews of new entities, there is no entity ID yet, and thus, also
+  // no recursion to prevent.
+  if (empty($element['#entity_id'])) {
+    return $element;
+  }
+
+  // Abort rendering in case of recursion.
+  if (isset($stack[$element['#entity_type']][$element['#entity_id']])) {
+    $element['#printed'] = TRUE;
+  }
+  // Otherwise, add the rendered entity to the stack to prevent recursion.
+  else {
+    $stack[$element['#entity_type']][$element['#entity_id']] = TRUE;
+  }
+  return $element;
+}
+
+/**
+ * #post_render callback for a viewfield field.
+ *
+ * @see viewfield_pre_render()
+ * @see viewfield_field_formatter_view()
+ */
+function viewfield_post_render($element) {
+  $stack = &drupal_static('viewfield_stack', array());
+
+  unset($stack[$element['#entity_type']][$element['#entity_id']]);
+
+  return $element;
+}
+
+/**
+ * Return HTML for a view in a field.
+ *
+ * @see views_embed_view()
+ */
+function theme_viewfield_formatter_default($variables) {
+  $element = $variables['element'];
+
+  // @todo Move load + access check into #pre_render or viewfield_field_formatter_view()?
+  $view = views_get_view($element['#view_name']);
+  if ($view && $view->access($element['#view_display'])) {
+    // Override the view's path to the current path. Otherwise, exposed views
+    // filters would submit to the front page.
+    $view->override_path = $_GET['q'];
+
+    $view_args = _viewfield_get_view_args($element['#view_arguments'], $element['#entity_type'], $element['#entity']);
+
+    // Only return an actual view result to not break empty value behavior.
+    return $view->preview($element['#view_display'], $view_args);
+  }
+}
+
+/**
  * Implements hook_field_widget_info().
  */
 function viewfield_field_widget_info() {
@@ -287,21 +368,6 @@ function _viewfield_potential_references($field, $instance) {
 }
 
 /**
- * Implements hook_theme().
- */
-function viewfield_theme() {
-  return array(
-    'viewfield_formatter_default' => array(
-      'variables' => array(
-        'item' => NULL,
-        'entity_type' => NULL,
-        'entity' => NULL,
-      ),
-    ),
-  );
-}
-
-/**
  * Perform argument replacement
  */
 function _viewfield_get_view_args($vargs, $entity_type, $entity) {
