Provide a more standard GWT linker for HTML5 worker threads based on the ConfigurableLinker. Unlike the non-standard WorkerLinker and SharedWorkerLinker, this change allows worker threads to do GWT RPCs. A follow-up change will migrate existing uses of the old linkers to this new one.

Review by: unnurg@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10334 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeLinker.java b/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeLinker.java
index 6d55189..a2615b0 100644
--- a/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeLinker.java
+++ b/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeLinker.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2010 Google Inc.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -66,10 +66,18 @@
       LinkerContext context, ArtifactSet artifacts, CompilationResult result)
       throws UnableToCompleteException {
 
+    if (shouldUseSelfForWindowAndDocument(context)) {
+      replaceAll(ss, "__WINDOW_DEF__", "self");
+      replaceAll(ss, "__DOCUMENT_DEF__", "self");
+    } else {
+      replaceAll(ss, "__WINDOW_DEF__", "window");
+      replaceAll(ss, "__DOCUMENT_DEF__", "document");
+    }
+
     // Must do installScript before installLocation and waitForBodyLoaded
     includeJs(ss, logger, getJsInstallScript(context), "__INSTALL_SCRIPT__");
     includeJs(ss, logger, getJsInstallLocation(context), "__INSTALL_LOCATION__");
-    
+
     // Must do waitForBodyLoaded before isBodyLoaded
     includeJs(ss, logger, getJsWaitForBodyLoaded(context), "__WAIT_FOR_BODY_LOADED__");
     includeJs(ss, logger, getJsIsBodyLoaded(context), "__IS_BODY_LOADED__");
@@ -132,12 +140,25 @@
 
     if (context.isOutputCompact()) {
       replaceAll(ss, "__START_OBFUSCATED_ONLY__", "");
-      replaceAll(ss, "__END_OBFUSCATED_ONLY__", "");      
+      replaceAll(ss, "__END_OBFUSCATED_ONLY__", "");
     } else {
       replaceAll(ss, "__START_OBFUSCATED_ONLY__", "/*");
       replaceAll(ss, "__END_OBFUSCATED_ONLY__", "*/");
     }
 
+    String jsModuleFunctionErrorCatch = getJsModuleFunctionErrorCatch(context);
+    if (jsModuleFunctionErrorCatch != null) {
+      replaceAll(ss, "__BEGIN_TRY_BLOCK__", "try {");
+      replaceAll(ss, "__END_TRY_BLOCK_AND_START_CATCH__", "} catch (moduleError) {");
+      includeJs(ss, logger, jsModuleFunctionErrorCatch, "__MODULE_FUNC_ERROR_CATCH__");
+      replaceAll(ss, "__END_CATCH_BLOCK__", "}");
+    } else {
+      replaceAll(ss, "__BEGIN_TRY_BLOCK__", "");
+      replaceAll(ss, "__END_TRY_BLOCK_AND_START_CATCH__", "");
+      replaceAll(ss, "__MODULE_FUNC_ERROR_CATCH__", "");
+      replaceAll(ss, "__END_CATCH_BLOCK__", "");
+    }
+
     return ss.toString();
   }
 
@@ -220,6 +241,18 @@
   }
 
   /**
+   * Returns the name of the {@code JsModuleFunctionErrorCatch} script. By default returns null.
+   * This script executes if there's an error loading the module function or executing it.
+   * The error will be available under a local variable named "moduleError". If non-null, the
+   * module function and the call to the module function will be placed in a try/catch block.
+   *
+   * @param context a LinkerContext
+   */
+  protected String getJsModuleFunctionErrorCatch(LinkerContext context) {
+    return null;
+  }
+
+  /**
    * Returns the name of the {@code JsPermutations} script.  By default,
    * returns {@code "com/google/gwt/core/ext/linker/impl/permutations.js"}.
    *
@@ -414,6 +447,14 @@
     return false;
   }
 
+  /**
+   * Returns whether to use "self" for $wnd and $doc references. Defaults to false.
+   * Useful for worker threads.
+   */
+  protected boolean shouldUseSelfForWindowAndDocument(LinkerContext context) {
+    return false;
+  }
+
   @Override
   protected String wrapPrimaryFragment(TreeLogger logger, LinkerContext context, String script,
       ArtifactSet artifacts, CompilationResult result) throws UnableToCompleteException {
diff --git a/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeTemplate.js b/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeTemplate.js
index 383197c..bb8a364 100644
--- a/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeTemplate.js
+++ b/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeTemplate.js
@@ -13,9 +13,10 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+__BEGIN_TRY_BLOCK__
 function __MODULE_FUNC__() {
-  var $wnd = window;
-  var $doc = document;
+  var $wnd = __WINDOW_DEF__;
+  var $doc = __DOCUMENT_DEF__;
   sendStats('bootstrap', 'begin');
 
   /****************************************************************************
@@ -49,7 +50,7 @@
    ***************************************************************************/
   // These are set by various parts of the bootstrapping code, but they always
   // need to exist, so give them all default values here.
-  
+
   // Exposed for the convenience of the devmode.js and md5.js files
   __MODULE_FUNC__.__sendStats = sendStats;
 
@@ -89,7 +90,7 @@
   // Provides the computeUrlForResource() function
   __COMPUTE_URL_FOR_RESOURCE__
 
-  // Provides the getCompiledCodeFilename() function which sets the 
+  // Provides the getCompiledCodeFilename() function which sets the
   // __gwt_isKnownPropertyValue, MODULE_FUNC__.__computePropValue and
   // __MODULE_FUNC__.__softPermutationId variables if needed
   __PERMUTATIONS__
@@ -117,3 +118,7 @@
 
 }
 __MODULE_FUNC__();
+
+__END_TRY_BLOCK_AND_START_CATCH__
+  __MODULE_FUNC_ERROR_CATCH__
+__END_CATCH_BLOCK__