Index: modules/field/field.attach.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.attach.inc,v
retrieving revision 1.11
diff -u -p -r1.11 field.attach.inc
--- modules/field/field.attach.inc	26 Apr 2009 09:18:20 -0000	1.11
+++ modules/field/field.attach.inc	30 Apr 2009 11:27:04 -0000
@@ -333,6 +333,26 @@ function _field_attach_load($obj_type, $
         $additions[$id][$key] = $value;
       }
 
+      // Invoke hook_field_sanitize() on the additions.
+      list(, , $bundle) = field_attach_extract_ids($obj_type, $object);
+      $instances = field_info_instances($bundle);
+
+      foreach ($instances as $instance) {
+        $field_name = $instance['field_name'];
+        $field = field_info_field($field_name);
+        $items = isset($object->$field_name) ? $object->$field_name : array();
+        foreach (module_implements('field_sanitize') as $module) {
+          $function = $module . '_field_sanitize';
+          $function($obj_type, $object, $field, $instance, $items);
+        }
+        // Put back the altered items into additions, if the field was present to
+        // begin with (avoid replacing missing field with empty array(), those are
+        // not semantically equivalent on update).
+        if (isset($additions[$id][$field_name])) {
+          $additions[$id][$field_name] = $items;
+        }
+      }
+
       // Invoke hook_field_attach_load(): let other modules act on loading the
       // object.
       // TODO : this currently doesn't get cached (we cache $additions).
@@ -625,7 +645,7 @@ function _field_attach_delete_revision($
  */
 function _field_attach_view($obj_type, &$object, $teaser = FALSE) {
   // Let field modules sanitize their data for output.
-  _field_invoke('sanitize', $obj_type, $object);
+  _field_invoke('sanitize_uncached', $obj_type, $object);
 
   $output = _field_invoke_default('view', $obj_type, $object, $teaser);
 
Index: modules/field/field.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.test,v
retrieving revision 1.14
diff -u -p -r1.14 field.test
--- modules/field/field.test	29 Apr 2009 21:33:00 -0000	1.14
+++ modules/field/field.test	30 Apr 2009 11:27:05 -0000
@@ -450,10 +450,10 @@ class FieldAttachTestCase extends Drupal
     field_attach_insert($cached_type, $entity);
     $this->assertFalse(cache_get($cid, 'cache_field'), 'Cached: no cache entry on save');
 
-    // Load, and confirm cache entry
+    // Load, and confirm cache entry.
     field_attach_load($cached_type, array(0 => $entity));
     $cache = cache_get($cid, 'cache_field');
-    $this->assertEqual($cache->data[$this->field_name], $values, 'Cached: correct cache entry on load');
+    $this->assertTrue($cache->data[$this->field_name], TRUE, 'Cached: entry was returned on load.');
 
     // Delete, and confirm no cache entry
     field_attach_delete($cached_type, $entity);
Index: modules/field/modules/text/text.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.module,v
retrieving revision 1.6
diff -u -p -r1.6 text.module
--- modules/field/modules/text/text.module	12 Apr 2009 02:18:51 -0000	1.6
+++ modules/field/modules/text/text.module	30 Apr 2009 11:27:05 -0000
@@ -105,21 +105,44 @@ function text_field_validate($obj_type, 
   }
 }
 
+/**
+ * Implementation of hook_field_sanitize().
+ */
 function text_field_sanitize($obj_type, $object, $field, $instance, &$items) {
   global $language;
   foreach ($items as $delta => $item) {
-    // TODO D7 : this code is really node-related.
+    $format = $item['format'];
     if (!empty($instance['settings']['text_processing'])) {
-      $check = is_null($object) || (isset($object->build_mode) && $object->build_mode == NODE_BUILD_PREVIEW);
-      $text = isset($item['value']) ? check_markup($item['value'], $item['format'], isset($object->language) ? $object->language : $language->language, $check) : '';
+      if (filter_format_allowcache($format)) {
+        $text = isset($item['value']) ? check_markup($item['value'], $format, isset($object->language) ? $object->language : $language->language, FALSE, TRUE) : '';
+      }
     }
     else {
       $text = check_plain($item['value']);
     }
-    $items[$delta]['safe'] = $text;
+    if (isset($text)) {
+      $items[$delta]['safe'] = $text;
+    }
+  }
+}
+
+/**
+ * Implementation of hook_field_sanitize_uncached().
+ */
+function text_field_sanitize_uncached($obj_type, $object, $field, $instance, &$items) {
+  global $language;
+  foreach ($items as $delta => $item) {
+    if (!isset($items[$delta]['safe'])) {
+      $format = $item['format'];
+      if (!empty($instance['settings']['text_processing'])) {
+        $text = isset($item['value']) ? check_markup($item['value'], $format, isset($object->language) ? $object->language : $language->language, FALSE, TRUE) : '';
+      }
+      $items[$delta]['safe'] = $text;
+    }
   }
 }
 
+
 /**
  * Implementation of hook_field_is_empty().
  */
Index: modules/filter/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v
retrieving revision 1.248
diff -u -p -r1.248 filter.module
--- modules/filter/filter.module	25 Apr 2009 18:01:10 -0000	1.248
+++ modules/filter/filter.module	30 Apr 2009 11:27:07 -0000
@@ -424,14 +424,14 @@ function filter_list_format($format) {
  *    showing content that is not (yet) stored in the database (eg. upon preview),
  *    set to TRUE so the user's permissions are checked.
  */
-function check_markup($text, $format = FILTER_FORMAT_DEFAULT, $langcode = '', $check = TRUE) {
+function check_markup($text, $format = FILTER_FORMAT_DEFAULT, $langcode = '', $check = TRUE, $skip_cache = FALSE) {
   // When $check = TRUE, do an access check on $format.
   if (isset($text) && (!$check || filter_access($format))) {
     $format = filter_resolve_format($format);
 
     // Check for a cached version of this piece of text.
     $cache_id = $format . ':' . $langcode . ':' . md5($text);
-    if ($cached = cache_get($cache_id, 'cache_filter')) {
+    if (!$skip_cache && $cached = cache_get($cache_id, 'cache_filter')) {
       return $cached->data;
     }
 
@@ -453,7 +453,7 @@ function check_markup($text, $format = F
     }
 
     // Store in cache with a minimum expiration time of 1 day.
-    if (filter_format_allowcache($format)) {
+    if (!$skip_cache && filter_format_allowcache($format)) {
       cache_set($cache_id, $text, 'cache_filter', REQUEST_TIME + (60 * 60 * 24));
     }
   }
