Index: includes/ajax.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/ajax.inc,v
retrieving revision 1.32
diff -u -p -r1.32 ajax.inc
--- includes/ajax.inc	13 Sep 2010 01:09:25 -0000	1.32
+++ includes/ajax.inc	17 Sep 2010 23:08:21 -0000
@@ -238,6 +238,7 @@ function ajax_get_form() {
 
   // Since some of the submit handlers are run, redirects need to be disabled.
   $form_state['no_redirect'] = TRUE;
+  $form_state['rebuild'] = TRUE;
 
   // When a form is rebuilt after AJAX processing, its #build_id and #action
   // should not change.
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.493
diff -u -p -r1.493 form.inc
--- includes/form.inc	16 Sep 2010 20:14:49 -0000	1.493
+++ includes/form.inc	18 Sep 2010 01:33:25 -0000
@@ -321,8 +321,11 @@ function drupal_build_form($form_id, &$f
     // - temporary: Any assigned data is expected to survives within the same
     //   page request.
     if ($check_cache) {
-      $uncacheable_keys = array_flip(array_diff(form_state_keys_no_cache(), array('always_process', 'temporary')));
-      $form_state = array_diff_key($form_state, $uncacheable_keys);
+      $uncacheable_keys = array_diff(form_state_keys_no_cache(), array('always_process', 'temporary'));
+      // Don't break $form_state reference.
+      foreach ($uncacheable_keys as $key) {
+        unset($form_state[$key]);
+      }
       $form_state += $form_state_before_retrieval;
     }
   }
@@ -753,7 +756,7 @@ function drupal_process_form($form_id, &
     // browser don't increment all the element IDs needlessly.
     drupal_static_reset('drupal_html_id');
 
-    if ($form_state['submitted'] && !form_get_errors() && !$form_state['rebuild']) {
+    if ($form_state['submitted'] && !form_get_errors()) {
       // Execute form submit handlers.
       form_execute_handlers('submit', $form, $form_state);
 
@@ -769,7 +772,7 @@ function drupal_process_form($form_id, &
       // possibly ending execution. We make sure we do not react to the batch
       // that is already being processed (if a batch operation performs a
       // drupal_form_submit).
-      if ($batch =& batch_get() && !isset($batch['current_set'])) {
+      if ($batch = &batch_get() && !isset($batch['current_set'])) {
         // Store $form_state information in the batch definition.
         // We need the full $form_state when either:
         // - Some submit handlers were saved to be called during batch
Index: misc/ajax.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/ajax.js,v
retrieving revision 1.18
diff -u -p -r1.18 ajax.js
--- misc/ajax.js	25 Jun 2010 20:34:07 -0000	1.18
+++ misc/ajax.js	18 Sep 2010 01:30:41 -0000
@@ -108,7 +108,7 @@ Drupal.ajax = function (base, element, e
   // Replacing 'nojs' with 'ajax' in the URL allows for an easy method to let
   // the server detect when it needs to degrade gracefully.
   this.url = element_settings.url.replace(/\/nojs(\/|$)/g, '/ajax$1');
-  this.wrapper = '#' + element_settings.wrapper;
+  this.wrapper = '#' + (element_settings.wrapper || (this.element.form ? this.element.form.id : base));
 
   // If there isn't a form, jQuery.ajax() will be used instead, allowing us to
   // bind AJAX to links as well.
@@ -249,7 +249,7 @@ Drupal.ajax.prototype.success = function
 
   Drupal.freezeHeight();
 
-  for (i in response) {
+  for (var i in response) {
     if (response[i]['command'] && this.commands[response[i]['command']]) {
       this.commands[response[i]['command']](this, response[i], status);
     }
Index: modules/simpletest/tests/form_test.file.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.file.inc,v
retrieving revision 1.1
diff -u -p -r1.1 form_test.file.inc
--- modules/simpletest/tests/form_test.file.inc	17 Jul 2010 18:52:39 -0000	1.1
+++ modules/simpletest/tests/form_test.file.inc	18 Sep 2010 01:32:37 -0000
@@ -13,12 +13,17 @@
 function form_test_load_include_menu($form, &$form_state) {
   // Submit the form via AJAX. That way the FAPI has to care about including
   // the file specified in hook_menu().
+  $form['ajax_wrapper'] = array(
+    '#type' => 'container',
+    '#id' => 'ajax-wrapper',
+  );
   $form['button'] = array(
     '#type' => 'submit',
     '#value' => t('Save'),
     '#submit' => array('form_test_load_include_submit'),
     '#ajax' => array(
       'callback' => 'form_test_load_include_menu_ajax',
+      'wrapper' => 'ajax-wrapper',
     ),
   );
   return $form;
@@ -35,6 +40,6 @@ function form_test_load_include_submit($
  * Ajax callback for the file inclusion via menu test. We don't need to return
  * anything as the messages are added automatically.
  */
-function form_test_load_include_menu_ajax($form) {
-  return '';
+function form_test_load_include_menu_ajax($form, $form_state) {
+  return $form['ajax_wrapper'];
 }
Index: modules/simpletest/tests/form_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v
retrieving revision 1.48
diff -u -p -r1.48 form_test.module
--- modules/simpletest/tests/form_test.module	27 Aug 2010 11:54:32 -0000	1.48
+++ modules/simpletest/tests/form_test.module	17 Sep 2010 22:17:20 -0000
@@ -11,118 +11,103 @@
  */
 function form_test_menu() {
   $items['form-test/alter'] = array(
-    'title' => 'Form altering test',
+    'title' => 'Alter',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_test_alter_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
   $items['form-test/validate'] = array(
-    'title' => 'Form validation handlers test',
+    'title' => 'Validation handlers',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_test_validate_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
   $items['form-test/limit-validation-errors'] = array(
-    'title' => 'Form validation with some error suppression',
+    'title' => 'Limit validation errors',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_test_limit_validation_errors_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
 
   $items['form_test/tableselect/multiple-true'] = array(
-    'title' => 'Tableselect checkboxes test',
+    'title' => 'Tableselect checkboxes',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('_form_test_tableselect_multiple_true_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
   $items['form_test/tableselect/multiple-false'] = array(
-    'title' => 'Tableselect radio button test',
+    'title' => 'Tableselect radio button',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('_form_test_tableselect_multiple_false_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
   $items['form_test/tableselect/empty-text'] = array(
-    'title' => 'Tableselect empty text test',
+    'title' => 'Tableselect empty text',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('_form_test_tableselect_empty_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
   $items['form_test/tableselect/advanced-select'] = array(
-    'title' => 'Tableselect js_select tests',
+    'title' => 'Tableselect js_select',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('_form_test_tableselect_js_select_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
 
   $items['form_test/form-storage'] = array(
-    'title' => 'Form storage test',
+    'title' => 'Form storage',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_test_storage_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
 
   $items['form_test/wrapper-callback'] = array(
-    'title' => 'Form wrapper callback test',
+    'title' => 'Wrapper callback',
     'page callback' => 'form_test_wrapper_callback',
     'page arguments' => array('form_test_wrapper_callback_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
 
   $items['form_test/form-state-values-clean'] = array(
-    'title' => 'Form state values clearance test',
+    'title' => 'Form state values clearance',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_test_form_state_values_clean_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
 
   $items['form-test/checkbox'] = array(
-    'title' => t('Form test'),
+    'title' => 'Checkboxes',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('_form_test_checkbox'),
     'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
   );
 
   $items['form-test/disabled-elements'] = array(
-    'title' => t('Form test'),
+    'title' => 'Disabled elements',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('_form_test_disabled_elements'),
     'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
   );
 
   $items['form-test/input-forgery'] = array(
-    'title' => t('Form test'),
+    'title' => 'Input forgery',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('_form_test_input_forgery'),
     'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
   );
 
   $items['form-test/form-rebuild-preserve-values'] = array(
-    'title' => 'Form values preservation during rebuild test',
+    'title' => 'Value preservation during rebuild',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_test_form_rebuild_preserve_values_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
 
   $items['form_test/form-labels'] = array(
-    'title' => 'Form label test',
+    'title' => 'Labels',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_label_test_form'),
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
+    'access callback' => TRUE,
   );
 
   $items['form-test/state-persist'] = array(
@@ -130,15 +115,13 @@ function form_test_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_test_state_persist'),
     'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
   );
 
   $items['form-test/clicked-button'] = array(
-    'title' => 'Clicked button test',
+    'title' => 'Clicked button',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_test_clicked_button'),
     'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
   );
 
   if (module_exists('node')) {
@@ -149,25 +132,21 @@ function form_test_menu() {
       'access arguments' => array('create', 'page'),
       'file path' => drupal_get_path('module', 'node'),
       'file' => 'node.pages.inc',
-      'type' => MENU_CALLBACK,
     );
   }
 
   $items['form-test/load-include-menu'] = array(
-    'title' => 'FAPI test loading includes',
+    'title' => 'Include files (menu)',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_test_load_include_menu'),
     'access callback' => TRUE,
     'file' => 'form_test.file.inc',
-    'type' => MENU_CALLBACK,
   );
-
   $items['form-test/load-include-custom'] = array(
-    'title' => 'FAPI test loading includes',
+    'title' => 'Include files (custom)',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('form_test_load_include_custom'),
     'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
   );
 
   return $items;
