Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.864
diff -u -p -r1.864 common.inc
--- includes/common.inc	5 Feb 2009 01:21:16 -0000	1.864
+++ includes/common.inc	9 Feb 2009 00:51:15 -0000
@@ -3323,13 +3323,8 @@ function drupal_render(&$elements) {
     }
   }
 
-  // Sort the elements by weight if they have not been sorted elsewhere already,
-  // for example by a database query. Pre-sorted elements should have
-  // $elements['#sorted'] set to TRUE to avoid unnecessary calls to uasort().
-  if (empty($elements['#sorted'])) {
-    uasort($elements, 'element_sort');
-    $elements['#sorted'] = TRUE;
-  }
+  // Get the children of the element, sorted by weight.
+  $children = element_children($elements, TRUE);
 
   $elements['#children'] = '';
   // Call the element's #theme function if it is set. Then any children of the
@@ -3340,7 +3335,7 @@ function drupal_render(&$elements) {
   // If #theme was not set and the element has children, render them now
   // using drupal_render_children().
   if ($elements['#children'] == '') {
-    $elements['#children'] = drupal_render_children($elements);
+    $elements['#children'] = drupal_render_children($elements, $children);
   }
 
   // Let the theme function in #theme_wrapper add markup around the rendered
@@ -3474,16 +3469,37 @@ function element_child($key) {
 }
 
 /**
- * Get keys of a structured array tree element that are not properties (i.e., do not begin with '#').
+ * Return the children of an element, optionally sorted by weight.
+ *
+ * @param $elements
+ *   The element to be sorted.
+ * @param $sort
+ *   Boolean to indicate whether the children should be sorted by weight.
+ *
+ * @return
+ *   The array keys of the element's children.
  */
-function element_children($element) {
-  $keys = array();
-  foreach(array_keys($element) as $key) {
-    if ($key[0] !== '#') { 
-      $keys[] = $key;
+function element_children(&$element, $sort = FALSE) {
+  // Do not attempt to sort elements which have already been sorted.
+  $sort = isset($element['#sorted']) ? !$element['#sorted'] : $sort;
+
+  // Filter out properties from the element, leaving only children.
+  $children = array();
+  $sortable = FALSE;
+  foreach ($element as $key => $value) {
+    if ($key[0] !== '#') {
+      $children[$key] = $value;
+      if (is_array($value) && isset($value['#weight'])) {
+        $sortable = TRUE;
+      }
     }
   }
-  return $keys;
+  // Sort the element if necessary.
+  if ($sort && $sortable) {
+    uasort($children, 'element_sort');
+  }
+  $element['#sorted'] = TRUE;
+  return array_keys($children);
 }
 
 /**
Index: modules/simpletest/tests/common.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v
retrieving revision 1.25
diff -u -p -r1.25 common.test
--- modules/simpletest/tests/common.test	31 Jan 2009 19:07:45 -0000	1.25
+++ modules/simpletest/tests/common.test	9 Feb 2009 00:51:21 -0000
@@ -535,8 +535,28 @@ class DrupalRenderUnitTestCase extends D
       ),
     );
     $output = drupal_render($elements);
+
     // The lowest weight element should appear last in $output.
-    $this->assertTrue(strpos($output, $second) > strpos($output, $first), t('Elements were sorted correctly by weight'));
+    $this->assertTrue(strpos($output, $second) > strpos($output, $first), t('Elements were sorted correctly by weight.'));
+
+    // Confirm that the $elements array has '#sorted' set to TRUE.
+    $this->assertTrue($elements['#sorted'], t("'#sorted' => TRUE was added to the array"));
+
+    // Now the same array structure, but with #sorted set to TRUE.
+    $elements = array(
+      'second' => array(
+        '#weight' => 10,
+        '#markup' => $second,
+      ),
+      'first' => array(
+        '#weight' => 0,
+        '#markup' => $first,
+      ),
+      '#sorted' => TRUE,
+    );
+    $output = drupal_render($elements);
+    // The elements should appear in output in the same order as the array.
+    $this->assertTrue(strpos($output, $second) < strpos($output, $first), t('Elements were not sorted.'));
   }
 }
 
