Index: includes/token.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/token.inc,v
retrieving revision 1.7
diff -u -p -r1.7 token.inc
--- includes/token.inc	5 Dec 2009 03:49:17 -0000	1.7
+++ includes/token.inc	11 Jan 2010 22:37:39 -0000
@@ -78,6 +78,9 @@ function token_replace($text, array $dat
   $replacements = array();
   foreach (token_scan($text) as $type => $tokens) {
     $replacements += token_generate($type, $tokens, $data, $options);
+    if (!empty($options['clear'])) {
+      $replacements += array_fill_keys($tokens, '');
+    }
   }
 
   // Optionally alter the list of replacement values.
Index: modules/system/system.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.test,v
retrieving revision 1.102
diff -u -p -r1.102 system.test
--- modules/system/system.test	9 Jan 2010 23:03:21 -0000	1.102
+++ modules/system/system.test	11 Jan 2010 22:37:55 -0000
@@ -1237,7 +1237,7 @@ class SystemThemeFunctionalTest extends 
     $this->drupalPost('admin/appearance/settings', $edit, t('Save configuration'));
     $this->drupalGet('node');
     $this->assertRaw($file->uri, t('Logo path successfully changed.'));
-  
+
     // Upload a file to use for the logo.
     $file = current($this->drupalGetTestFiles('image'));
     $edit = array(
@@ -1422,18 +1422,23 @@ class TokenReplaceTestCase extends Drupa
     $source .= '[node:author:name]';   // Node author's name
     $source .= '[node:created:since]'; // Time since the node was created
     $source .= '[current-user:name]';  // Current user's name
-    $source .= '[user:name]';          // No user passed in, should be untouched
     $source .= '[date:short]';         // Short date format of REQUEST_TIME
-    $source .= '[bogus:token]';        // Nonexistent token, should be untouched
+    $source .= '[user:name]';          // No user passed in, should be untouched
+    $source .= '[bogus:token]';        // Nonexistent token
 
     $target  = check_plain($node->title);
     $target .= check_plain($account->name);
     $target .= format_interval(REQUEST_TIME - $node->created, 2, $language->language);
     $target .= check_plain($user->name);
-    $target .= '[user:name]';
     $target .= format_date(REQUEST_TIME, 'short', '', NULL, $language->language);
-    $target .= '[bogus:token]';
 
+    // Test that the clear parameter cleans out nonexistent tokens.
+    $result = token_replace($source, array('node' => $node), array('language' => $language, 'clear' => TRUE));
+    $result = $this->assertFalse(strcmp($target, $result), t('Basic placeholder tokens replaced.'));
+
+    // Test without using the clear parameter (nonexistant token untouched).
+    $target .= '[user:name]';
+    $target .= '[bogus:token]';
     $result = token_replace($source, array('node' => $node), array('language' => $language));
 
     // Check that the results of token_generate are sanitized properly. This does NOT
