diff --git a/includes/OutputPage.php b/includes/OutputPage.php
index beaca5f..5515160 100644
--- a/includes/OutputPage.php
+++ b/includes/OutputPage.php
@@ -2748,43 +2748,77 @@
 		// Legacy Scripts
 		$scripts .= "\n" . $this->mScripts;
 
-		$userScripts = array();
-
+		$defaultModules = array();
+		$groupScript = '';
+		
+		$siteLink = '';
 		// Add site JS if enabled
 		if ( $wgUseSiteJs ) {
-			$scripts .= $this->makeResourceLoaderLink( 'site', ResourceLoaderModule::TYPE_SCRIPTS,
+			$siteLink = $this->makeResourceLoaderLink( 'site', ResourceLoaderModule::TYPE_SCRIPTS,
 				/* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
 			);
+			$scripts .= $siteLink;
 			if( $this->getUser()->isLoggedIn() ){
-				$userScripts[] = 'user.groups';
+				$groupScript = 'user.groups';
 			}
 		}
+		$defaultModules['site'] = $siteLink == '' ? 'ready' : 'loading';
 
 		// Add user JS if enabled
+		$userLink = '';
 		if ( $wgAllowUserJs && $this->getUser()->isLoggedIn() ) {
 			if( $this->getTitle() && $this->getTitle()->isJsSubpage() && $this->userCanPreview() ) {
 				# XXX: additional security check/prompt?
 				// We're on a preview of a JS subpage
 				// Exclude this page from the user module in case it's in there (bug 26283)
-				$scripts .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS, false,
+				$userLink .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS, false,
 					array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() ), $inHead
 				);
 				// Load the previewed JS
-				$scripts .= Html::inlineScript( "\n" . $this->getRequest()->getText( 'wpTextbox1' ) . "\n" ) . "\n";
+				$userLink .= Html::inlineScript(
+					"\n" . $this->getRequest()->getText( 'wpTextbox1' ) . "\n" . ResourceLoader::makeLoaderStateScript( 'user', 'ready' )
+				) . "\n";
+				// FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded asynchronously and may arrive *after*
+				// the inline script here. So we may end up setting the "ready" state too early, and anyway the previewed code may execute
+				// before ./common.js runs. Normally, ./common.js runs before ./vector.js...
 			} else {
 				// Include the user module normally
 				// We can't do $userScripts[] = 'user'; because the user module would end up
 				// being wrapped in a closure, so load it raw like 'site'
-				$scripts .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS,
+				$userLink = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS,
 					/* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
 				);
 			}
+			$scripts .= $userLink;
 		}
-		$scripts .= $this->makeResourceLoaderLink( $userScripts, ResourceLoaderModule::TYPE_COMBINED,
-			/* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
-		);
+		$defaultModules['user'] = $userLink == '' ? 'ready' : 'loading';
 
-		return $scripts;
+		$groupLink = '';
+		if ( $groupScript != '' ) {
+			$groupLink = $this->makeResourceLoaderLink( $groupScript, ResourceLoaderModule::TYPE_COMBINED,
+				/* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
+			);		
+			$scripts .= $groupLink;
+		}
+		$defaultModules['user.groups'] = $groupLink == '' ? 'ready' : 'loading';
+
+		$loaderInit = '';
+		if ( $inHead ) {
+			// We generate loader calls anyway, so no need to fix the client-side loader's state to 'loading'
+			foreach ($defaultModules as $m => $state) {
+				if ( $state == 'loading' ) {
+					unset ($defaultModules[$m]);
+				}
+			}
+		}
+		if ( count( $defaultModules ) > 0 ) {
+			$loaderInit .= Html::inlineScript(
+				ResourceLoader::makeLoaderConditionalScript(
+					Xml::encodeJsCall( 'mw.loader.state', array( (object)$defaultModules ) )
+				)
+			) . "\n";
+		}
+		return $loaderInit . $scripts;
 	}
 
 	/**
diff --git a/resources/mediawiki/mediawiki.js b/resources/mediawiki/mediawiki.js
index eebbab2..db26514 100644
--- a/resources/mediawiki/mediawiki.js
+++ b/resources/mediawiki/mediawiki.js
@@ -1300,7 +1300,12 @@
 					if ( registry[module] === undefined ) {
 						mw.loader.register( module );
 					}
-					registry[module].state = state;
+					if ( state === 'ready' && registry[module].state !== state) {
+						// Make sure pending modules depending on this one get executed if their dependencies are now fulfilled!
+						mw.loader.implement ( module, function () {}, {}, {} );
+					} else {
+						registry[module].state = state;
+					}
 				},
 		
 				/**