diff --git includes/common.inc includes/common.inc
index 0b4f12a..3070cd5 100644
--- includes/common.inc
+++ includes/common.inc
@@ -2635,8 +2635,9 @@ function drupal_add_html_head_link($attributes, $header = FALSE) {
  *   (optional) A string defining the 'type' of CSS that is being added in the
  *   $data parameter ('file', 'inline', or 'external'), or an array which can
  *   have any or all of the following keys:
- *   - 'type': The type of stylesheet being added. Available options are 'file',
- *     'inline' or 'external'. Defaults to 'file'.
+ *   - 'type': The type of stylesheet being added. Available options are
+ *     'library','file', 'inline' or 'external'. Defaults to 'file'. Type
+ *     'library' is never aggregated and appears above other CSS.
  *   - 'weight': The weight of the stylesheet specifies the order in which the
  *     CSS will appear when presented on the page. Available constants are:
  *     - CSS_SYSTEM: Any system-layer CSS.
@@ -2735,7 +2736,7 @@ function drupal_get_css($css = NULL) {
   // browser-caching. The string changes on every update or full cache
   // flush, forcing browsers to load a new copy of the files, as the
   // URL changed.
-  $query_string = '?' . substr(variable_get('css_js_query_string', '0'), 0, 1);
+  $default_query_string = '?' . substr(variable_get('css_js_query_string', '0'), 0, 2);
 
   // Allow modules to alter the css items.
   drupal_alter('css', $css);
@@ -2771,6 +2772,12 @@ function drupal_get_css($css = NULL) {
   $external_css = '';
   $preprocess_items = array();
   foreach ($css as $data => $item) {
+    if (empty($item['version'])) {
+      $query_string = $default_query_string;
+    }
+    else {
+      $query_string = '?v=' . $item['version'];
+    }
     // Loop through each of the stylesheets, including them appropriately based
     // on their type.
     switch ($item['type']) {
@@ -2789,6 +2796,12 @@ function drupal_get_css($css = NULL) {
           $rendered_css['preprocess'] = '';
         }
         break;
+      case 'library':
+        $element = $css_element;
+        $element['#attributes']['media'] = $item['media'];
+        $element['#attributes']['href'] = file_create_url($item['data']) . $query_string;
+        $rendered_css[] = theme('html_tag', array('element' => $element));
+        break;
       case 'inline':
         // Include inline stylesheets.
         $inline_css .= drupal_load_stylesheet_content($item['data'], $item['preprocess']);
@@ -2809,8 +2822,8 @@ function drupal_get_css($css = NULL) {
       // starting with "ad*".
       $element = $css_element;
       $element['#attributes']['media'] = $media;
-      $filename = 'css_' . md5(serialize($items) . $query_string) . '.css';
-      $element['#attributes']['href'] = file_create_url(drupal_build_css_cache($items, $filename));
+      $filename = 'css_' . md5(serialize($items)) . '.css';
+      $element['#attributes']['href'] = file_create_url(drupal_build_css_cache($items, $filename)) . $default_query_string;
       $rendered_css['preprocess'] .= theme('html_tag', array('element' => $element));
     }
   }
@@ -3164,8 +3177,9 @@ function drupal_region_class($region) {
  *   always pass the string 'setting' only.
  *   - type
  *       The type of JavaScript that is to be added to the page. Allowed
- *       values are 'file', 'inline', 'external' or 'setting'. Defaults
- *       to 'file'.
+ *       values are 'library', 'file', 'inline', 'external' or 'setting'.
+ *       Defaults to 'file'. Type 'library' is never aggregated and will
+ *       appear before all JavaScript of type 'file'.
  *   - scope
  *       The location in which you want to place the script. Possible values
  *       are 'header' or 'footer'. If your theme implements different regions,
@@ -3199,6 +3213,10 @@ function drupal_region_class($region) {
  *       Aggregate the JavaScript if the JavaScript optimization setting has
  *       been toggled in admin/config/development/performance. Note that
  *       JavaScript of type 'external' is not aggregated. Defaults to TRUE.
+ *   - version
+ *       If not empty, the version is added as a query string insead of the
+ *       incremental query string that changes on cache clearing. Primarily
+ *       used for libraries.
  * @return
  *   The constructed array of JavaScript files.
  * @see drupal_get_js()
@@ -3239,12 +3257,11 @@ function drupal_add_js($data = NULL, $options = NULL) {
         ),
         'misc/drupal.js' => array(
           'data' => 'misc/drupal.js',
-          'type' => 'file',
+          'type' => 'library',
           'scope' => 'header',
           'weight' => JS_LIBRARY - 1,
           'cache' => TRUE,
           'defer' => FALSE,
-          'preprocess' => TRUE,
         ),
       );
       // Register all required libraries.
@@ -3263,7 +3280,7 @@ function drupal_add_js($data = NULL, $options = NULL) {
         $javascript[] = $options;
         break;
 
-      default: // 'file' and 'external'
+      default: // 'library', 'file' and 'external'
         // Local and external files must keep their name as the associative key
         // so the same JavaScript file is not be added twice.
         $javascript[$options['data']] = $options;
@@ -3340,7 +3357,8 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
 
   $output = '';
   $preprocessed = '';
-  $no_preprocess = "\n";
+  $no_preprocess = '';
+  $libraries = '';
   $files = array();
   $preprocess_js = (variable_get('preprocess_js', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
   $directory = file_directory_path('public');
@@ -3352,7 +3370,7 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
   // URL changed. Files that should not be cached (see drupal_add_js())
   // get REQUEST_TIME as query-string instead, to enforce reload on every
   // page request.
-  $query_string = '?' . substr(variable_get('css_js_query_string', '0'), 0, 1);
+  $default_query_string = '?' . substr(variable_get('css_js_query_string', '0'), 0, 2);
 
   // For inline Javascript to validate as XHTML, all Javascript containing
   // XHTML needs to be wrapped in CDATA. To make that backwards compatible
@@ -3372,6 +3390,12 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
     ),
   );
   foreach ($items as $item) {
+    if (empty($item['version'])) {
+      $query_string = $default_query_string;
+    }
+    else {
+      $query_string = '?v=' . $item['version'];
+    }
     switch ($item['type']) {
       case 'setting':
         $js_element = $element;
@@ -3406,6 +3430,16 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
         }
         break;
 
+      case 'library':
+        $js_element = $element;
+        // Preprocessing for JavaScript libraries is ignored.
+        if ($item['defer']) {
+          $js_element['#attributes']['defer'] = 'defer';
+        }
+        $js_element['#attributes']['src'] = file_create_url($item['data']) . $query_string;
+        $libraries .= theme('html_tag', array('element' => $js_element));
+        break;
+
       case 'external':
         $js_element = $element;
         // Preprocessing for external JavaScript files is ignored.
@@ -3422,8 +3456,8 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
   if ($is_writable && $preprocess_js && count($files) > 0) {
     // Prefix filename to prevent blocking by firewalls which reject files
     // starting with "ad*".
-    $filename = 'js_' . md5(serialize($files) . $query_string) . '.js';
-    $preprocess_file = file_create_url(drupal_build_js_cache($files, $filename));
+    $filename = 'js_' . md5(serialize($files)) . '.js';
+    $preprocess_file = file_create_url(drupal_build_js_cache($files, $filename)) . $default_query_string;
     $js_element = $element;
     $js_element['#attributes']['src'] = $preprocess_file;
     $preprocessed .= theme('html_tag', array('element' => $js_element)) . "\n";
@@ -3431,7 +3465,7 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
 
   // Keep the order of JS files consistent as some are preprocessed and others are not.
   // Make sure any inline or JS setting variables appear last after libraries have loaded.
-  return $preprocessed . $no_preprocess . $output;
+  return $libraries . $preprocessed . $no_preprocess . $output;
 }
 
 /**
@@ -3671,6 +3705,12 @@ function drupal_get_library($module, $name) {
   if (!empty($libraries[$module][$name]) && is_array($libraries[$module][$name])) {
     // Add default elements to allow for easier processing.
     $libraries[$module][$name] += array('dependencies' => array(), 'js' => array(), 'css' => array());
+    foreach ($libraries[$module][$name]['js'] as $library => $options) {
+      $libraries[$module][$name]['js'][$library] += array('type' => 'library', 'version' => $libraries[$module][$name]['version']);
+    }
+    foreach ($libraries[$module][$name]['css'] as $library => $options) {
+      $libraries[$module][$name]['css'][$library] += array('type' => 'library', 'version' => $libraries[$module][$name]['version']);
+    }
   }
   else {
     $libraries[$module][$name] = FALSE;
@@ -5718,8 +5758,8 @@ function drupal_flush_all_caches() {
  *
  * Changes the character added to all css/js files as dummy query-string,
  * so that all browsers are forced to reload fresh files. We keep
- * 20 characters history (FIFO) to avoid repeats, but only the first
- * (newest) character is actually used on urls, to keep them short.
+ * 20 characters history (FIFO) to avoid repeats, but only the first two
+ * (newest) characters are actually used on urls, to keep them short.
  * This is also called from update.php.
  */
 function _drupal_flush_css_js() {
diff --git modules/simpletest/tests/common.test modules/simpletest/tests/common.test
index 7f66540..e13c65e 100644
--- modules/simpletest/tests/common.test
+++ modules/simpletest/tests/common.test
@@ -1168,7 +1168,7 @@ class JavaScriptTestCase extends DrupalWebTestCase {
    * Test rendering the JavaScript with a file's weight above jQuery's.
    */
   function testRenderDifferentWeight() {
-    drupal_add_js('misc/collapse.js', array('weight' => JS_LIBRARY - 21));
+    drupal_add_js('misc/collapse.js', array('weight' => JS_LIBRARY - 21, 'type' => 'library'));
     $javascript = drupal_get_js();
     $this->assertTrue(strpos($javascript, 'misc/collapse.js') < strpos($javascript, 'misc/jquery.js'), t('Rendering a JavaScript file above jQuery.'));
   }
diff --git modules/system/system.module modules/system/system.module
index 5c16f70..1e7adf7 100644
--- modules/system/system.module
+++ modules/system/system.module
@@ -1090,7 +1090,7 @@ function system_library() {
     'website' => 'http://benalman.com/projects/jquery-bbq-plugin/',
     'version' => '1.0.2',
     'js' => array(
-      'misc/jquery.ba-bbq.js',
+      'misc/jquery.ba-bbq.js' => array(),
     ),
   );
 
