Cleans up logging structure in hosted mode.  A lot of stuff was appearing in the shell's top logger directly.  This adds nesting levels in certain places to make the logging much more clear.  Compare before and after with -logLevel SPAM to see what I'm talking about.

Each instance of ModuleSpace now has its own unique logger.  This allows log messages related to a particular hosted mode session to be collected into one place.  For example, all rebind spam for a particular refresh cycle will be collected together.  The only exception is that GWT.log() will continue to go to the top level for high visibility.

Review by: bruce (TBR)


git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4701 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/HostedMode.java b/dev/core/src/com/google/gwt/dev/HostedMode.java
index 7ddbc49..e861dfe 100644
--- a/dev/core/src/com/google/gwt/dev/HostedMode.java
+++ b/dev/core/src/com/google/gwt/dev/HostedMode.java
@@ -339,7 +339,7 @@
 
     for (String moduleName : options.getModuleNames()) {
       TreeLogger loadLogger = getTopLogger().branch(TreeLogger.DEBUG,
-          "Loading module " + moduleName);
+          "Bootstrap link for command-line module " + moduleName);
       try {
         ModuleDef module = loadModule(loadLogger, moduleName, false);
 
@@ -405,12 +405,14 @@
       return false;
     }
     try {
+      TreeLogger logger = getTopLogger().branch(TreeLogger.DEBUG,
+          "Initializing module '" + module.getName() + "' for hosted mode");
       boolean shouldRefreshPage = false;
       if (module.isGwtXmlFileStale()) {
         shouldRefreshPage = true;
-        module = loadModule(getTopLogger(), module.getCanonicalName(), false);
+        module = loadModule(logger, module.getCanonicalName(), false);
       }
-      link(getTopLogger(), module);
+      link(logger, module);
       return shouldRefreshPage;
     } catch (UnableToCompleteException e) {
       // Already logged.
@@ -441,18 +443,21 @@
    */
   private void link(TreeLogger logger, ModuleDef module)
       throws UnableToCompleteException {
+    TreeLogger linkLogger = logger.branch(TreeLogger.DEBUG, "Linking module '"
+        + module.getName() + "'");
+
     // TODO: move the module-specific computations to a helper function.
     File moduleOutDir = new File(options.getWarDir(), module.getName());
     File moduleExtraDir = (options.getExtraDir() == null) ? null : new File(
         options.getExtraDir(), module.getName());
 
     // Create a new active linker stack for the fresh link.
-    StandardLinkerContext linkerStack = new StandardLinkerContext(logger,
+    StandardLinkerContext linkerStack = new StandardLinkerContext(linkLogger,
         module, options);
     linkerStacks.put(module.getName(), linkerStack);
 
-    ArtifactSet artifacts = linkerStack.invokeLink(logger);
-    linkerStack.produceOutputDirectory(logger, artifacts, moduleOutDir,
+    ArtifactSet artifacts = linkerStack.invokeLink(linkLogger);
+    linkerStack.produceOutputDirectory(linkLogger, artifacts, moduleOutDir,
         moduleExtraDir);
   }
 
@@ -467,6 +472,9 @@
    */
   private void relink(TreeLogger logger, ModuleDef module,
       ArtifactSet newlyGeneratedArtifacts) throws UnableToCompleteException {
+    TreeLogger linkLogger = logger.branch(TreeLogger.DEBUG,
+        "Relinking module '" + module.getName() + "'");
+
     // TODO: move the module-specific computations to a helper function.
     File moduleOutDir = new File(options.getWarDir(), module.getName());
     File moduleExtraDir = (options.getExtraDir() == null) ? null : new File(
@@ -476,9 +484,9 @@
     StandardLinkerContext linkerStack = linkerStacks.get(module.getName());
     assert linkerStack != null;
 
-    ArtifactSet artifacts = linkerStack.invokeRelink(logger,
+    ArtifactSet artifacts = linkerStack.invokeRelink(linkLogger,
         newlyGeneratedArtifacts);
-    linkerStack.produceOutputDirectory(logger, artifacts, moduleOutDir,
+    linkerStack.produceOutputDirectory(linkLogger, artifacts, moduleOutDir,
         moduleExtraDir);
   }
 }
diff --git a/dev/core/src/com/google/gwt/dev/HostedModeBase.java b/dev/core/src/com/google/gwt/dev/HostedModeBase.java
index f67553d..ad964af 100644
--- a/dev/core/src/com/google/gwt/dev/HostedModeBase.java
+++ b/dev/core/src/com/google/gwt/dev/HostedModeBase.java
@@ -202,8 +202,9 @@
       }
     }
 
-    public abstract ModuleSpaceHost createModuleSpaceHost(BrowserWidget widget,
-        final String moduleName) throws UnableToCompleteException;
+    public abstract ModuleSpaceHost createModuleSpaceHost(TreeLogger logger,
+        BrowserWidget widget, String moduleName)
+        throws UnableToCompleteException;
 
     public TreeLogger getLogger() {
       return getTopLogger();
diff --git a/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java b/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java
index 0fac666..a737d3b 100644
--- a/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java
+++ b/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java
@@ -49,12 +49,10 @@
   private class SwtBrowserWidgetHostImpl extends BrowserWidgetHostImpl {
 
     @Override
-    public ModuleSpaceHost createModuleSpaceHost(BrowserWidget widget,
-        final String moduleName) throws UnableToCompleteException {
-      TreeLogger logger = getLogger();
-
+    public ModuleSpaceHost createModuleSpaceHost(TreeLogger logger,
+        BrowserWidget widget, String moduleName)
+        throws UnableToCompleteException {
       // Switch to a wait cursor.
-      //
       Shell widgetShell = widget.getShell();
       try {
         Cursor waitCursor = display.getSystemCursor(SWT.CURSOR_WAIT);
@@ -66,8 +64,8 @@
         assert (moduleDef != null);
 
         TypeOracle typeOracle = moduleDef.getTypeOracle(logger);
-        ShellModuleSpaceHost host = doCreateShellModuleSpaceHost(logger,
-            typeOracle, moduleDef);
+        ShellModuleSpaceHost host = doCreateShellModuleSpaceHost(
+            getTopLogger(), typeOracle, moduleDef);
         return host;
       } finally {
         Cursor normalCursor = display.getSystemCursor(SWT.CURSOR_ARROW);
diff --git a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
index 6ab4a8f..7517cee 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
@@ -378,6 +378,8 @@
   public synchronized void refresh(TreeLogger logger)
       throws UnableToCompleteException {
     PerfLogger.start("ModuleDef.refresh");
+    logger = logger.branch(TreeLogger.DEBUG, "Refreshing module '" + getName()
+        + "'");
 
     // Refresh resource oracles.
     lazyPublicOracle.refresh(logger);
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationState.java b/dev/core/src/com/google/gwt/dev/javac/CompilationState.java
index 3ada290..2c52e79 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationState.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationState.java
@@ -96,6 +96,8 @@
   @SuppressWarnings("unchecked")
   public void addGeneratedCompilationUnits(TreeLogger logger,
       Set<? extends CompilationUnit> generatedCups) {
+    logger = logger.branch(TreeLogger.DEBUG, "Adding '" + generatedCups.size()
+        + "' new generated units");
     for (CompilationUnit unit : generatedCups) {
       String typeName = unit.getTypeName();
       assert (!unitMap.containsKey(typeName));
@@ -154,6 +156,8 @@
    * TODO: something more optimal with generated files?
    */
   public void refresh(TreeLogger logger) {
+    logger = logger.branch(TreeLogger.DEBUG, "Refreshing module from source");
+
     // Always remove all generated compilation units.
     for (Iterator<CompilationUnit> it = unitMap.values().iterator(); it.hasNext();) {
       CompilationUnit unit = it.next();
@@ -183,6 +187,9 @@
   private void compile(TreeLogger logger, Set<CompilationUnit> newUnits) {
     PerfLogger.start("CompilationState.compile");
     if (jdtCompiler.doCompile(newUnits)) {
+      logger = logger.branch(TreeLogger.DEBUG,
+          "Validating newly compiled units");
+
       // Dump all units with direct errors; we cannot safely check them.
       boolean anyErrors = CompilationUnitInvalidator.invalidateUnitsWithErrors(
           logger, newUnits);
diff --git a/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java b/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
index e3d9e96..0fd5810 100644
--- a/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
+++ b/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
@@ -411,6 +411,7 @@
    * Full refresh based on new units.
    */
   public void refresh(TreeLogger logger, Set<CompilationUnit> units) {
+    logger = logger.branch(TreeLogger.DEBUG, "Refreshing TypeOracle");
     binaryMapper.clear();
     typeOracle.reset();
     addNewUnits(logger, units);
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java b/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java
index 8ac02f1..5a0ddcc 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserWidget.java
@@ -332,7 +332,7 @@
    * 
    * @param space ModuleSpace instance to initialize
    */
-  protected final void attachModuleSpace(ModuleSpace space)
+  protected final void attachModuleSpace(TreeLogger logger, ModuleSpace space)
       throws UnableToCompleteException {
     Object key = space.getKey();
     loadedModules.put(key, space);
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java b/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java
index 8e73ae9..b917a1b 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserWidgetHost.java
@@ -42,8 +42,8 @@
   void compile(String[] modules) throws UnableToCompleteException;
 
   // Factor this out if BrowserWidget becomes decoupled from hosted mode
-  ModuleSpaceHost createModuleSpaceHost(BrowserWidget widget, String moduleName)
-      throws UnableToCompleteException;
+  ModuleSpaceHost createModuleSpaceHost(TreeLogger logger,
+      BrowserWidget widget, String moduleName) throws UnableToCompleteException;
 
   TreeLogger getLogger();
 
diff --git a/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java b/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java
index 1671046..10aedbc 100644
--- a/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java
+++ b/dev/core/src/com/google/gwt/dev/shell/ModuleSpace.java
@@ -81,14 +81,17 @@
 
   private final Object key;
 
+  private final TreeLogger logger;
+
   private final String moduleName;
 
-  protected ModuleSpace(ModuleSpaceHost host, String moduleName, Object key) {
+  protected ModuleSpace(TreeLogger logger, ModuleSpaceHost host,
+      String moduleName, Object key) {
     this.host = host;
     this.moduleName = moduleName;
     this.key = key;
-    TreeLogger hostLogger = host.getLogger();
-    threadLocalLogger.set(hostLogger);
+    this.logger = logger;
+    threadLocalLogger.set(host.getLogger());
   }
 
   public void dispose() {
@@ -247,10 +250,13 @@
       Object[] args) throws Throwable {
     JsValue result = invokeNative(name, jthis, types, args);
     if (!result.isUndefined()) {
-      getLogger().log(
+      logger.log(
           TreeLogger.WARN,
-          "JSNI method '" + name + "' returned a value of type "
-              + result.getTypeString() + " but was declared void; it should not have returned a value at all",
+          "JSNI method '"
+              + name
+              + "' returned a value of type "
+              + result.getTypeString()
+              + " but was declared void; it should not have returned a value at all",
           null);
     }
   }
@@ -259,12 +265,12 @@
    * Allows client-side code to log to the tree logger.
    */
   public void log(String message, Throwable e) {
-    TreeLogger logger = host.getLogger();
     TreeLogger.Type type = TreeLogger.INFO;
     if (e != null) {
       type = TreeLogger.ERROR;
     }
-    logger.log(type, message, e);
+    // Log at the top level for visibility.
+    getLogger().log(type, message, e);
   }
 
   /**
@@ -465,7 +471,7 @@
 
   protected String rebind(String sourceName) throws UnableToCompleteException {
     try {
-      String result = host.rebind(host.getLogger(), sourceName);
+      String result = host.rebind(logger, sourceName);
       if (result != null) {
         return result;
       } else {
@@ -480,7 +486,8 @@
   }
 
   private String composeResultErrorMsgPrefix(String name, String typePhrase) {
-    return "Something other than " + typePhrase + " was returned from JSNI method '" + name + "'";
+    return "Something other than " + typePhrase
+        + " was returned from JSNI method '" + name + "'";
   }
 
   private boolean isUserFrame(StackTraceElement element) {
diff --git a/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java b/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java
index e1f8aef..addbfb0 100644
--- a/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java
+++ b/dev/linux/src/com/google/gwt/dev/shell/moz/BrowserWidgetMoz.java
@@ -37,34 +37,32 @@
   private class ExternalObjectImpl implements ExternalObject {
 
     public boolean gwtOnLoad(int scriptObject, String moduleName, String version) {
-      try {
-        if (moduleName == null) {
-          // Indicates one or more modules are being unloaded.
-          //
-          handleUnload(scriptObject);
-          return true;
-        }
+      if (moduleName == null) {
+        // Indicates one or more modules are being unloaded.
+        return handleUnload(scriptObject);
+      }
 
+      TreeLogger logger = getHost().getLogger().branch(TreeLogger.DEBUG,
+          "Loading an instance of module '" + moduleName + "'");
+      try {
         if (!validHostedHtmlVersion(version)) {
           return false;
         }
 
         Object key = new Integer(scriptObject);
         // Attach a new ModuleSpace to make it programmable.
-        //
-        ModuleSpaceHost msh = getHost().createModuleSpaceHost(
+        ModuleSpaceHost msh = getHost().createModuleSpaceHost(logger,
             BrowserWidgetMoz.this, moduleName);
-        ModuleSpace moduleSpace = new ModuleSpaceMoz(msh, scriptObject,
+        ModuleSpace moduleSpace = new ModuleSpaceMoz(logger, msh, scriptObject,
             moduleName, key);
-        attachModuleSpace(moduleSpace);
+        attachModuleSpace(logger, moduleSpace);
         return true;
       } catch (Throwable e) {
         // We do catch Throwable intentionally because there are a ton of things
         // that can go wrong trying to load a module, including Error-derived
         // things like NoClassDefFoundError.
-        // 
-        getHost().getLogger().log(TreeLogger.ERROR,
-            "Failure to load module '" + moduleName + "'", e);
+        logger.log(TreeLogger.ERROR, "Failure to load module '" + moduleName
+            + "'", e);
         return false;
       }
     }
@@ -85,12 +83,19 @@
      * 
      * @param scriptObject window to unload, 0 if all
      */
-    protected void handleUnload(int scriptObject) {
-      Integer key = null;
-      if (scriptObject != 0) {
-        key = new Integer(scriptObject);
+    protected boolean handleUnload(int scriptObject) {
+      try {
+        Integer key = null;
+        if (scriptObject != 0) {
+          key = new Integer(scriptObject);
+        }
+        doUnload(key);
+        return true;
+      } catch (Throwable e) {
+        getHost().getLogger().log(TreeLogger.ERROR,
+            "Failure to unload modules", e);
+        return false;
       }
-      doUnload(key);
     }
   }
 
diff --git a/dev/linux/src/com/google/gwt/dev/shell/moz/ModuleSpaceMoz.java b/dev/linux/src/com/google/gwt/dev/shell/moz/ModuleSpaceMoz.java
index b6de40f..6ee992e 100644
--- a/dev/linux/src/com/google/gwt/dev/shell/moz/ModuleSpaceMoz.java
+++ b/dev/linux/src/com/google/gwt/dev/shell/moz/ModuleSpaceMoz.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.dev.shell.moz;
 
+import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.dev.shell.CompilingClassLoader;
 import com.google.gwt.dev.shell.JsValue;
 import com.google.gwt.dev.shell.JsValueGlue;
@@ -32,9 +33,9 @@
   /**
    * Constructs a browser interface for use with a Mozilla global window object.
    */
-  public ModuleSpaceMoz(ModuleSpaceHost host, int scriptGlobalObject,
-      String moduleName, Object key) {
-    super(host, moduleName, key);
+  public ModuleSpaceMoz(TreeLogger logger, ModuleSpaceHost host,
+      int scriptGlobalObject, String moduleName, Object key) {
+    super(logger, host, moduleName, key);
 
     // Hang on to the parent window.
     //
diff --git a/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java b/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java
index 3d0fe1a..a0097f1 100644
--- a/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java
+++ b/dev/mac/src/com/google/gwt/dev/shell/mac/BrowserWidgetSaf.java
@@ -52,13 +52,14 @@
     }
 
     public boolean gwtOnLoad(int scriptObject, String moduleName, String version) {
-      try {
-        if (moduleName == null) {
-          // Indicates one or more modules are being unloaded.
-          handleUnload(scriptObject);
-          return true;
-        }
+      if (moduleName == null) {
+        // Indicates one or more modules are being unloaded.
+        return handleUnload(scriptObject);
+      }
 
+      TreeLogger logger = getHost().getLogger().branch(TreeLogger.DEBUG,
+          "Loading an instance of module '" + moduleName + "'");
+      try {
         if (!validHostedHtmlVersion(version)) {
           return false;
         }
@@ -66,7 +67,7 @@
         // Attach a new ModuleSpace to make it programmable.
         //
         Integer key = new Integer(scriptObject);
-        ModuleSpaceHost msh = getHost().createModuleSpaceHost(
+        ModuleSpaceHost msh = getHost().createModuleSpaceHost(logger,
             BrowserWidgetSaf.this, moduleName);
 
         /*
@@ -76,17 +77,17 @@
          */
         final int globalContext = globalContexts.get(scriptObject).intValue();
 
-        ModuleSpace moduleSpace = new ModuleSpaceSaf(msh, scriptObject,
+        ModuleSpace moduleSpace = new ModuleSpaceSaf(logger, msh, scriptObject,
             globalContext, moduleName, key);
-        attachModuleSpace(moduleSpace);
+        attachModuleSpace(logger, moduleSpace);
         return true;
       } catch (Throwable e) {
         // We do catch Throwable intentionally because there are a ton of things
         // that can go wrong trying to load a module, including Error-dervied
         // things like NoClassDefFoundError.
         // 
-        getHost().getLogger().log(TreeLogger.ERROR,
-            "Failure to load module '" + moduleName + "'", e);
+        logger.log(TreeLogger.ERROR, "Failure to load module '" + moduleName
+            + "'", e);
         return false;
       }
     }
@@ -117,12 +118,19 @@
      * 
      * @param scriptObject window to unload, 0 if all
      */
-    protected void handleUnload(int scriptObject) {
-      Integer key = null;
-      if (scriptObject != 0) {
-        key = new Integer(scriptObject);
+    protected boolean handleUnload(int scriptObject) {
+      try {
+        Integer key = null;
+        if (scriptObject != 0) {
+          key = new Integer(scriptObject);
+        }
+        doUnload(key);
+        return true;
+      } catch (Throwable e) {
+        getHost().getLogger().log(TreeLogger.ERROR,
+            "Failure to unload modules", e);
+        return false;
       }
-      doUnload(key);
     }
   }
 
diff --git a/dev/mac/src/com/google/gwt/dev/shell/mac/ModuleSpaceSaf.java b/dev/mac/src/com/google/gwt/dev/shell/mac/ModuleSpaceSaf.java
index 1959d43..d4eaa4a 100644
--- a/dev/mac/src/com/google/gwt/dev/shell/mac/ModuleSpaceSaf.java
+++ b/dev/mac/src/com/google/gwt/dev/shell/mac/ModuleSpaceSaf.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.dev.shell.mac;
 
+import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.dev.shell.CompilingClassLoader;
 import com.google.gwt.dev.shell.JsValue;
 import com.google.gwt.dev.shell.JsValueGlue;
@@ -36,9 +37,10 @@
    * @param moduleName name of the module
    * @param key unique key for this instance of the module
    */
-  public ModuleSpaceSaf(ModuleSpaceHost host, int scriptGlobalObject,
-      int scriptGlobalContext, String moduleName, Object key) {
-    super(host, moduleName, key);
+  public ModuleSpaceSaf(TreeLogger logger, ModuleSpaceHost host,
+      int scriptGlobalObject, int scriptGlobalContext, String moduleName,
+      Object key) {
+    super(logger, host, moduleName, key);
 
     // Hang on to the global execution state.
     //
@@ -86,7 +88,7 @@
     int argc = args.length;
     int[] argv = new int[argc];
     // GC protect passed arguments on the Java stack for call duration.
-    JsValueSaf[] jsValueArgs = new JsValueSaf[argc]; 
+    JsValueSaf[] jsValueArgs = new JsValueSaf[argc];
     for (int i = 0; i < argc; ++i) {
       JsValueSaf jsValue = jsValueArgs[i] = new JsValueSaf();
       JsValueGlue.set(jsValue, isolatedClassLoader, types[i], args[i]);
diff --git a/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java b/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java
index 6e3aa62..ead6a81 100644
--- a/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java
+++ b/dev/windows/src/com/google/gwt/dev/shell/ie/BrowserWidgetIE6.java
@@ -51,13 +51,14 @@
      */
     public boolean gwtOnLoad(IDispatch frameWnd, String moduleName,
         String version) {
-      try {
-        if (moduleName == null) {
-          // Indicates one or more modules are being unloaded.
-          handleUnload(frameWnd);
-          return true;
-        }
+      if (moduleName == null) {
+        // Indicates one or more modules are being unloaded.
+        return handleUnload(frameWnd);
+      }
 
+      TreeLogger logger = getHost().getLogger().branch(TreeLogger.DEBUG,
+          "Loading an instance of module '" + moduleName + "'");
+      try {
         if (!validHostedHtmlVersion(version)) {
           throw new HResultException(COM.E_INVALIDARG);
         }
@@ -69,19 +70,19 @@
 
         // Attach a new ModuleSpace to make it programmable.
         //
-        ModuleSpaceHost msh = getHost().createModuleSpaceHost(
+        ModuleSpaceHost msh = getHost().createModuleSpaceHost(logger,
             BrowserWidgetIE6.this, moduleName);
-        ModuleSpaceIE6 moduleSpace = new ModuleSpaceIE6(msh, frameWnd,
+        ModuleSpaceIE6 moduleSpace = new ModuleSpaceIE6(logger, msh, frameWnd,
             moduleName, key);
-        attachModuleSpace(moduleSpace);
+        attachModuleSpace(logger, moduleSpace);
         return true;
       } catch (Throwable e) {
         // We do catch Throwable intentionally because there are a ton of things
         // that can go wrong trying to load a module, including Error-derived
         // things like NoClassDefFoundError.
         // 
-        getHost().getLogger().log(TreeLogger.ERROR,
-            "Failure to load module '" + moduleName + "'", e);
+        logger.log(TreeLogger.ERROR, "Failure to load module '" + moduleName
+            + "'", e);
         return false;
       }
     }
@@ -122,12 +123,19 @@
      * 
      * @param frameWnd window to unload, null if all
      */
-    protected void handleUnload(IDispatch frameWnd) {
-      Integer key = null;
-      if (frameWnd != null) {
-        key = new Integer(getIntProperty(frameWnd, "__gwt_module_id"));
+    protected boolean handleUnload(IDispatch frameWnd) {
+      try {
+        Integer key = null;
+        if (frameWnd != null) {
+          key = new Integer(getIntProperty(frameWnd, "__gwt_module_id"));
+        }
+        doUnload(key);
+        return true;
+      } catch (Throwable e) {
+        getHost().getLogger().log(TreeLogger.ERROR,
+            "Failure to unload modules", e);
+        return false;
       }
-      doUnload(key);
     }
 
     @Override
diff --git a/dev/windows/src/com/google/gwt/dev/shell/ie/ModuleSpaceIE6.java b/dev/windows/src/com/google/gwt/dev/shell/ie/ModuleSpaceIE6.java
index 2ff7941..9a91973 100644
--- a/dev/windows/src/com/google/gwt/dev/shell/ie/ModuleSpaceIE6.java
+++ b/dev/windows/src/com/google/gwt/dev/shell/ie/ModuleSpaceIE6.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.dev.shell.ie;
 
+import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.dev.shell.CompilingClassLoader;
 import com.google.gwt.dev.shell.JsValue;
 import com.google.gwt.dev.shell.ModuleSpace;
@@ -85,9 +86,9 @@
    * 
    * @param moduleName
    */
-  public ModuleSpaceIE6(ModuleSpaceHost host, IDispatch scriptFrameWindow,
-      String moduleName, Object key) {
-    super(host, moduleName, key);
+  public ModuleSpaceIE6(TreeLogger logger, ModuleSpaceHost host,
+      IDispatch scriptFrameWindow, String moduleName, Object key) {
+    super(logger, host, moduleName, key);
 
     window = new OleAutomation(scriptFrameWindow);
   }