Index: wp-includes/default-filters.php
===================================================================
--- wp-includes/default-filters.php	(revision 3783)
+++ wp-includes/default-filters.php	(working copy)
@@ -86,6 +86,7 @@
 add_action('wp_head', 'rsd_link');
 add_action('publish_future_post', 'wp_publish_post', 10, 1);
 add_action('wp_head', 'noindex', 1);
+add_action('wp_head', 'wp_print_scripts');
 if(!defined('DOING_CRON'))
 	add_action('init', 'wp_cron');
 add_action('do_feed_rdf', 'do_feed_rdf', 10, 1);
Index: wp-includes/functions-post.php
===================================================================
--- wp-includes/functions-post.php	(revision 3783)
+++ wp-includes/functions-post.php	(working copy)
@@ -1037,18 +1037,6 @@
 }
 
 /**
- * Places two script links in <head>: one to get tinyMCE (big), one to configure and start it (small)
- */
-function tinymce_include() {
-	$ver = '04162006';
-	$src1 = get_settings('siteurl') . "/wp-includes/js/tinymce/tiny_mce_gzip.php?ver=$ver";
-	$src2 = get_settings('siteurl') . "/wp-includes/js/tinymce/tiny_mce_config.php?ver=$ver";
-
-	echo "<script type='text/javascript' src='$src1'></script>\n";
-	echo "<script type='text/javascript' src='$src2'></script>\n";
-}
-
-/**
  * Places a textarea according to the current user's preferences, filled with $content.
  * Also places a script block that enables tabbing between Title and Content.
  *
Index: wp-includes/deprecated.php
===================================================================
--- wp-includes/deprecated.php	(revision 3783)
+++ wp-includes/deprecated.php	(working copy)
@@ -452,4 +452,8 @@
 	return wp_dropdown_categories($query);
 }
 
+// Deprecated.  Use wp_print_scripts() or WP_Scripts instead.
+function tinymce_include() {
+	wp_print_script( 'wp_tiny_mce' );
+}
 ?>
Index: wp-includes/script-loader.php
===================================================================
--- wp-includes/script-loader.php	(revision 0)
+++ wp-includes/script-loader.php	(revision 0)
@@ -0,0 +1,220 @@
+<?php
+class WP_Scripts {
+	var $scripts = array();
+	var $queue = array();
+	var $printed = array();
+
+	function WP_Scripts() {
+		$this->default_scripts();
+	}
+
+	function default_scripts() {
+		$this->add( 'dbx', '/wp-includes/js/dbx.js', false, '2.02' );
+		$this->add( 'dbx-key', '/wp-includes/js/dbx-key.js', false, '3651' );
+		$this->add( 'fat', '/wp-includes/js/fat.js', false, '1.0-RC1_3660' );
+		$this->add( 'sack', '/wp-includes/js/tw-sack.js', false, '1.6.1' );
+		$this->add( 'quicktags', '/wp-includes/js/quicktags.js', false, '3517' );
+		$this->add( 'colorpicker', '/wp-includes/js/colorpicker.js', false, '3517' );
+		$this->add( 'tiny_mce', '/wp-includes/js/tinymce/tiny_mce_gzip.php', false, '04162006' );
+		$this->add( 'wp_tiny_mce', '/wp-includes/js/tinymce/tiny_mce_config.php', array('tiny_mce'), '04162006' );
+		if ( is_admin() ) {
+			$this->add( 'listman', '/wp-admin/list-manipulation-js.php', array('sack', 'fat'), '3733' );
+			$this->add( 'ajaxcat', '/wp-admin/cat-js.php', array('listman'), '3684' );
+			$this->add( 'admin-categories', '/wp-admin/categories.js', array('listman'), '3684' );
+			$this->add( 'admin-custom-fields', '/wp-admin/custom-fields.js', array('listman'), '3733' );
+			$this->add( 'admin-comments', '/wp-admin/edit-comments.js', array('listman'), '3736' );
+			$this->add( 'admin-users', '/wp-admin/users.js', array('listman'), '3684' );
+			$this->add( 'xfn', '/wp-admin/xfn.js', false, '3517' );
+		}
+	}
+
+	/**
+	 * Prints script tags
+	 *
+	 * Prints the scripts passed to it or the print queue.  Also prints all necessary dependencies.
+	 *
+	 * @param mixed handles (optional) Scripts to be printed.  (void) prints queue, (string) prints that script, (array of strings) prints those scripts.
+	 * @return array Scripts that have been printed
+	 */
+	function print_scripts( $handles = false ) {
+		// Print the queue if nothing is passed.  If a string is passed, print that script.  If an array is passed, print those scripts.
+		$handles = false === $handles ? $this->queue : (array) $handles;
+		$handles = $this->all_deps( $handles );
+		$this->_print_scripts( $handles );
+		return $this->printed;
+	}
+
+	/**
+	 * Internally used helper function for printing script tags
+	 *
+	 * @param array handles Hierarchical array of scripts to be printed
+	 * @see WP_Scripts::all_deps()
+	 */
+	function _print_scripts( $handles ) {
+		global $wp_db_version;
+
+		foreach( array_keys($handles) as $handle ) {
+			if ( !$handles[$handle] )
+				return;
+			elseif ( is_array($handles[$handle]) )
+				$this->_print_scripts( $handles[$handle] );
+			if ( !in_array($handle, $this->printed) && isset($this->scripts[$handle]) ) {
+				$ver = $this->scripts[$handle]->ver ? $this->scripts[$handle]->ver : $wp_db_version;
+				$src = 0 === strpos($this->scripts[$handle]->src, 'http://') ? $this->scripts[$handle]->src : get_settings( 'siteurl' ) . $this->scripts[$handle]->src;
+				echo "<script type='text/javascript' src='$src?ver=$ver'></script>\n";
+				$this->printed[] = $handle;
+			}
+		}
+	}
+				
+
+	/**
+	 * Determines dependencies of scripts
+	 *
+	 * Recursively builds hierarchical array of script dependencies.  Does NOT catch infinite loops.
+	 *
+	 * @param mixed handles Accepts (string) script name or (array of strings) script names
+	 * @param bool recursion Used internally when function calls itself
+	 * @return array Hierarchical array of dependencies
+	 */
+	function all_deps( $handles, $recursion = false ) {
+		if ( ! $handles = (array) $handles )
+			return array();
+		$return = array();
+		foreach ( $handles as $handle ) {
+			if ( is_null($return[$handle]) ) // Prime the return array with $handles
+				$return[$handle] = true;
+			if ( $this->scripts[$handle]->deps ) {
+				if ( false !== $return[$handle] && array_diff($this->scripts[$handle]->deps, array_keys($this->scripts)) )
+					$return[$handle] = false; // Script required deps which don't exist
+				else
+					$return[$handle] = $this->all_deps( $this->scripts[$handle]->deps, true ); // Build the hierarchy
+			}
+			if ( $recursion && false === $return[$handle] )
+				return false; // Cut the branch
+		}
+		return $return;
+	}
+
+	/**
+	 * Adds script
+	 *
+	 * Adds the script only if no script of that name already exists
+	 *
+	 * @param string handle Script name
+	 * @param string src Script url
+	 * @param array deps (optional) Array of script names on which this script depends
+	 * @param string ver (optional) Script version (used for cache busting)
+	 * @return array Hierarchical array of dependencies
+	 */
+	function add( $handle, $src, $deps = array(), $ver = false ) {
+		if ( isset($this->scripts[$handle]) )
+			return false;
+		$this->scripts[$handle] = new _WP_Script( $handle, $src, $deps, $ver );
+		return true;
+	}
+
+	function remove( $handles ) {
+		foreach ( (array) $handles as $handle )
+			unset($this->scripts[$handle]);
+	}
+
+	function enqueue( $handles ) {
+		foreach ( (array) $handles as $handle )
+			if ( !in_array($handle, $this->queue) && isset($this->scripts[$handle]) )
+				$this->queue[] = $handle;
+	}
+
+	function dequeue( $handles ) {
+		foreach ( (array) $handles as $handle )
+			unset( $this->queue[$handle] );
+	}
+
+	function query( $handle, $list = 'scripts' ) { // scripts, queue, or printed
+		switch ( $list ) :
+		case 'scripts':
+			if ( isset($this->scripts[$handle]) )
+				return $this->scripts[$handle];
+			break;
+		default:
+			if ( in_array($handle, $this->$list) )
+				return true;
+			break;
+		endswitch;
+		return false;
+	}
+			
+}
+
+class _WP_Script {
+	var $handle;
+	var $src;
+	var $deps = array();
+	var $ver = false;
+
+	function _WP_Script() {
+		@list($this->handle, $this->src, $this->deps, $this->ver) = func_get_args();
+		if ( !is_array($this->deps) )
+			$this->deps = array();
+		if ( !$this->ver )
+			$this->ver = false;
+	}
+}
+
+/**
+ * Prints script tags in document head
+ *
+ * Called by admin-header.php and by wp_head hook. Since it is called by wp_head on every page load,
+ * the function does not instantiate the WP_Scripts object unless script names are explicitly passed.
+ * Does make use of already instantiated $wp_scripts if present.
+ * Use provided wp_print_scripts hook to register/enqueue new scripts.
+ *
+ * @see WP_Scripts::print_scripts()
+ */
+function wp_print_scripts( $handles = false ) {
+	do_action( 'wp_print_scripts' );
+
+	global $wp_scripts;
+	if ( !is_a($wp_scripts, 'WP_Scripts') ) {
+		if ( !$handles )
+			return array(); // No need to instantiate if nothing's there.
+		else
+			$wp_scripts = new WP_Scripts();
+	}
+
+	return $wp_scripts->print_scripts( $handles );
+}
+
+function wp_register_script( $handle, $src, $deps = array(), $ver = false ) {
+	global $wp_scripts;
+	if ( !is_a($wp_scripts, 'WP_Scripts') )
+		$wp_scripts = new WP_Scripts();
+
+	$wp_scripts->add( $handle, $src, $deps, $ver );
+}
+
+function wp_deregister_script( $handle ) {
+	global $wp_scripts;
+	if ( !is_a($wp_scripts, 'WP_Scripts') )
+		$wp_scripts = new WP_Scripts();
+
+	$wp_scripts->remove( $handle );
+}
+
+/**
+ * Equeues script
+ *
+ * Registers the script if src provided (does NOT overwrite) and enqueues.
+ *
+ * @see WP_Script::add(), WP_Script::enqueue()
+*/
+function wp_enqueue_script( $handle, $src = false, $deps = array(), $ver = false ) {
+	global $wp_scripts;
+	if ( !is_a($wp_scripts, 'WP_Scripts') )
+		$wp_scripts = new WP_Scripts();
+
+	if ( $src )
+		$wp_scripts->add( $handle, $src, $deps, $ver );
+	$wp_scripts->enqueue( $handle );
+}
+?>
Index: wp-settings.php
===================================================================
--- wp-settings.php	(revision 3783)
+++ wp-settings.php	(working copy)
@@ -143,6 +143,7 @@
 require (ABSPATH . WPINC . '/cron.php');
 require (ABSPATH . WPINC . '/version.php');
 require (ABSPATH . WPINC . '/deprecated.php');
