Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1024
diff -u -p -r1.1024 common.inc
--- includes/common.inc	17 Oct 2009 05:50:27 -0000	1.1024
+++ includes/common.inc	18 Oct 2009 05:07:46 -0000
@@ -5038,10 +5038,12 @@ function drupal_common_theme() {
     'html' => array(
       'arguments' => array('page' => NULL),
       'template' => 'html',
+      'render' => THEME_ELEMENT,
     ),
     'page' => array(
       'arguments' => array('page' => NULL),
       'template' => 'page',
+      'render' => THEME_ELEMENT,
     ),
     'region' => array(
       'arguments' => array('elements' => NULL),
@@ -5150,6 +5152,7 @@ function drupal_common_theme() {
     ),
     'menu_tree' => array(
       'arguments' => array('tree' => NULL),
+      'render' => THEME_ELEMENT,
     ),
     'menu_local_task' => array(
       'arguments' => array('element' => NULL),
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.537
diff -u -p -r1.537 theme.inc
--- includes/theme.inc	16 Oct 2009 08:27:40 -0000	1.537
+++ includes/theme.inc	18 Oct 2009 05:07:46 -0000
@@ -38,6 +38,30 @@ define('MARK_UPDATED', 2);
  */
 
 /**
+ * @name Render integration modes
+ * @{
+ * How theme() should map a renderable element to theme hook arguments.
+ * @see theme(), hook_theme()
+ */
+
+/**
+ * When theme() is passed a renderable element instead of a variables array,
+ * set the first theme hook argument to the element.
+ */
+define('THEME_ELEMENT', 1);
+
+/**
+ * When theme() is passed a renderable element instead of a variables array,
+ * set each argument to the value of the element's correspondingly named
+ * property.
+ */
+define('THEME_PROPERTIES', 2);
+
+/**
+ * @} End of "Render integration modes".
+ */
+
+/**
  * Determines if a theme is available to use.
  *
  * @param $theme
@@ -302,6 +326,7 @@ function drupal_theme_rebuild() {
  *   - 'arguments': The arguments for this theme hook as defined in
  *     hook_theme(). If there is more than one implementation and 'arguments' is
  *     not specified in a later one, then the previous definition is kept.
+ *   - 'render': How theme() should map a renderable element to hook arguments.
  *   - 'theme paths': The paths where implementations of a theme hook can be
  *     found. Its definition is similarly inherited like 'arguments'. Each time
  *     _theme_process_registry() is called for this theme hook, either the
@@ -371,6 +396,25 @@ function _theme_process_registry(&$cache
       if (!isset($info['arguments']) && isset($cache[$hook])) {
         $result[$hook]['arguments'] = $cache[$hook]['arguments'];
       }
+      // Same for 'render'.
+      if (!isset($info['render']) && isset($cache[$hook])) {
+        $result[$hook]['render'] = $cache[$hook]['render'];
+      }
+      // If render is left out, default it based on number and names of
+      // arguments. @see hook_theme().
+      if (!isset($result[$hook]['render'])) {
+        // In any case, allow property to be accessed without PHP notices.
+        $result[$hook]['render'] = NULL;
+        if (!empty($result[$hook]['arguments'])) {
+          $arg_keys = array_keys($result[$hook]['arguments']);
+          if (count($arg_keys) == 1 && in_array($arg_keys[0], array('element', 'elements', 'form'))) {
+            $result[$hook]['render'] = THEME_ELEMENT;
+          }
+          else {
+            $result[$hook]['render'] = THEME_PROPERTIES;
+          }
+        }
+      }
 
       // The following apply only to theming hooks implemented as templates.
       if (isset($info['template'])) {
@@ -779,23 +823,24 @@ function theme($hook, $variables = array
   }
 
   // If a renderable array is passed as $variables, then set $variables to
-  // what's expected by the theme hook. If the theme hook expects a single
-  // argument, set the renderable array as that argument. If the theme hook
-  // expects multiple arguments, set the properties of the renderable array as
-  // those arguments.
+  // what's expected by the theme hook.
   if (isset($variables['#theme']) || isset($variables['#theme_wrappers'])) {
     $element = $variables;
     $variables = array();
-    $n = count($info['arguments']);
-    if ($n == 1) {
+    if (!empty($info['arguments'])) {
       $arg_keys = array_keys($info['arguments']);
-      $variables[$arg_keys[0]] = $element;
-    }
-    elseif ($n > 1) {
-      foreach ($info['arguments'] as $name => $default) {
-        if (isset($element["#$name"])) {
-          $variables[$name] = $element["#$name"];
-        }
+      switch ($info['render']) {
+        case THEME_ELEMENT:
+          $variables[$arg_keys[0]] = $element;
+          break;
+
+        case THEME_PROPERTIES:
+          foreach ($arg_keys as $name) {
+            if (isset($element["#$name"])) {
+              $variables[$name] = $element["#$name"];
+            }
+          }
+          break;
       }
     }
   }
@@ -992,6 +1037,7 @@ function drupal_find_theme_functions($ca
             $templates[$new_hook] = array(
               'function' => $match,
               'arguments' => $info['arguments'],
+              'render' => $info['render'],
             );
           }
         }
@@ -1096,6 +1142,7 @@ function drupal_find_theme_templates($ca
             'template' => $file,
             'path' => dirname($files[$match]->uri),
             'arguments' => $info['arguments'],
+            'render' => $info['render'],
           );
         }
       }
Index: modules/book/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.module,v
retrieving revision 1.519
diff -u -p -r1.519 book.module
--- modules/book/book.module	15 Oct 2009 14:07:26 -0000	1.519
+++ modules/book/book.module	18 Oct 2009 05:07:46 -0000
@@ -27,6 +27,7 @@ function book_theme() {
     ),
     'book_all_books_block' => array(
       'arguments' => array('book_menus' => array()),
+      'render' => THEME_ELEMENT,
       'template' => 'book-all-books-block',
     ),
     'book_node_export_html' => array(
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.793
diff -u -p -r1.793 comment.module
--- modules/comment/comment.module	17 Oct 2009 05:50:28 -0000	1.793
+++ modules/comment/comment.module	18 Oct 2009 05:07:46 -0000
@@ -137,6 +137,7 @@ function comment_theme() {
     'comment_wrapper' => array(
       'template' => 'comment-wrapper',
       'arguments' => array('content' => NULL),
+      'render' => THEME_ELEMENT,
     ),
   );
 }
Index: modules/simpletest/simpletest.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.module,v
retrieving revision 1.77
diff -u -p -r1.77 simpletest.module
--- modules/simpletest/simpletest.module	9 Oct 2009 01:00:03 -0000	1.77
+++ modules/simpletest/simpletest.module	18 Oct 2009 05:07:46 -0000
@@ -76,6 +76,7 @@ function simpletest_theme() {
   return array(
     'simpletest_test_table' => array(
       'arguments' => array('table' => NULL),
+      'render' => THEME_ELEMENT,
       'file' => 'simpletest.pages.inc',
     ),
     'simpletest_result_summary' => array(
Index: modules/system/system.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v
retrieving revision 1.93
diff -u -p -r1.93 system.api.php
--- modules/system/system.api.php	16 Oct 2009 13:18:31 -0000	1.93
+++ modules/system/system.api.php	18 Oct 2009 05:07:46 -0000
@@ -853,8 +853,24 @@ function hook_permission() {
  *   value allows the theme layer to properly utilize templates. The
  *   array keys represent the name of the variable, and the value will be
  *   used as the default value if not specified to the theme() function.
- *   These arguments must be in the same order that they will be given to
- *   the theme() function.
+ *   Template implementations receive these arguments as variables in the
+ *   template file. Function implementations receive these arguments within the
+ *   $variables parameter.
+ * - render: (optional) How theme() should map a renderable element (called
+ *   with render()) to the arguments. Can be one of:
+ *   - THEME_ELEMENT: specifies that the element should be passed as the
+ *     variable corresponding to the first argument's name (see 'arguments').
+ *   - THEME_PROPERTIES: specifies that for each argument in 'arguments', the
+ *     element's property of the same name (except for with leading '#') should
+ *     be passed as that variable.
+ *   If this property is not specified, the theme system uses the following
+ *   logic to decide:
+ *   - If there is only 1 argument defined in 'arguments' and that argument is
+ *     named either 'element', 'elements', or 'form', then THEME_ELEMENT.
+ *   - Otherwise, THEME_PROPERTIES.
+ *   Because of this, it is encouraged that theme hooks intended to operate on
+ *   renderable elements be defined with 1 argument named 'element', 'elements',
+ *   or 'form'. Otherwise, set the 'render' entry to achieve desired results.
  * - file: The file the implementation resides in. This file will be included
  *   prior to the theme being rendered, to make sure that the function or
  *   preprocess function (as needed) is actually loaded; this makes it possible
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.820
diff -u -p -r1.820 system.module
--- modules/system/system.module	17 Oct 2009 05:50:29 -0000	1.820
+++ modules/system/system.module	18 Oct 2009 05:07:46 -0000
@@ -180,6 +180,7 @@ function system_theme() {
     ),
     'status_report' => array(
       'arguments' => array('requirements' => NULL),
+      'render' => THEME_ELEMENT,
       'file' => 'system.admin.inc',
     ),
     'admin_page' => array(
Index: modules/toolbar/toolbar.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/toolbar/toolbar.module,v
retrieving revision 1.14
diff -u -p -r1.14 toolbar.module
--- modules/toolbar/toolbar.module	17 Oct 2009 00:51:53 -0000	1.14
+++ modules/toolbar/toolbar.module	18 Oct 2009 05:07:46 -0000
@@ -24,6 +24,7 @@ function toolbar_permission() {
 function toolbar_theme($existing, $type, $theme, $path) {
   $items['toolbar'] = array(
     'arguments' => array('toolbar' => array()),
+    'render' => THEME_ELEMENT,
     'template' => 'toolbar',
     'path' => drupal_get_path('module', 'toolbar'),
   );
Index: modules/update/update.report.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/update/update.report.inc,v
retrieving revision 1.26
diff -u -p -r1.26 update.report.inc
--- modules/update/update.report.inc	15 Oct 2009 21:19:31 -0000	1.26
+++ modules/update/update.report.inc	18 Oct 2009 05:07:46 -0000
@@ -199,7 +199,7 @@ function theme_update_report($variables)
             break;
             
           default:
-            $base_themes[] = theme('placeholder', $base_theme);
+            $base_themes[] = theme('placeholder', array('text' => $base_theme));
         }
       }
       $row .= t('Depends on: !basethemes', array('!basethemes' => implode(', ', $base_themes)));
