Bug 447738 - Unminified JS plugin times out in web worker case
diff --git a/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptPlugin.js b/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptPlugin.js
index c0c929f..03ae602 100644
--- a/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptPlugin.js
+++ b/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptPlugin.js
@@ -28,7 +28,6 @@
 	'javascript/occurrences',
 	'javascript/hover',
 	'javascript/outliner',
-	'orion/plugin',
 	'orion/util',
 	'javascript/commands/generateDocCommand',
 	'orion/editor/stylers/application_javascript/syntax',
@@ -36,18 +35,15 @@
 	'orion/editor/stylers/application_schema_json/syntax',
 	'orion/editor/stylers/application_x-ejs/syntax'
 ], function(Esprima, ASTManager, MongodbIndex, MysqlIndex, PostgresIndex, RedisIndex, ExpressIndex, AMQPIndex, ContentAssist, 
-			EslintValidator, Occurrences, Hover, Outliner,	PluginProvider, Util, GenerateDocCommand, mJS, mJSON, mJSONSchema, mEJS) {
+			EslintValidator, Occurrences, Hover, Outliner, Util, GenerateDocCommand, mJS, mJSON, mJSONSchema, mEJS) {
 
-	/**
-	 * Plug-in headers
-	 */
-	var headers = {
-		name: "Orion JavaScript Tool Support", //$NON-NLS-0$
-		version: "1.0", //$NON-NLS-0$
-		description: "This plugin provides JavaScript tools support for Orion, like editing, search, navigation, validation, and code completion." //$NON-NLS-0$
-	};
-	var provider = new PluginProvider(headers);
-	
+/**
+ * Registers the JS services against the given <tt>PluginProvider</tt>.
+ * @name javascript.JSPluginFactory
+ * @param {orion.PluginProvider} provider
+ */
+function Factory(provider) {
+
 	/**
 	 * Register the JavaScript content types
 	 */
@@ -395,4 +391,8 @@
 	});
 
 	provider.connect();
-});
+} // Factory()
+
+return Factory;
+
+});
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptPluginLoader.js b/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptPluginLoader.js
index 0cd6629..15d99fc 100644
--- a/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptPluginLoader.js
+++ b/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptPluginLoader.js
@@ -27,12 +27,12 @@
 	}
 
 	if (!useWorker) {
-		// Non-worker case
-		require(["javascript/plugins/javascriptPlugin"]);
+		// Non-worker case.
+		require(["javascript/plugins/javascriptWorker"]);
 		return;
 	}
 
-	// Worker case. Talk directly to the framework message plumbing
+	// Worker case. Talk directly to the framework message plumbing.
 	var framework;
 	if (window !== window.parent) {
 		framework = window.parent;
diff --git a/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptWorker.js b/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptWorker.js
index 5864933..3bfbc93 100644
--- a/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptWorker.js
+++ b/bundles/org.eclipse.orion.client.javascript/web/javascript/plugins/javascriptWorker.js
@@ -12,33 +12,71 @@
 /*global importScripts*/
 /*eslint-env amd*/
 
-// This file bootstraps RequireJS in the worker context, then loads the JavaScript plugin impl
+/**
+ * This file is invoked to initialize the JS plugin. It may be loaded in 2 contexts:
+ *
+ * 1) As a web worker script via new Worker("javascriptWorker.js").
+ * In this mode it configures RequireJS in the worker's global environment, then initializes the JS plugin.
+ *
+ * 2) In a regular Window.
+ * In this mode it simply initializes the JS plugin.
+ */
+(function(factory) {
+	if (typeof define === "function" && define.amd && typeof importScripts === "undefined") {
+		// Case 1
+		define(factory);
+	} else if (typeof importScripts === "function") {
+		// Case 2
+		importScripts("../../requirejs/require.js"); // synchronous
+		require.config({
+			baseUrl: "../../",
+			paths: {
+				text: "requirejs/text",
+				esprima: "esprima/esprima",
+				estraverse: "estraverse/estraverse",
+				escope: "escope/escope",
+				logger: "javascript/logger",
+				doctrine: 'doctrine/doctrine'
+			},
+			packages: [
+				{
+					name: "eslint",
+					location: "eslint/lib",
+					main: "eslint"
+				},
+				{
+					name: "eslint/conf",
+					main: "eslint/conf"
+			}]
+		});
+		factory();
+	} else {
+		throw new Error("Unsupported global context");
+	}
+}(function() {
+	/**
+	 * Set up the plugin. This happens in several stages:
+	 *
+	 * 1) Create the PluginProvider. This causes a loading() callback to the framework, which prevents it from
+	 * timeout'ing us after 5 seconds. This is important in the worker case when running an un-optimized build
+	 * of Orion, as javascriptPlugin takes longer than 5 seconds to load.
+	 * 2) Load javascriptPlugin.
+	 * 3) Register the actual services against the PluginProvider.
+	 */
+	// TODO can we move orion/plugin up into the importScripts() call?
+	require(["orion/plugin"], function(PluginProvider) {
+		/**
+		 * Plug-in headers
+		 */
+		var headers = {
+			name: "Orion JavaScript Tool Support", //$NON-NLS-0$
+			version: "1.0", //$NON-NLS-0$
+			description: "This plugin provides JavaScript tools support for Orion, like editing, search, navigation, validation, and code completion." //$NON-NLS-0$
+		};
+		var provider = new PluginProvider(headers);
 
-if (typeof importScripts !== "function") {
-	throw new Error("This script must be run from a Worker");
-}
-importScripts("../../requirejs/require.js");
-
-require.config({
-	baseUrl: "../../",
-	paths: {
-		text: "requirejs/text",
-		esprima: "esprima/esprima",
-		estraverse: "estraverse/estraverse",
-		escope: "escope/escope",
-		logger: "javascript/logger",
-		doctrine: 'doctrine/doctrine'
-	},
-	packages: [
-		{
-			name: "eslint",
-			location: "eslint/lib",
-			main: "eslint"
-		},
-		{
-			name: "eslint/conf",
-			main: "eslint/conf"
-	}]
-});
-
-require(["javascript/plugins/javascriptPlugin"]);
+		require(["javascript/plugins/javascriptPlugin"], function(jsPluginFactory) {
+			jsPluginFactory(provider);
+		});
+	});
+}));