+require (ABSPATH . WPINC . '/script-loader.php');
 
 if (!strstr($_SERVER['PHP_SELF'], 'install.php')) :
     // Used to guarantee unique hash cookies
@@ -226,4 +227,4 @@
 // Everything is loaded and initialized.
 do_action('init');
 
-?>
\ No newline at end of file
+?>
Index: wp-admin/users.php
===================================================================
--- wp-admin/users.php	(revision 3783)
+++ wp-admin/users.php	(working copy)
@@ -143,10 +143,8 @@
 	}
 
 default:
+	wp_enqueue_script( 'admin-users' );
 
-	$list_js = true;
-	$users_js = true;
-
 	include ('admin-header.php');
 
 	$userids = $wpdb->get_col("SELECT ID FROM $wpdb->users;");
Index: wp-admin/edit-comments.php
===================================================================
--- wp-admin/edit-comments.php	(revision 3783)
+++ wp-admin/edit-comments.php	(working copy)
@@ -3,7 +3,7 @@
 
 $title = __('Edit Comments');
 $parent_file = 'edit.php';
-$list_js = true;
+wp_enqueue_script( 'admin-comments' );
 
 require_once('admin-header.php');
 if (empty($_GET['mode'])) $mode = 'view';
Index: wp-admin/admin.php
===================================================================
--- wp-admin/admin.php	(revision 3783)
+++ wp-admin/admin.php	(working copy)
@@ -40,8 +40,10 @@
     }
 }
 
