Index: includes/ajax.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/ajax.inc,v
retrieving revision 1.11
diff -u -p -r1.11 ajax.inc
--- includes/ajax.inc	21 Sep 2009 08:54:57 -0000	1.11
+++ includes/ajax.inc	21 Sep 2009 17:42:00 -0000
@@ -259,7 +259,7 @@ function ajax_form_callback() {
  *   None. Additional code is added to the header of the page using
  *   drupal_add_js().
  */
-function ajax_process_form($element) {
+function ajax_process_form($element, &$form_state) {
   $js_added = &drupal_static(__FUNCTION__, array());
 
   // Add a reasonable default event handler if none was specified.
@@ -329,7 +329,7 @@ function ajax_process_form($element) {
     drupal_add_js(array('ajax' => array($element['#id'] => $ajax_binding)), 'setting');
 
     $js_added[$element['#id']] = TRUE;
-    $element['#cache'] = TRUE;
+    $form_state['cache'] = TRUE;
   }
   return $element;
 }
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.375
diff -u -p -r1.375 form.inc
--- includes/form.inc	21 Sep 2009 06:44:13 -0000	1.375
+++ includes/form.inc	21 Sep 2009 17:56:50 -0000
@@ -106,7 +106,9 @@ function drupal_get_form($form_id) {
  *     can have unexpected effects. The 'get' method should only be used on
  *     forms that do not change data, as that is exclusively the domain of post.
  *   - no_redirect: If set to TRUE the form will NOT perform a drupal_goto(),
- *     even if a redirect is set.
+ *     even if 'redirect' is set.
+ *   - no_cache: If set to TRUE the form will NOT be cached, even if 'cache' is
+ *     set.
  *   - always_process: If TRUE and the method is GET, a form_id is not
  *     necessary. This should only be used on RESTful GET forms that do NOT
  *     write data, as this could lead to security issues. It is useful so that
@@ -185,7 +187,7 @@ function drupal_build_form($form_id, &$f
 
       drupal_prepare_form($form_id, $form, $form_state);
       // Store a copy of the unprocessed form for caching and indicate that it
-      // is cacheable if #cache will be set.
+      // is cacheable in case $form_state['cache'] is set.
       $original_form = $form;
       $cacheable = TRUE;
     }
@@ -197,9 +199,11 @@ function drupal_build_form($form_id, &$f
     // reference.
     drupal_process_form($form_id, $form, $form_state);
 
-    if ($cacheable && !empty($form_state['cache']) && empty($form['#no_cache'])) {
-      // Caching is done past drupal_process_form so #process callbacks can
-      // set #cache.
+    // After processing the form, the form builder or a #process callback may
+    // have set $form_state['cache'] to indicate that the original form and the
+    // $form_state shall be cached. But the form may only be cached if the
+    // special 'no_cache' property is not set to TRUE.
+    if ($cacheable && !empty($form_state['cache']) && empty($form_state['no_cache'])) {
       form_set_cache($form_build_id, $original_form, $form_state);
     }
   }
@@ -294,7 +298,7 @@ function drupal_rebuild_form($form_id, &
   $form['#build_id'] = $form_build_id;
   drupal_prepare_form($form_id, $form, $form_state);
 
-  if (empty($form['#no_cache'])) {
+  if (empty($form_state['no_cache'])) {
     // We cache the form structure so it can be retrieved later for validation.
     // If $form_state['storage'] is populated, we also cache it so that it can
     // be used to resume complex multi-step processes.
@@ -1123,12 +1127,6 @@ function form_builder($form_id, $element
     unset($form_state['buttons']);
   }
 
-  // If some callback set #cache, we need to flip a flag so later it
-  // can be found.
-  if (!empty($element['#cache'])) {
-    $form_state['cache'] = $element['#cache'];
-  }
-
   // If there is a file element, we need to flip a flag so later the
   // form encoding can be set.
   if (isset($element['#type']) && $element['#type'] == 'file') {
Index: modules/book/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.module,v
retrieving revision 1.514
diff -u -p -r1.514 book.module
--- modules/book/book.module	18 Sep 2009 10:54:20 -0000	1.514
+++ modules/book/book.module	21 Sep 2009 17:33:49 -0000
@@ -356,8 +356,7 @@ function book_get_books() {
  * @see book_pick_book_submit()
  * @see book_submit()
  */
-function book_form_alter(&$form, $form_state, $form_id) {
-
+function book_form_alter(&$form, &$form_state, $form_id) {
   if (!empty($form['#node_edit_form'])) {
     // Add elements to the node form.
     $node = $form['#node'];
@@ -371,7 +370,7 @@ function book_form_alter(&$form, $form_s
     }
 
     if ($access) {
-      _book_add_form_elements($form, $node);
+      _book_add_form_elements($form, $form_state, $node);
       $form['book']['pick-book'] = array(
         '#type' => 'submit',
         '#value' => t('Change book (update list of parents)'),
@@ -435,9 +434,9 @@ function _book_parent_select($book_link)
 /**
  * Build the common elements of the book form for the node and outline forms.
  */
-function _book_add_form_elements(&$form, $node) {
+function _book_add_form_elements(&$form, &$form_state, $node) {
   // Need this for AJAX.
-  $form['#cache'] = TRUE;
+  $form_state['cache'] = TRUE;
 
   $form['book'] = array(
     '#type' => 'fieldset',
Index: modules/book/book.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.pages.inc,v
retrieving revision 1.16
diff -u -p -r1.16 book.pages.inc
--- modules/book/book.pages.inc	18 Sep 2009 00:12:45 -0000	1.16
+++ modules/book/book.pages.inc	21 Sep 2009 17:34:04 -0000
@@ -117,7 +117,7 @@ function book_outline_form($form, &$form
   }
   $form['#node'] = $node;
   $form['#id'] = 'book-outline';
-  _book_add_form_elements($form, $node);
+  _book_add_form_elements($form, $form_state, $node);
 
   $form['book']['#collapsible'] = FALSE;
 
Index: modules/menu/menu.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v
retrieving revision 1.204
diff -u -p -r1.204 menu.module
--- modules/menu/menu.module	18 Sep 2009 00:04:22 -0000	1.204
+++ modules/menu/menu.module	21 Sep 2009 17:34:47 -0000
@@ -398,10 +398,10 @@ function _menu_parent_depth_limit($item)
 /**
  * Implement hook_form_alter(). Adds menu item fields to the node form.
  */
-function menu_form_alter(&$form, $form_state, $form_id) {
+function menu_form_alter(&$form, &$form_state, $form_id) {
   if (!empty($form['#node_edit_form'])) {
-    // Note - doing this to make sure the delete checkbox stays in the form.
-    $form['#cache'] = TRUE;
+    // Make sure the delete checkbox stays in the form.
+    $form_state['cache'] = TRUE;
 
     $form['menu'] = array(
       '#type' => 'fieldset',
Index: modules/poll/poll.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v
retrieving revision 1.314
diff -u -p -r1.314 poll.module
--- modules/poll/poll.module	21 Sep 2009 08:54:57 -0000	1.314
+++ modules/poll/poll.module	21 Sep 2009 17:36:37 -0000
@@ -211,16 +211,14 @@ function poll_field_extra_fields($bundle
 /**
  * Implement hook_form().
  */
-function poll_form($node, $form_state) {
+function poll_form($node, &$form_state) {
   global $user;
 
   $admin = user_access('administer nodes') || user_access('edit any poll content') || (user_access('edit own poll content') && $user->uid == $node->uid);
 
   $type = node_type_get_type($node);
 
-  $form = array(
-    '#cache' => TRUE,
-  );
+  $form_state['cache'] = TRUE;
 
   $form['title'] = array(
     '#type' => 'textfield',
@@ -653,7 +651,7 @@ function poll_view_voting($form, &$form_
 
   // Set form caching because we could have multiple of these forms on
   // the same page, and we want to ensure the right one gets picked.
-  $form['#cache'] = TRUE;
+  $form_state['cache'] = TRUE;
 
   // Provide a more cleanly named voting form theme.
   $form['#theme'] = 'poll_vote';
@@ -838,6 +836,8 @@ function template_preprocess_poll_bar(&$
  * @see poll_cancel()
  */
 function poll_cancel_form($form, &$form_state, $nid) {
+  $form_state['cache'] = TRUE;
+
   // Store the nid so we can get to it in submit functions.
   $form['#nid'] = $nid;
 
@@ -847,8 +847,6 @@ function poll_cancel_form($form, &$form_
     '#submit' => array('poll_cancel')
   );
 
-  $form['#cache'] = TRUE;
-
   return $form;
 }
 
Index: modules/simpletest/tests/form.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v
retrieving revision 1.15
diff -u -p -r1.15 form.test
--- modules/simpletest/tests/form.test	18 Sep 2009 00:12:48 -0000	1.15
+++ modules/simpletest/tests/form.test	21 Sep 2009 17:37:13 -0000
@@ -424,7 +424,7 @@ class FormsFormStorageTestCase extends D
   }
 
   /**
-   * Tests using the form with an activated #cache property.
+   * Tests using the form with an activated $form_state['cache'] property.
    */
   function testFormCached() {
     $user = $this->drupalCreateUser(array('access content'));
Index: modules/simpletest/tests/form_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v
retrieving revision 1.9
diff -u -p -r1.9 form_test.module
--- modules/simpletest/tests/form_test.module	18 Sep 2009 00:12:48 -0000	1.9
+++ modules/simpletest/tests/form_test.module	21 Sep 2009 17:37:36 -0000
@@ -342,7 +342,7 @@ function form_storage_test_form($form, &
   if (isset($_REQUEST['cache'])) {
     // Manually activate caching, so we can test that the storage keeps working
     // when it's enabled.
-    $form['#cache'] = TRUE;
+    $form_state['cache'] = TRUE;
   }
 
   return $form;
Index: modules/upload/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v
retrieving revision 1.259
diff -u -p -r1.259 upload.module
--- modules/upload/upload.module	21 Sep 2009 07:56:09 -0000	1.259
+++ modules/upload/upload.module	21 Sep 2009 17:40:31 -0000
@@ -210,7 +210,7 @@ function upload_node_form_submit(&$form,
   }
 }
 
-function upload_form_alter(&$form, $form_state, $form_id) {
+function upload_form_alter(&$form, &$form_state, $form_id) {
   if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
     $form['workflow']['upload'] = array(
       '#type' => 'radios',
@@ -256,7 +256,7 @@ function upload_form_alter(&$form, $form
         }
       }
       else {
-        $form['attachments']['wrapper'] += _upload_form($node);
+        $form['attachments']['wrapper'] += _upload_form($node, $form_state);
       }
       $form['#submit'][] = 'upload_node_form_submit';
     }
@@ -527,12 +527,12 @@ function upload_save($node) {
   }
 }
 
-function _upload_form($node) {
+function _upload_form($node, &$form_state) {
   global $user;
 
+  $form_state['cache'] = TRUE;
   $form = array(
     '#theme' => 'upload_form_new',
-    '#cache' => TRUE,
     '#prefix' => '<div id="attach-wrapper">',
     '#suffix' => '</div>',
   );
@@ -665,7 +665,7 @@ function upload_js() {
 
   $node->files = $files;
 
-  $form = _upload_form($node);
+  $form = _upload_form($node, $form_state);
 
   unset($cached_form['attachments']['wrapper']['new']);
   $cached_form['attachments']['wrapper'] = array_merge($cached_form['attachments']['wrapper'], $form);
