Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.829
diff -u -r1.829 common.inc
--- includes/common.inc	22 Nov 2008 13:55:27 -0000	1.829
+++ includes/common.inc	23 Nov 2008 08:24:33 -0000
@@ -2143,7 +2143,9 @@
  * performed using this function:
  *
  * - Add a file ('file'):
- *   Adds a reference to a JavaScript file to the page.
+ *   Adds a reference to a JavaScript file to the page. This may either be a file
+ *   relative to base_path(), or the absolute path to a JavaScript file hosted
+ *   externally.
  *
  * - Add inline JavaScript code ('inline'):
  *   Executes a piece of JavaScript code on the current page by placing the code
@@ -2164,11 +2166,13 @@
  *   drupal_add_js('$(document).ready(function(){alert("Hello!");});',
  *     array('type' => 'inline', 'scope' => 'footer', 'weight' => 5)
  *   );
+ *   drupal_add_js('http://yui.yahooapis.com/2.6.0/build/utilities/utilities.js');
  * @endcode
  *
  * @param $data
  *   (optional) If given, the value depends on the $options parameter:
- *   - 'file': Path to the file relative to base_path().
+ *   - 'file': Path to the file relative to base_path(), or the absolute path
+ *       to a JavaScript file hosted externally.
  *   - 'inline': The JavaScript code that should be placed in the given scope.
  *   - 'setting': An array with configuration options as associative array. The
  *       array is directly placed in Drupal.settings. All modules should wrap
@@ -2379,7 +2383,10 @@
 
       case 'file':
         if (!$item['preprocess'] || !$is_writable || !$preprocess_js) {
-          $no_preprocess .= '<script type="text/javascript"' . ($item['defer'] ? ' defer="defer"' : '') . ' src="' . base_path() . $item['data'] . ($item['cache'] ? $query_string : '?' . REQUEST_TIME) . "\"></script>\n";
+          // Local JavaScript files require a base_path() prefix, while scripts
+          // that are hosted externally require not having any prefix at all.
+          $prefix = filter_var($item['data'], FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED) ? '' : base_path();
+          $no_preprocess .= '<script type="text/javascript"' . ($item['defer'] ? ' defer="defer"' : '') . ' src="' . $prefix . $item['data'] . ($item['cache'] ? $query_string : '?' . REQUEST_TIME) . "\"></script>\n";
         }
         else {
           $files[$item['data']] = $item;
@@ -2552,8 +2559,16 @@
     // Build aggregate JS file.
     foreach ($files as $path => $info) {
       if ($info['preprocess']) {
-        // Append a ';' after each JS file to prevent them from running together.
-        $contents .= file_get_contents($path) . ';';
+        // Local files are aggregated inline, while external scripts are loaded
+        // through JavaScript.
+        if (!filter_var($path, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)) {
+          // Append a ';' after each JS file to prevent them from running together.
+          $contents .= file_get_contents($path) . ';';
+        }
+        else {
+          // Use jQuery's getScript function to load the external script.
+          $contents .= '$.getScript("' . $path . '");';
+        }
       }
     }
 
Index: modules/simpletest/tests/common.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v
retrieving revision 1.14
diff -u -r1.14 common.test
--- modules/simpletest/tests/common.test	16 Nov 2008 15:19:34 -0000	1.14
+++ modules/simpletest/tests/common.test	23 Nov 2008 08:24:33 -0000
@@ -455,6 +455,17 @@
   }
 
   /**
+   * Test rendering an external JavaScript file.
+   */
+  function testRenderExternal() {
+    $external = 'http://yui.yahooapis.com/2.6.0/build/utilities/utilities.js';
+    drupal_add_js($external);
+    $javascript = drupal_get_js();
+    // Local files have a base_path() prefix, external files should not.
+    $this->assertTrue(strpos($javascript, 'src="' . $external) > 0, t('Rendering an external JavaScript file.'));
+  }
+
+  /**
    * Test drupal_get_js() with a footer scope.
    */
   function testFooterHTML() {