-$xfn_js = $sack_js = $list_js = $cat_js = $users_js = $dbx_js = $pmeta_js = $editing = false;
+wp_enqueue_script( 'fat' );
 
+$editing = false;
+
 require(ABSPATH . '/wp-admin/menu.php');
 
 // Handle plugin admin pages.
Index: wp-admin/admin-functions.php
===================================================================
--- wp-admin/admin-functions.php	(revision 3783)
+++ wp-admin/admin-functions.php	(working copy)
@@ -1173,14 +1173,15 @@
 
 function the_quicktags() {
 	// Browser detection sucks, but until Safari supports the JS needed for this to work people just assume it's a bug in WP
-	if (!strstr($_SERVER['HTTP_USER_AGENT'], 'Safari'))
+	if (!strstr($_SERVER['HTTP_USER_AGENT'], 'Safari')) {
 		echo '
 		<div id="quicktags">
-			<script src="../wp-includes/js/quicktags.js" type="text/javascript"></script>
-			<script type="text/javascript">if ( typeof tinyMCE == "undefined" || tinyMCE.configs.length < 1 ) edToolbar();</script>
+			';
+		wp_print_scripts( 'quicktags' );
+		echo '			<script type="text/javascript">if ( typeof tinyMCE == "undefined" || tinyMCE.configs.length < 1 ) edToolbar();</script>
 		</div>
 ';
-	else echo '
+	} else echo '
 <script type="text/javascript">
 function edInsertContent(myField, myValue) {
 	//IE support
Index: wp-admin/moderation.php
===================================================================
--- wp-admin/moderation.php	(revision 3783)
+++ wp-admin/moderation.php	(working copy)
@@ -3,7 +3,7 @@
 
 $title = __('Moderate comments');
 $parent_file = 'edit.php';
-$list_js = true;
+wp_enqueue_script( 'listman' );
 
 $wpvarstoreset = array('action', 'item_ignored', 'item_deleted', 'item_approved', 'item_spam', 'feelinglucky');
 for ($i=0; $i<count($wpvarstoreset); $i += 1) {
@@ -229,4 +229,4 @@
 
 include('admin-footer.php');
 
-?>
\ No newline at end of file
+?>
Index: wp-admin/admin-header.php
===================================================================
--- wp-admin/admin-header.php	(revision 3783)
+++ wp-admin/admin-header.php	(working copy)
@@ -2,15 +2,12 @@
 @header('Content-type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset'));
 if (!isset($_GET["page"])) require_once('admin.php');
 if ( $editing ) {
-	$dbx_js = true;
-	$pmeta_js = true;
-	$list_js = true;
-	if ( current_user_can('manage_categories') ) {
-		$cat_js = true;
-	}
+	wp_enqueue_script( array('dbx','admin-custom-fields') );
+	if ( current_user_can('manage_categories') )
+		wp_enqueue_script( 'ajaxcat' );
+	if ( user_can_richedit() )
+		wp_enqueue_script( 'wp_tiny_mce' );
 }
-if ( $list_js )
-	$sack_js = true;
 ?>
 <?php get_admin_page_title(); ?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@@ -24,30 +21,10 @@
 function addLoadEvent(func) {if ( typeof wpOnload!='function'){wpOnload=func;}else{ var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}}
 //]]>
 </script>
-<script type="text/javascript" src="../wp-includes/js/fat.js"></script>
-<?php if ( $xfn_js ) { ?>
-<script type="text/javascript" src="xfn.js"></script>
-<?php } ?>
-<?php if ( $sack_js ) { ?>
-<script type="text/javascript" src="../wp-includes/js/tw-sack.js"></script>
-<?php } ?>
-<?php if ( $list_js ) { ?>
-<script type="text/javascript" src="list-manipulation-js.php"></script>
-<?php } ?>
-<?php if ( $pmeta_js ) { ?>
-<script type="text/javascript" src="custom-fields.js"></script>
-<?php } ?>
-<?php if ( 'categories.php' == $pagenow && 'edit' != $action ) { ?>
-<script type="text/javascript" src="categories.js"></script>
-<?php } ?>
-<?php if ( $users_js ) { ?>
-<script type="text/javascript" src="users.js"></script>
-<?php } ?>
-<?php if ( 'edit-comments.php' == $pagenow || ( 'edit.php' == $pagenow && 1 == $_GET['c'] ) ) { ?>
-<script type="text/javascript" src="edit-comments.js"></script>
-<?php } ?>
-<?php if ( $dbx_js ) { ?>
-<script type="text/javascript" src="../wp-includes/js/dbx.js"></script>
+<?php if ( ($parent_file != 'link-manager.php') && ($parent_file != 'options-general.php') ) : ?>
+<style type="text/css">* html { overflow-x: hidden; }</style>
+<?php endif; $printed_scripts = wp_print_scripts(); ?>
+<?php if ( in_array('dbx', $printed_scripts) ) { ?>
 <script type="text/javascript">
 //<![CDATA[
 addLoadEvent( function() {
@@ -63,13 +40,6 @@
 </script>
 <script type="text/javascript" src="../wp-includes/js/dbx-key.js"></script>
 <?php } ?>
-<?php if ( $editing && user_can_richedit() ) { tinymce_include(); } ?>
-<?php if ( $cat_js ) { ?>
-<script type="text/javascript" src="cat-js.php"></script>
-<?php } ?>
-<?php if ( ($parent_file != 'link-manager.php') && ($parent_file != 'options-general.php') ) : ?>
-<style type="text/css">* html { overflow-x: hidden; }</style>
-<?php endif; ?>
 <?php do_action('admin_head'); ?>
 </head>
 <body>
Index: wp-admin/link-add.php
===================================================================
--- wp-admin/link-add.php	(revision 3783)
+++ wp-admin/link-add.php	(working copy)
@@ -25,7 +25,7 @@
     }
 }
 
-$xfn_js = true;
+wp_enqueue_script( 'xfn' );
 $editing = true;
 require('admin-header.php');
 ?>
Index: wp-admin/edit.php
===================================================================
--- wp-admin/edit.php	(revision 3783)
+++ wp-admin/edit.php	(working copy)
@@ -3,7 +3,7 @@
 
 $title = __('Posts');
 $parent_file = 'edit.php';
-$list_js = true;
+wp_enqueue_script( 1 == $_GET['c'] ? 'admin-comments' : 'listman' );
 require_once('admin-header.php');
 
 $_GET['m'] = (int) $_GET['m'];
Index: wp-admin/link.php
===================================================================
--- wp-admin/link.php	(revision 3783)
+++ wp-admin/link.php	(working copy)
@@ -102,7 +102,7 @@
 		break;
 
 	case 'edit' :
-		$xfn_js = true;
+		wp_enqueue_script( 'xfn' );
 		$editing = true;
 		$parent_file = 'link-manager.php';
 		$submenu_file = 'link-manager.php';
@@ -124,4 +124,4 @@
 }
 
 include ('admin-footer.php');
-?>
\ No newline at end of file
+?>
Index: wp-admin/link-manager.php
===================================================================
--- wp-admin/link-manager.php	(revision 3783)
+++ wp-admin/link-manager.php	(working copy)
@@ -8,7 +8,7 @@
 
 $title = __('Manage Bookmarks');
 $this_file = $parent_file = 'link-manager.php';
-$list_js = true;
+wp_enqueue_script( 'listman' );
 
 $wpvarstoreset = array ('action', 'cat_id', 'linkurl', 'name', 'image', 'description', 'visible', 'target', 'category', 'link_id', 'submit', 'order_by', 'links_show_cat_id', 'rating', 'rel', 'notes', 'linkcheck[]');
 
Index: wp-admin/edit-pages.php
===================================================================
--- wp-admin/edit-pages.php	(revision 3783)
+++ wp-admin/edit-pages.php	(working copy)
@@ -2,7 +2,7 @@
 require_once('admin.php');
 $title = __('Pages');
 $parent_file = 'edit.php';
-$list_js = true;
+wp_enqueue_script( 'listman' );
 require_once('admin-header.php');
 ?>
 
Index: wp-admin/categories.php
===================================================================
--- wp-admin/categories.php	(revision 3783)
+++ wp-admin/categories.php	(working copy)
@@ -79,7 +79,7 @@
 
 default:
 
-$list_js = true;
+wp_enqueue_script( 'admin-categories' );
 require_once ('admin-header.php');
 
 $messages[1] = __('Category added.');
@@ -131,4 +131,4 @@
 
 include('admin-footer.php');
 
-?>
\ No newline at end of file
+?>
