Fixes Issue #1792
Added separate build targets on OSX for 10.4 and 10.5 and updated
hosted mode and junit support to work around a 10.5 issues.

Patch by: fabbott, knorton
Review by: jat (desk)



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2000 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/common.ant.xml b/common.ant.xml
index 8a5afa2..8575f4d 100755
--- a/common.ant.xml
+++ b/common.ant.xml
@@ -17,7 +17,7 @@
 		<equals arg1="${ant.file}" arg2="${test.ant.file}"
                   casesensitive="${gwt.build.iscasesensitivefs}"/>
 	</condition>
-	<fail unless="project.valid" message="This build file is in an inconsistent state." />
+	<fail unless="project.valid" message="This build file is in an inconsistent state (${ant.file} != ${test.ant.file})." />
 
 	<!-- Global Properties -->
 	<property environment="env" />
@@ -74,7 +74,19 @@
 		</and>
 	</condition>
 	<condition property="build.host.platform" value="mac">
-		<isset property="build.host.ismac" />
+            <isset property="build.host.ismac" />
+	</condition>
+	<condition property="build.host.platform.detail" value="mac_10.5">
+		<and>
+			<isset property="build.host.ismac" />
+			<contains string="${os.version}" substring="10.5." />
+		</and>
+	</condition>
+	<condition property="build.host.platform.detail" value="mac_10.4">
+		<and>
+			<isset property="build.host.ismac" />
+			<contains string="${os.version}" substring="10.4." />
+		</and>
 	</condition>
 
 	<condition property="build.host.iswindows">
@@ -85,12 +97,17 @@
 	</condition>
 	<fail unless="build.host.platform" message="Building on ${os.name} is not supported" />
 
+	<!-- for OS's that don't need to set a detail revision 
+             (i.e. as of 3mar08, all but MacOS) -->
+	<property name="build.host.platform.detail" 
+	          value="${build.host.platform}" />
+
 	<condition property="junit.platform.args" value="-XstartOnFirstThread" else="">
-		<equals arg1="${build.host.platform}" arg2="mac" casesensitive="false" />
+		<isset property="build.host.ismac" />
 	</condition>
 
 	<!-- JUnit support -->
-	<property name="gwt.dev.staging.jar" location="${gwt.build.staging}/gwt-${build.host.platform}-${gwt.version}/gwt-dev-${build.host.platform}.jar" />
+	<property name="gwt.dev.staging.jar" location="${gwt.build.staging}/gwt-${build.host.platform.detail}-${gwt.version}/gwt-dev-${build.host.platform}.jar" />
 	<property name="gwt.junit.port" value="8888" />
 	<property name="gwt.junit.testcase.includes" value="**/*Suite.class"/>
 	
@@ -172,7 +189,7 @@
 		<element name="tar.elements" implicit="true" optional="true" />
 		<sequential>
 			<taskdef name="tar.cat" classname="com.google.gwt.ant.taskdefs.TarCat" classpath="${gwt.build.lib}/ant-gwt.jar" />
-			<tar.cat destfile="${project.dist}" compression="gzip" longfile="gnu">
+			<tar.cat destfile="@{destfile}" compression="gzip" longfile="gnu">
 				<tar.elements />
 			</tar.cat>
 		</sequential>
diff --git a/dev/core/src-dummy/com/google/gwt/dev/BootStrapPlatform.java b/dev/core/src-dummy/com/google/gwt/dev/BootStrapPlatform.java
index d9c2bde..de80543 100644
--- a/dev/core/src-dummy/com/google/gwt/dev/BootStrapPlatform.java
+++ b/dev/core/src-dummy/com/google/gwt/dev/BootStrapPlatform.java
@@ -22,15 +22,15 @@
  */
 public class BootStrapPlatform {
 
-  public static void go() {
+  public static void applyPlatformHacks() {
     // nothing to do
   }
 
+  public static void init() {
+    // nothing to do.
+  }
+
   public static void maybeInitializeAWT() {
     // nothing to do
   }
-  
-  public static void setSystemProperties() {
-    // nothing to do.
-  }
 }
diff --git a/dev/core/src/com/google/gwt/dev/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
index a97e0dc..2de4086 100644
--- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
@@ -580,7 +580,7 @@
    */
   private boolean run() {
     // Set any platform specific system properties.
-    BootStrapPlatform.setSystemProperties();
+    BootStrapPlatform.applyPlatformHacks();
 
     if (useGuiLogger) {
       // Initialize a tree logger window.
diff --git a/dev/core/src/com/google/gwt/dev/GWTShell.java b/dev/core/src/com/google/gwt/dev/GWTShell.java
index 2b0f908..ac742c1 100644
--- a/dev/core/src/com/google/gwt/dev/GWTShell.java
+++ b/dev/core/src/com/google/gwt/dev/GWTShell.java
@@ -368,7 +368,7 @@
      * shutdown AWT related threads, since the contract for their termination is
      * still implementation-dependent.
      */
-    BootStrapPlatform.go();
+    BootStrapPlatform.init();
     GWTShell shellMain = new GWTShell();
     if (shellMain.processArgs(args)) {
       shellMain.run();
@@ -591,7 +591,7 @@
   public void run() {
     try {
       // Set any platform specific system properties.
-      BootStrapPlatform.setSystemProperties();
+      BootStrapPlatform.applyPlatformHacks();
 
       if (!startUp()) {
         // Failed to initalize.
diff --git a/dev/linux/src/com/google/gwt/dev/BootStrapPlatform.java b/dev/linux/src/com/google/gwt/dev/BootStrapPlatform.java
index a5cc0c8..e297690 100644
--- a/dev/linux/src/com/google/gwt/dev/BootStrapPlatform.java
+++ b/dev/linux/src/com/google/gwt/dev/BootStrapPlatform.java
@@ -22,13 +22,17 @@
  */
 public class BootStrapPlatform {
 
+  public static void applyPlatformHacks() {
+    // nothing to do
+  }
+
   /**
    * Find a usable Mozilla installation and load it. Fail immediately, logging
    * to stderr and exiting with a failure code, if we are unable to find or load
    * it. If successful, store the loaded path in the property swt.mozilla.path
    * so SWT's Browser object can use it.
    */
-  public static void go() {
+  public static void init() {
     MozillaInstall mozInstall = MozillaInstall.find();
     if (mozInstall == null) {
       System.err.println("** Unable to find a usable Mozilla install **");
@@ -50,8 +54,4 @@
   public static void maybeInitializeAWT() {
     // nothing to do
   }
-
-  public static void setSystemProperties() {
-    // nothing to do
-  }
 }
diff --git a/dev/mac/src/com/google/gwt/dev/BootStrapPlatform.java b/dev/mac/src/com/google/gwt/dev/BootStrapPlatform.java
index 3ef423a..559e59a 100644
--- a/dev/mac/src/com/google/gwt/dev/BootStrapPlatform.java
+++ b/dev/mac/src/com/google/gwt/dev/BootStrapPlatform.java
@@ -17,6 +17,7 @@
 
 import com.google.gwt.dev.shell.mac.LowLevelSaf;
 
+import java.awt.GraphicsEnvironment;
 import java.awt.Toolkit;
 
 /**
@@ -24,23 +25,24 @@
  */
 public class BootStrapPlatform {
 
-  public static void go() {
-    // Ensure we were started with -XstartOnFirstThread
+  public static void applyPlatformHacks() {
+    setSystemProperties();
+    fixContextClassLoaderOnMainThread();
+  }
+
+  public static void init() {
     LowLevelSaf.init();
-    String[] args = LowLevelSaf.getProcessArgs();
-    for (int i = 0; i < args.length; ++i) {
-      if (args[i].equalsIgnoreCase("-xstartonfirstthread")) {
-        return;
-      }
+    // Ensure we were started with -XstartOnFirstThread
+    if (!hasStartOnFirstThreadFlag(LowLevelSaf.getProcessArgs())) {
+      System.err.println("Invalid launch configuration: -XstartOnFirstThread not specified.");
+      System.err.println();
+      System.err.println("On Mac OS X, GWT requires that the Java virtual machine be invoked with the");
+      System.err.println("-XstartOnFirstThread VM argument.");
+      System.err.println();
+      System.err.println("Example:");
+      System.err.println("  java -XstartOnFirstThread -cp gwt-dev-mac.jar com.google.gwt.dev.GWTShell");
+      System.exit(-1);
     }
-    System.err.println("Invalid launch configuration: -XstartOnFirstThread not specified.");
-    System.err.println();
-    System.err.println("On Mac OS X, GWT requires that the Java virtual machine be invoked with the");
-    System.err.println("-XstartOnFirstThread VM argument.");
-    System.err.println();
-    System.err.println("Example:");
-    System.err.println("  java -XstartOnFirstThread -cp gwt-dev-mac.jar com.google.gwt.dev.GWTShell");
-    System.exit(-1);
   }
 
   /**
@@ -65,30 +67,55 @@
    * <p>
    * NOTE: In GUI applications, {@link #setSystemProperties()} and
    * {@link #maybeInitializeAWT()} will both be called during the bootstrap
-   * process. Command line applications (like 
-   * @{link com.google.gwt.dev.GWTCompiler}) avoid eagerly initializing AWT
-   * and only call {@link #setSystemProperties()} allowing AWT to be
-   * initialized on demand.
-   * </p>
+   * process. Command line applications (like
+   * 
+   * @{link com.google.gwt.dev.GWTCompiler}) avoid eagerly initializing AWT and
+   *        only call {@link #setSystemProperties()} allowing AWT to be
+   *        initialized on demand.
+   *        </p>
    */
   public static void maybeInitializeAWT() {
+    GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
     Toolkit.getDefaultToolkit();
   }
 
   /**
+   * This works around apple radr:5569300. When -XstartOnFirstThread is passed
+   * as a jvm argument, the main thread returns null for
+   * {@link Thread#getContextClassLoader()}.
+   */
+  private static void fixContextClassLoaderOnMainThread() {
+    final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+    if (classLoader == null) {
+      Thread.currentThread().setContextClassLoader(
+          BootStrapPlatform.class.getClassLoader());
+    }
+  }
+
+  private static boolean hasStartOnFirstThreadFlag(String[] args) {
+    for (int i = 0; i < args.length; ++i) {
+      if (args[i].equalsIgnoreCase("-xstartonfirstthread")) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
    * Sets platform specific system properties. Currently, this disables
    * CocoaComponent CompatibilityMode.
    * 
    * <p>
    * NOTE: In GUI applications, {@link #setSystemProperties()} and
    * {@link #maybeInitializeAWT()} will both be called during the bootstrap
-   * process. Command line applications (like 
-   * @{link com.google.gwt.dev.GWTCompiler}) avoid eagerly initializing AWT
-   * and only call {@link #setSystemProperties()} allowing AWT to be
-   * initialized on demand.
-   * </p>
+   * process. Command line applications (like
+   * 
+   * @{link com.google.gwt.dev.GWTCompiler}) avoid eagerly initializing AWT and
+   *        only call {@link #setSystemProperties()} allowing AWT to be
+   *        initialized on demand.
+   *        </p>
    */
-  public static void setSystemProperties() {
+  private static void setSystemProperties() {
     // Disable CocoaComponent compatibility mode.
     System.setProperty("com.apple.eawt.CocoaComponent.CompatibilityMode",
         "false");
diff --git a/dev/windows/src/com/google/gwt/dev/BootStrapPlatform.java b/dev/windows/src/com/google/gwt/dev/BootStrapPlatform.java
index fc19628..180c39b 100644
--- a/dev/windows/src/com/google/gwt/dev/BootStrapPlatform.java
+++ b/dev/windows/src/com/google/gwt/dev/BootStrapPlatform.java
@@ -20,15 +20,15 @@
  */
 public class BootStrapPlatform {
 
-  public static void go() {
+  public static void applyPlatformHacks() {
     // nothing to do
   }
   
+  public static void init() {
+    // nothing to do
+  }
+
   public static void maybeInitializeAWT() {
     // nothing to do
   }
-  
-  public static void setSystemProperties() {
-    // nothing to do
-  }
 }
diff --git a/distro-source/common.ant.xml b/distro-source/common.ant.xml
index e5904f5..661e610 100755
--- a/distro-source/common.ant.xml
+++ b/distro-source/common.ant.xml
@@ -3,7 +3,7 @@
 	<property name="project.tail" value="distro-source/${dist.platform}" />
 	<import file="${gwt.root}/common.ant.xml" />
 
-	<property name="project.distname" value="gwt-${dist.platform}-${gwt.version}" />
+	<property name="project.distname" value="gwt-${dist.platform.detail}-${gwt.version}" />
 	<property name="project.staging" location="${gwt.build.staging}/${project.distname}" />
 
 	<patternset id="chmod.executables">
diff --git a/distro-source/linux/build.xml b/distro-source/linux/build.xml
index 4abbb34..6ffb9eb 100755
--- a/distro-source/linux/build.xml
+++ b/distro-source/linux/build.xml
@@ -1,5 +1,6 @@
 <project name="dist-linux" default="build" basedir=".">
 	<property name="dist.platform" value="linux" />
+	<property name="dist.platform.detail" value="linux" />
 	<import file="../common.ant.xml" />
 	<property name="project.dist" location="${gwt.build.dist}/${project.distname}.tar.gz" />
 
diff --git a/distro-source/mac/src/libswt-webkit-carbon-3235.jnilib b/distro-source/mac/10.4/libswt-webkit-carbon-3235.jnilib
similarity index 100%
rename from distro-source/mac/src/libswt-webkit-carbon-3235.jnilib
rename to distro-source/mac/10.4/libswt-webkit-carbon-3235.jnilib
Binary files differ
diff --git a/distro-source/mac/10.5/libswt-webkit-carbon-3235.jnilib b/distro-source/mac/10.5/libswt-webkit-carbon-3235.jnilib
new file mode 100755
index 0000000..e61e653
--- /dev/null
+++ b/distro-source/mac/10.5/libswt-webkit-carbon-3235.jnilib
Binary files differ
diff --git a/distro-source/mac/build.xml b/distro-source/mac/build.xml
index 00f111f..6b272c5 100755
--- a/distro-source/mac/build.xml
+++ b/distro-source/mac/build.xml
@@ -1,42 +1,69 @@
 <project name="dist-mac" default="build" basedir=".">
+	<!-- TODO: Either split this into top-level mac-10.4 and mac-10.5 targets
+		or merge these back together with OOPHM. -->
+        <!-- distro doesn't use the top-level common.ant.xml, nor properties
+             defined there. -->
 	<property name="dist.platform" value="mac" />
-	<import file="../common.ant.xml" />
-	<property name="project.dist" location="${gwt.build.dist}/${project.distname}.tar.gz" />
+	<condition property="dist.platform.detail" value="mac_10.5" else="mac_10.4">
+		<contains string="${os.version}" substring="10.5." />
+	</condition>
 
-	<target name="build" depends="filter" description="Packages the distro">
+	<property name="project.distname_10.4" value="gwt-mac_10.4-${gwt.version}" />
+	<property name="project.distname_10.5" value="gwt-mac_10.5-${gwt.version}" />
+
+	<import file="../common.ant.xml" />
+	<condition property="webkitrev" value="525-10.5" else="418.9">
+		<equals arg1="mac_10.5" arg2="${build.host.platform.detail}" />
+	</condition>
+	<property name="project_10_4.dist" location="${gwt.build.dist}/gwt-mac_10.4-${gwt.version}.tar.gz" />
+	<property name="project_10_5.dist" location="${gwt.build.dist}/gwt-mac_10.5-${gwt.version}.tar.gz" />
+
+
+	<target name="build" depends="filter, build_10.4, build_10.5" 
+		description="Packages the distro">
+	</target> 
+
+	<target name="build_10.4" depends="filter" 
+	        description="Packages the MacOS 10.4 distro">
 		<!-- TODO: figure out how to share most of this across platforms -->
 		<mkdir dir="${gwt.build.dist}" />
-		<gwt.tgz.cat destfile="${project.dist}">
+		<gwt.tgz.cat destfile="${project_10_4.dist}">
 			<!-- jars -->
-			<tarfileset file="${gwt.build.lib}/gwt-dev-${dist.platform}.jar" prefix="${project.distname}" />
-			<tarfileset file="${gwt.build.lib}/gwt-user.jar" prefix="${project.distname}" />
-			<tarfileset file="${gwt.build.lib}/gwt-servlet.jar" prefix="${project.distname}" />
-                        <tarfileset file="${gwt.build.lib}/gwt-benchmark-viewer.jar" prefix="${project.distname}" />
+			<tarfileset file="${gwt.build.lib}/gwt-dev-${build.host.platform}.jar" prefix="${project.distname_10.4}" />
+			<tarfileset file="${gwt.build.lib}/gwt-user.jar" prefix="${project.distname_10.4}" />
+			<tarfileset file="${gwt.build.lib}/gwt-servlet.jar" prefix="${project.distname_10.4}" />
+                        <tarfileset file="${gwt.build.lib}/gwt-benchmark-viewer.jar" prefix="${project.distname_10.4}" />
 
 			<!-- jni libs-->
-			<tarfileset dir="${gwt.build.jni}/${dist.platform}" prefix="${project.distname}" />
-			<tarfileset dir="${gwt.tools.lib}/eclipse" prefix="${project.distname}">
+			<tarfileset dir="${gwt.build.jni}/mac_10.4" prefix="${project.distname_10.4}" />
+			<tarfileset dir="${gwt.tools.lib}/eclipse" prefix="${project.distname_10.4}">
 				<include name="libswt-*carbon-3235.jnilib" />
 				<!-- User our modified version instead of this stock version -->
 				<exclude name="libswt-webkit-carbon-3235.jnilib" />
 			</tarfileset>
 
 			<!-- raw files -->
-			<tarfileset dir="${project.build}" prefix="${project.distname}" mode="755">
+			<tarfileset dir="${project.build}" prefix="${project.distname_10.4}" mode="755">
 				<patternset refid="chmod.executables" />
 			</tarfileset>
-			<tarfileset dir="${project.build}" prefix="${project.distname}">
+			<tarfileset dir="${project.build}" prefix="${project.distname_10.4}">
 				<patternset refid="chmod.not.executables" />
 			</tarfileset>
-			<tarfileset dir="src" prefix="${project.distname}" mode="755">
+			<tarfileset dir="src" prefix="${project.distname_10.4}" mode="755">
 				<patternset refid="chmod.executables" />
 			</tarfileset>
-			<tarfileset dir="src" prefix="${project.distname}">
+			<tarfileset dir="10.4" prefix="${project.distname_10.4}" mode="755">
+				<patternset refid="chmod.executables" />
+			</tarfileset>
+			<tarfileset dir="src" prefix="${project.distname_10.4}">
+				<patternset refid="chmod.not.executables" />
+			</tarfileset>
+			<tarfileset dir="10.4" prefix="${project.distname_10.4}">
 				<patternset refid="chmod.not.executables" />
 			</tarfileset>
 
 			<!-- doc -->
-			<tarfileset dir="${gwt.build.out}" prefix="${project.distname}">
+			<tarfileset dir="${gwt.build.out}" prefix="${project.distname_10.4}">
 				<include name="doc" />
 				<include name="doc/html/**" />
 				<include name="doc/css/**" />
@@ -44,19 +71,19 @@
 			</tarfileset>
 
 			<!-- samples -->
-			<tarfileset dir="${gwt.build.out}" prefix="${project.distname}">
+			<tarfileset dir="${gwt.build.out}" prefix="${project.distname_10.4}">
 				<include name="samples" />
 				<include name="samples/*" />
 				<include name="samples/*/src/**" />
 				<include name="samples/*/bin/**" />
 				<include name="samples/*/www/**" />
 			</tarfileset>
-			<tarfileset dir="${gwt.build.out}/samples-scripts/${dist.platform}" mode="755" prefix="${project.distname}/samples">
+			<tarfileset dir="${gwt.build.out}/samples-scripts/${dist.platform}" mode="755" prefix="${project.distname_10.4}/samples">
 				<include name="*/*-compile" />
 				<include name="*/*-shell" />
 			</tarfileset>
 
-			<includetar src="${gwt.tools.redist}/webkit/WebKit-418.9.tar.gz" compression="gzip" prefix="${project.distname}" />
+			<includetar src="${gwt.tools.redist}/webkit/WebKit-${webkitrev}.tar.gz" compression="gzip" prefix="${project.distname_10.4}" />
 		</gwt.tgz.cat>
 
 		<if>
@@ -69,7 +96,88 @@
 				<mkdir dir="${gwt.build.staging}" />
 				<exec executable="tar">
 					<arg value="-xpzf" />
-					<arg file="${project.dist}" />
+					<arg file="${project_10_4.dist}" />
+					<arg value="-C" />
+					<arg file="${gwt.build.staging}" />
+				</exec>
+			</then>
+		</if>
+	</target>
+
+	<target name="build_10.5" depends="filter" 
+	        description="Packages the MacOS 10.5 distro">
+		<!-- TODO: figure out how to share most of this across platforms -->
+		<mkdir dir="${gwt.build.dist}" />
+		<gwt.tgz.cat destfile="${project_10_5.dist}">
+			<!-- jars -->
+			<tarfileset file="${gwt.build.lib}/gwt-dev-${build.host.platform}.jar" prefix="${project.distname_10.5}" />
+			<tarfileset file="${gwt.build.lib}/gwt-user.jar" prefix="${project.distname_10.5}" />
+			<tarfileset file="${gwt.build.lib}/gwt-servlet.jar" prefix="${project.distname_10.5}" />
+                        <tarfileset file="${gwt.build.lib}/gwt-benchmark-viewer.jar" prefix="${project.distname_10.5}" />
+
+			<!-- jni libs-->
+			<tarfileset dir="${gwt.build.jni}/mac_10.5" prefix="${project.distname_10.5}" />
+			<tarfileset dir="${gwt.tools.lib}/eclipse" prefix="${project.distname_10.5}">
+				<include name="libswt-*carbon-3235.jnilib" />
+				<!-- User our modified version instead of this stock version -->
+				<exclude name="libswt-webkit-carbon-3235.jnilib" />
+			</tarfileset>
+
+			<!-- raw files -->
+			<tarfileset dir="${project.build}" prefix="${project.distname_10.5}" mode="755">
+				<patternset refid="chmod.executables" />
+			</tarfileset>
+			<tarfileset dir="${project.build}" prefix="${project.distname_10.5}">
+				<patternset refid="chmod.not.executables" />
+			</tarfileset>
+			<tarfileset dir="src" prefix="${project.distname_10.5}" mode="755">
+				<patternset refid="chmod.executables" />
+			</tarfileset>
+			<tarfileset dir="10.4" prefix="${project.distname_10.5}" mode="755">
+				<patternset refid="chmod.executables" />
+			</tarfileset>
+			<tarfileset dir="src" prefix="${project.distname_10.5}">
+				<patternset refid="chmod.not.executables" />
+			</tarfileset>
+			<tarfileset dir="10.4" prefix="${project.distname_10.5}">
+				<patternset refid="chmod.not.executables" />
+			</tarfileset>
+
+			<!-- doc -->
+			<tarfileset dir="${gwt.build.out}" prefix="${project.distname_10.5}">
+				<include name="doc" />
+				<include name="doc/html/**" />
+				<include name="doc/css/**" />
+				<include name="doc/javadoc/**" />
+			</tarfileset>
+
+			<!-- samples -->
+			<tarfileset dir="${gwt.build.out}" prefix="${project.distname_10.5}">
+				<include name="samples" />
+				<include name="samples/*" />
+				<include name="samples/*/src/**" />
+				<include name="samples/*/bin/**" />
+				<include name="samples/*/www/**" />
+			</tarfileset>
+			<tarfileset dir="${gwt.build.out}/samples-scripts/${dist.platform}" mode="755" prefix="${project.distname_10.5}/samples">
+				<include name="*/*-compile" />
+				<include name="*/*-shell" />
+			</tarfileset>
+
+			<includetar src="${gwt.tools.redist}/webkit/WebKit-${webkitrev}.tar.gz" compression="gzip" prefix="${project.distname_10.5}" />
+		</gwt.tgz.cat>
+
+		<if>
+			<isset property="build.host.ismac" />
+			<then>
+				<!--
+					Untar distro into the staging directory.  Must use GNU tar
+					to handle permissions and symlinks correctly.
+				-->
+				<mkdir dir="${gwt.build.staging}" />
+				<exec executable="tar">
+					<arg value="-xpzf" />
+					<arg file="${project_10_5.dist}" />
 					<arg value="-C" />
 					<arg file="${gwt.build.staging}" />
 				</exec>
diff --git a/distro-source/windows/build.xml b/distro-source/windows/build.xml
index 8fce756..87f9c22 100755
--- a/distro-source/windows/build.xml
+++ b/distro-source/windows/build.xml
@@ -1,5 +1,6 @@
 <project name="dist-windows" default="build" basedir=".">
 	<property name="dist.platform" value="windows" />
+	<property name="dist.platform.detail" value="windows" />
 	<import file="../common.ant.xml" />
 	<property name="project.dist" location="${gwt.build.dist}/${project.distname}.zip" />
 
diff --git a/jni/mac/DispWrapper.cpp b/jni/mac/10.4/DispWrapper.cpp
similarity index 100%
rename from jni/mac/DispWrapper.cpp
rename to jni/mac/10.4/DispWrapper.cpp
diff --git a/jni/mac/DispWrapper.h b/jni/mac/10.4/DispWrapper.h
similarity index 100%
rename from jni/mac/DispWrapper.h
rename to jni/mac/10.4/DispWrapper.h
diff --git a/jni/mac/FuncWrapper.cpp b/jni/mac/10.4/FuncWrapper.cpp
similarity index 100%
rename from jni/mac/FuncWrapper.cpp
rename to jni/mac/10.4/FuncWrapper.cpp
diff --git a/jni/mac/FuncWrapper.h b/jni/mac/10.4/FuncWrapper.h
similarity index 100%
rename from jni/mac/FuncWrapper.h
rename to jni/mac/10.4/FuncWrapper.h
diff --git a/jni/mac/FunctionObject.cpp b/jni/mac/10.4/FunctionObject.cpp
similarity index 100%
rename from jni/mac/FunctionObject.cpp
rename to jni/mac/10.4/FunctionObject.cpp
diff --git a/jni/mac/FunctionObject.h b/jni/mac/10.4/FunctionObject.h
similarity index 100%
rename from jni/mac/FunctionObject.h
rename to jni/mac/10.4/FunctionObject.h
diff --git a/jni/mac/JStringWrap.h b/jni/mac/10.4/JStringWrap.h
similarity index 100%
rename from jni/mac/JStringWrap.h
rename to jni/mac/10.4/JStringWrap.h
diff --git a/jni/mac/Makefile b/jni/mac/10.4/Makefile
similarity index 96%
rename from jni/mac/Makefile
rename to jni/mac/10.4/Makefile
index e0614ee..752cb4a 100644
--- a/jni/mac/Makefile
+++ b/jni/mac/10.4/Makefile
@@ -15,7 +15,7 @@
 ##
 # Try a GWT_TOOLS default if it isn't set
 ##
-GWT_TOOLS ?= ../../../tools
+GWT_TOOLS ?= ../../../../tools
 
 ##
 # External WebKit products.
@@ -99,8 +99,8 @@
 ##
 # Rule for gwt-ll objects.
 ##
-gwt-ll.o: ../core/gwt-ll.cpp
-	$(CC) -c -o gwt-ll.o $(CFLAGS) ../core/gwt-ll.cpp
+gwt-ll.o: ../../core/gwt-ll.cpp
+	$(CC) -c -o gwt-ll.o $(CFLAGS) ../../core/gwt-ll.cpp
 
 gwt-args.o: gwt-args.cpp
 	$(CC) -c -o gwt-args.o $(CFLAGS) gwt-args.cpp
diff --git a/jni/mac/fix-install-name.sh b/jni/mac/10.4/fix-install-name.sh
similarity index 100%
rename from jni/mac/fix-install-name.sh
rename to jni/mac/10.4/fix-install-name.sh
diff --git a/jni/mac/gwt-args.cpp b/jni/mac/10.4/gwt-args.cpp
similarity index 100%
rename from jni/mac/gwt-args.cpp
rename to jni/mac/10.4/gwt-args.cpp
diff --git a/jni/mac/gwt-ll.h b/jni/mac/10.4/gwt-ll.h
similarity index 100%
rename from jni/mac/gwt-ll.h
rename to jni/mac/10.4/gwt-ll.h
diff --git a/jni/mac/gwt-webkit.cpp b/jni/mac/10.4/gwt-webkit.cpp
similarity index 100%
rename from jni/mac/gwt-webkit.cpp
rename to jni/mac/10.4/gwt-webkit.cpp
diff --git a/jni/mac/gwt-webkit.h b/jni/mac/10.4/gwt-webkit.h
similarity index 100%
rename from jni/mac/gwt-webkit.h
rename to jni/mac/10.4/gwt-webkit.h
diff --git a/jni/mac/localize-framework-install-names.rb b/jni/mac/10.4/localize-framework-install-names.rb
similarity index 100%
rename from jni/mac/localize-framework-install-names.rb
rename to jni/mac/10.4/localize-framework-install-names.rb
diff --git a/jni/mac/org.eclipse.swt/make_macosx.mak b/jni/mac/10.4/org.eclipse.swt/make_macosx.mak
similarity index 95%
rename from jni/mac/org.eclipse.swt/make_macosx.mak
rename to jni/mac/10.4/org.eclipse.swt/make_macosx.mak
index af9ea3b..25fdf55 100644
--- a/jni/mac/org.eclipse.swt/make_macosx.mak
+++ b/jni/mac/10.4/org.eclipse.swt/make_macosx.mak
@@ -30,7 +30,7 @@
 #SWT_DEBUG = -g
 ARCHS = -arch i386 -arch ppc
 CFLAGS = -c $(ARCHS) -DSWT_VERSION=$(SWT_VERSION) $(NATIVE_STATS) $(SWT_DEBUG) -DCARBON -I /System/Library/Frameworks/JavaVM.framework/Headers
-LFLAGS = -bundle $(ARCHS) -framework JavaVM -framework Carbon -isysroot /Developer/SDKs/MacOSX10.4u.sdk
+LFLAGS = -bundle $(ARCHS) -framework JavaVM -framework Carbon
 WEBKITCFLAGS = -c $(ARCHS) -xobjective-c -I /System/Library/Frameworks/JavaVM.framework/Headers -I /System/Library/Frameworks/Cocoa.framework/Headers -I /System/Library/Frameworks/WebKit.framework/Headers
 WEBKITLFLAGS = $(LFLAGS) -framework WebKit -framework Cocoa -framework WebCore -framework JavaScriptCore -F../Frameworks
 AGLLFLAGS = $(LFLAGS) -framework OpenGL -framework AGL
diff --git a/jni/mac/org.eclipse.swt/webkit.c b/jni/mac/10.4/org.eclipse.swt/webkit.c
similarity index 100%
rename from jni/mac/org.eclipse.swt/webkit.c
rename to jni/mac/10.4/org.eclipse.swt/webkit.c
diff --git a/jni/mac/prebuilt/libgwt-ll.jnilib b/jni/mac/10.4/prebuilt/libgwt-ll.jnilib
similarity index 100%
rename from jni/mac/prebuilt/libgwt-ll.jnilib
rename to jni/mac/10.4/prebuilt/libgwt-ll.jnilib
Binary files differ
diff --git a/jni/mac/prebuilt/libgwt-webkit.jnilib b/jni/mac/10.4/prebuilt/libgwt-webkit.jnilib
similarity index 100%
rename from jni/mac/prebuilt/libgwt-webkit.jnilib
rename to jni/mac/10.4/prebuilt/libgwt-webkit.jnilib
Binary files differ
diff --git a/jni/mac/10.5/DispWrapper.cpp b/jni/mac/10.5/DispWrapper.cpp
new file mode 100644
index 0000000..cc84c92
--- /dev/null
+++ b/jni/mac/10.5/DispWrapper.cpp
@@ -0,0 +1,159 @@
+/* 
+ * Copyright 2007 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+#include "DispWrapper.h"
+#include "FunctionObject.h"
+
+using namespace KJS;
+
+const ClassInfo DispWrapper::info = {"DispWrapper", 0, 0};
+
+JSValue *DispWrapper::getter(ExecState* exec, JSObject* thisObj,
+    const Identifier& propertyName, const PropertySlot& slot)
+{
+  TRACE("ENTER DispWrapper::getter");
+  if (propertyName.ustring() == "toString") {
+    return new ToStringFunction();
+  }
+  if (thisObj->classInfo() == &DispWrapper::info) {
+    DispWrapper* dispWrap = static_cast<DispWrapper*>(thisObj);
+    jobject dispObj = dispWrap->dispObj;
+    jstring jpropName = gEnv->NewString((const jchar*)propertyName.data(),
+        propertyName.size());
+    if (!jpropName || gEnv->ExceptionCheck()) {
+      gEnv->ExceptionClear();
+      return jsUndefined();
+    }
+    jint result = gEnv->CallIntMethod(dispObj, gGetFieldMeth, jpropName);
+    if (!result || gEnv->ExceptionCheck()) {
+      gEnv->ExceptionClear();
+      return jsUndefined();
+    }
+    TRACE("SUCCESS DispWrapper::getter");
+    return (JSValue*)result;
+  }
+  return jsUndefined();
+}
+
+/*
+ * Construct a JavaScript wrapper around a WebKitDispatchAdapter object.
+ * 
+ * dispObj a GlobalRef to the Java object to wrap
+ */
+DispWrapper::DispWrapper(jobject dispObj): dispObj(dispObj) { }
+
+/*
+ * Free GlobalRef on the underlying WebKitDispatchAdapter object.
+ */
+DispWrapper::~DispWrapper() {
+  gEnv->DeleteGlobalRef(dispObj);
+}
+
+bool DispWrapper::getOwnPropertySlot(ExecState *exec,
+    const Identifier& propertyName, PropertySlot& slot)
+{
+  slot.setCustom(this, getter);
+  return true;
+}
+
+/*
+ * Tells JavaScript that we can store properties into this object.
+ * Note that we do not verify the property exists, so we 
+ * 
+ * exec JS execution state
+ * proeprtyName the property to be updated
+ */
+bool DispWrapper::canPut(ExecState *exec, const Identifier &propertyName)
+    const
+{
+  return true;
+}
+
+/*
+ * Store a value into a field on a Java object.
+ * 
+ * exec JS execution state
+ * propertyName the name of the field
+ * value the JS value to store in the field
+ * attr unused attributes of the property
+ * 
+ * Silently catches any Java exceptions in WebKitDispatchAdapter.setField(),
+ * including undefined fields, so updates to undefined fields in Java objects
+ * will be silently ignored.  TODO: is that the desired behavior?
+ */
+void DispWrapper::put(ExecState *exec, const Identifier &propertyName,
+    JSValue *value, int attr)
+{
+  TRACE("ENTER DispWrapper::put");
+  jstring jpropName = gEnv->NewString((const jchar*)propertyName.data(),
+      propertyName.size());
+  if (!jpropName || gEnv->ExceptionCheck()) {
+    gEnv->ExceptionClear();
+    return;
+  }
+  gwtGCProtect(value); // Java will take ownership of this value
+  gEnv->CallVoidMethod(dispObj, gSetFieldMeth, jpropName, (jint)value);
+  if (gEnv->ExceptionCheck()) {
+    gEnv->ExceptionClear();
+    return;
+  }
+  TRACE("SUCCESS DispWrapper::put");
+}
+
+/*
+ * Prevent JavaScript from deleting fields from a Java object.
+ */
+bool DispWrapper::deleteProperty(ExecState *exec,
+    const Identifier &propertyName)
+{
+  return false;
+}
+
+/*
+ * Return a string representation of the Java object.
+ * Calls obj.toString() on the Java object.
+ * 
+ * exec JS execution state
+ * hint unused
+ * 
+ * Returns undefined if toString() failed, or the string returned (which may
+ * be null).
+ */
+JSValue *DispWrapper::defaultValue(ExecState *exec, JSType hint) const {
+  jstring result = (jstring)gEnv->CallObjectMethod(dispObj, gToStringMeth);
+  if (gEnv->ExceptionCheck()) {
+    return jsUndefined();
+  } else if (!result) {
+    return jsNull();
+  } else {
+    JStringWrap jresult(gEnv, result);
+    return jsString(UString((const UChar*)jresult.jstr(), jresult.length()));
+  }
+}
+
+/*
+ * Tell JavaScript that this object does not implement call functionality.
+ */
+bool DispWrapper::implementsCall() const {
+  return false;
+}
+
+/*
+ * Prevent JavaScript from calling the WebKitDispatchAdapter object
+ * as if it were a function.
+ */
+JSValue *DispWrapper::callAsFunction(ExecState *, JSObject *, const List &) {
+  return jsUndefined();
+}
diff --git a/jni/mac/DispWrapper.h b/jni/mac/10.5/DispWrapper.h
similarity index 100%
copy from jni/mac/DispWrapper.h
copy to jni/mac/10.5/DispWrapper.h
diff --git a/jni/mac/FuncWrapper.cpp b/jni/mac/10.5/FuncWrapper.cpp
similarity index 100%
copy from jni/mac/FuncWrapper.cpp
copy to jni/mac/10.5/FuncWrapper.cpp
diff --git a/jni/mac/FuncWrapper.h b/jni/mac/10.5/FuncWrapper.h
similarity index 100%
copy from jni/mac/FuncWrapper.h
copy to jni/mac/10.5/FuncWrapper.h
diff --git a/jni/mac/10.5/FunctionObject.cpp b/jni/mac/10.5/FunctionObject.cpp
new file mode 100644
index 0000000..4085925
--- /dev/null
+++ b/jni/mac/10.5/FunctionObject.cpp
@@ -0,0 +1,166 @@
+/* 
+ * Copyright 2007 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+#include "FunctionObject.h"
+#include <kjs/array_object.h>
+
+using namespace KJS;
+
+const ClassInfo FunctionObject::info = {"Function", 0, 0};
+
+class CallFunction : public FunctionObject {
+public:
+  CallFunction(): FunctionObject("call") {
+  }
+
+  virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj,
+        const List &args)
+  {
+    // Copied from FunctionProtoFunc::callAsFunction()
+    JSValue *thisArg = args[0];
+    JSObject *func = thisObj;
+
+    if (!func->implementsCall()) {
+      return throwError(exec, TypeError);
+    }
+
+    JSObject *callThis;
+    if (thisArg->isUndefinedOrNull()) {
+      callThis = exec->dynamicGlobalObject();
+    } else {
+      callThis = thisArg->toObject(exec);
+    }
+
+    List tail;
+    args.getSlice(1, tail);
+    return func->call(exec, callThis, tail);
+  }
+};
+
+class ApplyFunction  : public FunctionObject {
+public:
+  ApplyFunction(): FunctionObject("apply") {
+  }
+
+  virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj,
+      const List &args)
+  {
+    // Copied from FunctionProtoFunc::callAsFunction()
+    JSObject *func = thisObj;
+    if (!func->implementsCall()) {
+      return throwError(exec, TypeError);
+    }
+
+    JSValue *thisArg = args[0];
+    JSObject *applyThis;
+    if (thisArg->isUndefinedOrNull()) {
+      applyThis = exec->dynamicGlobalObject();
+    } else {
+      applyThis = thisArg->toObject(exec);
+    }
+
+    JSValue *argArray = args[1];
+    List applyArgs;
+    if (!argArray->isUndefinedOrNull()) {
+      if (!argArray->isObject(&ArrayInstance::info)) {
+        return throwError(exec, TypeError);
+      }
+
+      JSObject *argArrayObj = static_cast<JSObject *>(argArray);
+      unsigned int length = argArrayObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+      for (unsigned int i = 0; i < length; ++i) {
+        applyArgs.append(argArrayObj->get(exec,i));
+      }
+    }
+    return func->call(exec, applyThis, applyArgs);
+  }
+};
+
+
+static UString makeFunctionString(const UString& name) {
+  return "\nfunction " + name + "() {\n    [native code]\n}\n";
+}
+
+JSValue *FunctionObject::getter(ExecState* exec, JSObject* obj,
+    const Identifier& propertyName, const PropertySlot& slot)
+{
+  if (propertyName.ustring() == "toString") {
+    return new ToStringFunction();
+  } else if (propertyName.ustring() == "call") {
+    return new CallFunction();
+  } else if (propertyName.ustring() == "apply") {
+    return new ApplyFunction();
+  }
+  return jsUndefined();
+}
+
+FunctionObject::FunctionObject(const UString& name): name(name) {
+}
+
+bool FunctionObject::getOwnPropertySlot(ExecState *exec,
+    const Identifier& propertyName, PropertySlot& slot)
+{
+  if (propertyName.ustring() == "toString") {
+    slot.setCustom(this, getter);
+    return true;
+  }
+  if (propertyName.ustring() == "call") {
+    slot.setCustom(this, getter);
+    return true;
+  }
+  if (propertyName.ustring() == "apply") {
+    slot.setCustom(this, getter);
+    return true;
+  }
+  return false;
+}
+
+bool FunctionObject::canPut(ExecState *exec, const Identifier &propertyName)
+    const
+{
+  return false;
+}
+
+void FunctionObject::put(ExecState *exec, const Identifier &propertyName,
+    JSValue *value, int attr)
+{
+}
+
+bool FunctionObject::deleteProperty(ExecState *exec,
+    const Identifier &propertyName)
+{
+  return false;
+}
+
+JSValue *FunctionObject::defaultValue(ExecState *exec, JSType hint) const {
+  return jsString(makeFunctionString(name));
+}
+
+bool FunctionObject::implementsCall() const {
+  return true;
+}
+
+// ToStringFunction
+ToStringFunction::ToStringFunction(): FunctionObject("toString") {
+}
+
+JSValue *ToStringFunction::callAsFunction(ExecState *exec, JSObject *thisObj,
+    const List &args)
+{
+  if (!thisObj) {
+    return throwError(exec, TypeError);
+  }
+  return jsString(thisObj->toString(exec));
+}
diff --git a/jni/mac/FunctionObject.h b/jni/mac/10.5/FunctionObject.h
similarity index 100%
copy from jni/mac/FunctionObject.h
copy to jni/mac/10.5/FunctionObject.h
diff --git a/jni/mac/JStringWrap.h b/jni/mac/10.5/JStringWrap.h
similarity index 100%
copy from jni/mac/JStringWrap.h
copy to jni/mac/10.5/JStringWrap.h
diff --git a/jni/mac/Makefile b/jni/mac/10.5/Makefile
similarity index 91%
copy from jni/mac/Makefile
copy to jni/mac/10.5/Makefile
index e0614ee..b25908d 100644
--- a/jni/mac/Makefile
+++ b/jni/mac/10.5/Makefile
@@ -15,13 +15,13 @@
 ##
 # Try a GWT_TOOLS default if it isn't set
 ##
-GWT_TOOLS ?= ../../../tools
+GWT_TOOLS ?= ../../../../tools
 
 ##
 # External WebKit products.
 ## 
-WEBKIT_REDIST=$(GWT_TOOLS)/redist/webkit/WebKit-418.9.tar.gz
-WEBKIT_INCLUDE=$(GWT_TOOLS)/sdk/WebKit-418.9
+WEBKIT_REDIST=$(GWT_TOOLS)/redist/webkit/WebKit-525-10.5.tar.gz
+WEBKIT_INCLUDE=$(GWT_TOOLS)/sdk/WebKit-525
 
 ##
 # External SWT products.
@@ -54,7 +54,7 @@
 ##
 ARCHS = -arch i386 -arch ppc
 CFLAGS = -Wall -c $(ARCHS) -DCARBON -I/System/Library/Frameworks/JavaVM.framework/Headers -fno-exceptions -fno-rtti
-LFLAGS = -bundle $(ARCHS) -isysroot /Developer/SDKs/MacOSX10.4u.sdk
+LFLAGS = -bundle $(ARCHS)
 
 ##
 # JavaScriptCore options.
@@ -99,8 +99,8 @@
 ##
 # Rule for gwt-ll objects.
 ##
-gwt-ll.o: ../core/gwt-ll.cpp
-	$(CC) -c -o gwt-ll.o $(CFLAGS) ../core/gwt-ll.cpp
+gwt-ll.o: ../../core/gwt-ll.cpp
+	$(CC) -c -o gwt-ll.o $(CFLAGS) ../../core/gwt-ll.cpp
 
 gwt-args.o: gwt-args.cpp
 	$(CC) -c -o gwt-args.o $(CFLAGS) gwt-args.cpp
@@ -117,7 +117,7 @@
 # Rule for final lib for gwt-webkit.
 ##
 $(GWT_WEBKIT_LIB): Frameworks $(GWT_WEBKIT_OBJECTS)
-	$(CC) -o $(GWT_WEBKIT_LIB) $(JSCORE_LFLAGS) $(GWT_WEBKIT_OBJECTS)
+	$(CC) -o $(GWT_WEBKIT_LIB) -framework JavaVM $(JSCORE_LFLAGS) $(GWT_WEBKIT_OBJECTS)
 	$(FIX_INSTALL_NAME) JavaScriptCore $(JSCORE_INSTALL_NAME) $(GWT_WEBKIT_LIB)
 
 install: $(GWT_LL_LIB) $(GWT_WEBKIT_LIB)
diff --git a/jni/mac/10.5/build.xml b/jni/mac/10.5/build.xml
new file mode 100755
index 0000000..2bb1631
--- /dev/null
+++ b/jni/mac/10.5/build.xml
@@ -0,0 +1,18 @@
+<project name="jni-mac" default="build" basedir=".">
+	<property name="gwt.root" location="../.." />
+	<property name="project.tail" value="jni/mac" />
+	<import file="${gwt.root}/common.ant.xml" />
+
+	<target name="build" description="Builds a JNI lib">
+		<mkdir dir="${project.jni}" />
+		<!-- TODO: Actually build this from source! -->
+		<copy todir="${project.jni}">
+			<fileset dir="prebuilt" />
+		</copy>
+	</target>
+
+	<target name="clean" description="Cleans this project's intermediate and output files">
+		<delete dir="${project.build}" failonerror="false" />
+		<delete dir="${project.jni}" failonerror="false" />
+	</target>
+</project>
diff --git a/jni/mac/fix-install-name.sh b/jni/mac/10.5/fix-install-name.sh
similarity index 100%
copy from jni/mac/fix-install-name.sh
copy to jni/mac/10.5/fix-install-name.sh
diff --git a/jni/mac/gwt-args.cpp b/jni/mac/10.5/gwt-args.cpp
similarity index 100%
copy from jni/mac/gwt-args.cpp
copy to jni/mac/10.5/gwt-args.cpp
diff --git a/jni/mac/gwt-ll.h b/jni/mac/10.5/gwt-ll.h
similarity index 100%
copy from jni/mac/gwt-ll.h
copy to jni/mac/10.5/gwt-ll.h
diff --git a/jni/mac/10.5/gwt-webkit.cpp b/jni/mac/10.5/gwt-webkit.cpp
new file mode 100644
index 0000000..cf2ac36
--- /dev/null
+++ b/jni/mac/10.5/gwt-webkit.cpp
@@ -0,0 +1,895 @@
+/* 
+ * Copyright 2007 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+#include "gwt-ll.h"
+#include "DispWrapper.h"
+#include "FuncWrapper.h"
+
+JNIEnv* gEnv;
+jclass gClass;
+jclass gDispObjCls;
+jclass gDispMethCls;
+jmethodID gGetFieldMeth;
+jmethodID gSetFieldMeth;
+jmethodID gInvokeMeth;
+jmethodID gToStringMeth;
+
+using namespace KJS;
+
+/*
+ * Print a JSValue in human-readable form.
+ * 
+ * val JSValue* to print
+ * prefix a string to print before the value
+ */
+void PrintJSValue(JSValue* val, char* prefix) {
+  static const char* typeStrings[]={
+    "unspecified",
+    "number",
+    "boolean",
+    "undefined",
+    "null",
+    "string",
+    "object",
+    "getter/setter",
+  };
+  char buf[256];
+  snprintf(buf, sizeof(buf), "%s{%08x}:", prefix, unsigned(val));
+  TRACE(buf);
+  JSType type = val->type();
+  const char* typeString=typeStrings[type];
+  char* p = buf;
+  p += snprintf(p, sizeof(buf)-(p-buf), " %s: ", typeString);
+  //p += snprintf(p, sizeof(buf)-(p-buf), "%s{%08x} %s: ", prefix, 
+  //    unsigned(val), typeString);
+  if (val->isNumber()) {
+    p += snprintf(p, sizeof(buf)-(p-buf), "%lf", val->getNumber());
+  } else if(val->isString()) {
+    CString str(val->getString().UTF8String());
+    p += snprintf(p, sizeof(buf)-(p-buf), "%.*s", (int)str.size(),
+        str.c_str());
+  } else if(val->isObject()) {
+    const JSObject* obj = val->getObject();
+    const ClassInfo* cinfo = obj->classInfo();
+    const char* cname = cinfo ? cinfo->className : "js object";
+    p += snprintf(p, sizeof(buf)-(p-buf), "%s @ %08x", cname, unsigned(obj));
+  } else if(val->isBoolean()) {
+    p += snprintf(p, sizeof(buf)-(p-buf), "%s", val->getBoolean() ? "true" : "false");
+  }
+  TRACE(buf);
+}
+
+/*
+ * Called for each gcProtect, only if TRACING is enabled.
+ * 
+ * val JSValue* to be protected
+ */
+void gcProtectHook(JSValue* val) {
+  PrintJSValue(val, "gcProtect: val=");
+}
+
+/*
+ * Called for each gcUnprotect, only if TRACING is enabled.
+ * 
+ * val JSValue* to be protected
+ * trace string containing trace information for the creation site, or null
+ *     if not available
+ */
+void gcUnprotectHook(JSValue* val, const char* trace) {
+  if (trace) {
+    TRACE("gcUnprotect - value created at:");
+    TRACE(trace);
+  }
+  PrintJSValue(val, "gcUnprotect: val=");
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    isNull
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isNull
+    (JNIEnv *env, jclass, jint jsval)
+{
+  TRACE("ENTER LowLevelSaf__isNull");
+
+  JSValue* val = (JSValue*)jsval;
+  if (!val) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__isNull");
+  return val->isNull();
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    isUndefined
+ * Signature: (I)Z
+ */
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isUndefined
+    (JNIEnv *env, jclass, jint jsval)
+{
+  TRACE("ENTER LowLevelSaf__isUndefined");
+  JSValue* val = (JSValue*)jsval;
+  if (!val) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__isUndefined");
+  return val->isUndefined();
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    jsNull
+ * Signature: ()I
+ */
+extern "C" JNIEXPORT jint JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf_jsNull
+    (JNIEnv *, jclass)
+{
+  return reinterpret_cast<jint>(jsNull());
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    getTypeString
+ * Signature: (I)Ljava/lang/String;
+ */
+extern "C" JNIEXPORT jstring JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf_getTypeString
+    (JNIEnv *env, jclass, jint jsval)
+{
+  static const char* typeStrings[]={
+    "unspecified",
+    "number",
+    "boolean",
+    "undefined",
+    "null",
+    "string",
+    "object",
+    "getter/setter",
+  };
+  JSValue* val = (JSValue*)jsval;
+  if (!val) {
+    return 0;
+  }
+  JSType type = val->type();
+  const char* typeString=typeStrings[type];
+  if (type == ObjectType) {
+    if (val->isObject(&DispWrapper::info)) {
+       typeString = "Java object";
+     } else {
+       typeString = "JS object";
+    }
+  }
+  return env->NewStringUTF(typeString);
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    jsUndefined
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_jsUndefined
+    (JNIEnv *env, jclass)
+{
+  return reinterpret_cast<jint>(jsUndefined());
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _coerceToBoolean
+ * Signature: (II[Z)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1coerceToBoolean
+    (JNIEnv * env, jclass, jint execState, jint jsval, jbooleanArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1coerceToBoolean");
+
+  if (!execState || !jsval) {
+    return JNI_FALSE;
+  }
+
+  jboolean result = ((JSValue*)jsval)->toBoolean((ExecState*)execState);
+  env->SetBooleanArrayRegion(rval, 0, 1, &result);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__1coerceToBoolean");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _coerceToDouble
+ * Signature: (II[D)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1coerceToDouble
+    (JNIEnv *env, jclass, jint execState, jint jsval, jdoubleArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1coerceToDouble");
+
+  if (!execState || !jsval) {
+    return JNI_FALSE;
+  }
+
+  jdouble result = ((JSValue*)jsval)->toNumber((ExecState*)execState);
+  env->SetDoubleArrayRegion(rval, 0, 1, &result);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__1coerceToDouble");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _coerceToString
+ * Signature: (II[Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1coerceToString
+    (JNIEnv *env, jclass, jint execState, jint jsval, jobjectArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1coerceToString");
+
+  JSValue *val = (JSValue*)jsval;
+  if (!execState || !val) {
+    return JNI_FALSE;
+  }
+
+  /* 
+   * Convert all objects to their string representation, EXCEPT
+   * null and undefined which will be returned as a true NULL.
+   */
+  jstring result = NULL;
+  if (!val->isNull() && !val->isUndefined()) {
+    UString str = val->toString((ExecState*)execState);
+    result = env->NewString((const jchar*)str.data(), str.size());
+    if (env->ExceptionCheck())
+      return JNI_FALSE;
+  }
+
+  env->SetObjectArrayElement(rval,0,result);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__1coerceToString");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _convertBoolean
+ * Signature: (IZ[I)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1convertBoolean
+    (JNIEnv *env, jclass, jboolean jval, jintArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1convertBoolean");
+#ifdef ENABLE_TRACING
+  char buf[256];
+  snprintf(buf, sizeof(buf), " val=%s", jval ? "true" : "false");
+  TRACE(buf);
+#endif
+
+  JSValue *jsval = (jval == JNI_FALSE) ? jsBoolean(false) : jsBoolean(true);
+
+  /*
+   * Since we know this is a boolean primitive, the protect is a no-op, but
+   * it is useful to have it for the trace log.
+   */
+  gwtGCProtect(jsval);
+  
+  if (!jsval) {
+    return JNI_FALSE;
+  }
+
+  env->SetIntArrayRegion(rval,0,1,(const jint*)&jsval);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+  
+  TRACE("SUCCESS LowLevelSaf__1convertBoolean");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _convertDouble
+ * Signature: (ID[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1convertDouble
+    (JNIEnv *env, jclass, jdouble jval, jintArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1convertDouble");
+#ifdef ENABLE_TRACING
+  char buf[256];
+  snprintf(buf, sizeof(buf), " val=%lf", jval);
+  TRACE(buf);
+#endif
+
+  JSValue *jsval = jsNumber(jval);
+  gwtGCProtect(jsval);
+  if (!jsval) {
+    return JNI_FALSE;
+  }
+
+  env->SetIntArrayRegion(rval,0,1,(const jint*)&jsval);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__1convertDouble");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _convertString
+ * Signature: (ILjava/lang/String;[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1convertString
+    (JNIEnv *env, jclass, jstring jval, jintArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1convertString");
+
+  JStringWrap jstr(env, jval);
+  if (!jstr.jstr()) {
+    return JNI_FALSE;
+  }
+#ifdef ENABLE_TRACING
+  char buf[256];
+  snprintf(buf, sizeof(buf), " val=%s", jstr.str());
+  TRACE(buf);
+#endif
+  
+  JSValue *jsval = jsString(UString((const UChar*)jstr.jstr(), jstr.length()));
+
+  gwtGCProtect(jsval);
+  if (!jsval) {
+    return JNI_FALSE;
+  }
+
+  env->SetIntArrayRegion(rval,0,1,(const jint*)&jsval);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__1convertString");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _executeScript
+ * Signature: (ILjava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1executeScript
+    (JNIEnv* env, jclass, jint execState, jstring code)
+{
+  TRACE("ENTER LowLevelSaf__1executeScript"); 
+  if (!execState || !code) {
+    return JNI_FALSE;
+  }
+
+  JStringWrap jcode(env, code);
+  if (!jcode.jstr()) {
+    return JNI_FALSE;
+  }
+
+#ifdef ENABLE_TRACING
+  char buf[1024];
+  snprintf(buf, sizeof(buf), " code=%s", jcode.str());
+  TRACE(buf);
+#endif
+
+  Completion comp = Interpreter::evaluate((ExecState*) execState,
+    NULL, 0, (const UChar*)jcode.jstr(),
+    jcode.length());
+  switch (comp.complType()) {
+    case Normal:
+    case ReturnValue:
+      TRACE("SUCCESS LowLevelSaf__1executeScript");
+      return JNI_TRUE;
+    default:
+      return JNI_FALSE;
+  }
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _executeScriptWithInfo
+ * Signature: (ILjava/lang/String;Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1executeScriptWithInfo
+    (JNIEnv* env, jclass, jint execState, jstring code, jstring file, jint line)
+{
+  TRACE("ENTER LowLevelSaf__1executeScriptWithInfo");
+  if (!execState || !code || !file) {
+    return JNI_FALSE;
+  }
+
+  JStringWrap jcode(env, code);
+  if (!jcode.jstr()) {
+    return JNI_FALSE;
+  }
+
+  JStringWrap jfile(env, file);
+  if (!jcode.jstr()) {
+    return JNI_FALSE;
+  }
+
+#ifdef ENABLE_TRACING
+  char buf[1024];
+  snprintf(buf, sizeof(buf), " code=%s, file=%s, line=%d", jcode.str(),
+      jfile.str(), static_cast<int>(line));
+  TRACE(buf);
+#endif
+ 
+  UString uStrFile = UString((const UChar*) jfile.jstr(), jfile.length());
+  Completion comp = Interpreter::evaluate((ExecState*) execState,
+    uStrFile, (int)line, (const UChar*) jcode.jstr(),
+    jcode.length());
+  switch (comp.complType()) {
+    case Normal:
+    case ReturnValue:
+      TRACE("SUCCESS LowLevelSaf__1executeScript");
+      return JNI_TRUE;
+    default:
+      return JNI_FALSE;
+  }
+
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _gcLock
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1gcLock
+    (JNIEnv *, jclass, jint jsval)
+{
+  gwtGCProtect(reinterpret_cast<JSValue*>(jsval));
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _gcUnlock
+ * Signature: (ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1gcUnlock
+    (JNIEnv* jniEnv, jclass, jint jsval, jstring creationDesc)
+{
+  JStringWrap creationStr(jniEnv, creationDesc);
+  gwtGCUnprotect(reinterpret_cast<JSValue*>(jsval),
+      creationDesc ? creationStr.str() : 0);
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _getGlobalExecState
+ * Signature: (I[I)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1getGlobalExecState
+    (JNIEnv *env, jclass, jint scriptObject, jintArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1getGlobalExecState");
+
+  if (!scriptObject || !((JSValue*)scriptObject)->isObject()) {
+    return JNI_FALSE;
+  }
+
+  JSGlobalObject *globalObject = reinterpret_cast<JSGlobalObject*>(scriptObject);
+  ExecState* execState = globalObject->globalExec();
+  env->SetIntArrayRegion(rval, 0, 1, (jint*)&execState);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+  TRACE("SUCCESS LowLevelSaf__1getGlobalExecState");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _initNative
+ * Signature: (Ljava/lang/Class;Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1initNative
+    (JNIEnv* env, jclass llClass, jclass dispObjCls, jclass dispMethCls)
+{
+  Interpreter::setShouldPrintExceptions(true);
+  gEnv = env;
+  gClass =  static_cast<jclass>(env->NewGlobalRef(llClass));
+  gDispObjCls = static_cast<jclass>(env->NewGlobalRef(dispObjCls));
+  gDispMethCls = static_cast<jclass>(env->NewGlobalRef(dispMethCls));
+  if (!gClass || !gDispObjCls || !gDispMethCls || env->ExceptionCheck()) {
+    return false;
+  }
+
+  gGetFieldMeth
+      = env->GetMethodID(gDispObjCls, "getField", "(Ljava/lang/String;)I");
+  gSetFieldMeth
+      = env->GetMethodID(gDispObjCls, "setField", "(Ljava/lang/String;I)V");
+  gInvokeMeth = env->GetMethodID(gDispMethCls, "invoke", "(II[I)I");
+  gToStringMeth
+      = env->GetMethodID(gDispObjCls, "toString", "()Ljava/lang/String;");
+  if (!gGetFieldMeth || !gSetFieldMeth || !gInvokeMeth || !gToStringMeth
+      || env->ExceptionCheck())
+  {
+    return false;
+  }
+
+#ifdef FILETRACE
+  gout = fopen("/tmp/gwt-ll.log", "w");
+  filetrace("LOG STARTED");
+#endif // FILETRACE
+
+#ifdef JAVATRACE
+  gTraceMethod = env->GetStaticMethodID(gClass, "trace", "(Ljava/lang/String;)V");
+  if (!gTraceMethod || env->ExceptionCheck()) {
+    return false;
+  }
+#endif // JAVATRACE
+
+  return true;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _invoke
+ * Signature: (IILjava/lang/String;II[I[I)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1invoke
+    (JNIEnv* env, jclass, jint jsexecState, jint jsScriptObject, jstring method,
+    jint jsthis, jint argc, jintArray argv, jintArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1invoke");
+
+  if (!jsexecState || !jsScriptObject || !method || !rval) {
+    return JNI_FALSE;
+  }
+  JStringWrap jmethod(env, method);
+#ifdef ENABLE_TRACING
+  char buf[256];
+  snprintf(buf, sizeof(buf), "scriptObject=%08x, method=%s, argc=%d",
+      static_cast<unsigned>(jsScriptObject), jmethod.str(),
+      static_cast<unsigned>(argc));
+  TRACE(buf);
+  PrintJSValue((JSValue*)jsthis, " jsthis=");
+#endif
+  ExecState* execState = (ExecState*)jsexecState;
+
+  JSObject* scriptObj = (JSObject*)jsScriptObject;
+  if (!scriptObj->isObject()) {
+    return JNI_FALSE;
+  }
+
+  if (!jmethod.jstr()) {
+    return JNI_FALSE;
+  }
+
+  JSObject* thisObj = (JSObject*)jsthis;
+  if (!thisObj || thisObj->isNull() || thisObj->isUndefined()) {
+    thisObj = scriptObj;
+  }
+  if (!thisObj->isObject()) {
+    return JNI_FALSE;
+  }
+
+  JSValue* maybeFunc = scriptObj->get(execState,
+      Identifier((const UChar*)jmethod.jstr(), jmethod.length()));
+  if (!maybeFunc || !maybeFunc->isObject()) {
+    return JNI_FALSE;
+  }
+  
+  JSObject* func = (JSObject*)maybeFunc;
+  if (!func->implementsCall()) {
+    return JNI_FALSE;
+  }
+
+  List args;
+  for (int i = 0; i < argc; ++i) {
+    jint argi;
+    env->GetIntArrayRegion(argv, i, 1, &argi);
+    if (env->ExceptionCheck()) {
+      return JNI_FALSE;
+    }
+#ifdef ENABLE_TRACING
+    snprintf(buf, sizeof(buf), " arg[%d]=", i);
+    TRACE(buf);
+    PrintJSValue((JSValue*)argi, buf);
+#endif
+    if (argi) {
+      args.append((JSValue*)argi);
+    } else {
+      args.append(jsNull());
+    }
+  }
+
+  JSValue* result = func->call(execState, thisObj, args);
+  gwtGCProtect(result);
+  env->SetIntArrayRegion(rval, 0, 1, (jint*)&result);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__1invoke");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    isBoolean
+ * Signature: (I)Z
+ */
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isBoolean
+    (JNIEnv *, jclass, jint jsval)
+{
+  if (!jsval) {
+    return JNI_FALSE;
+  }
+  return reinterpret_cast<JSValue*>(jsval)->isBoolean() ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    isNumber
+ * Signature: (I)Z
+ */
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isNumber
+    (JNIEnv *, jclass, jint jsval)
+{
+  if (!jsval) {
+    return JNI_FALSE;
+  }
+  return reinterpret_cast<JSValue*>(jsval)->isNumber() ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _isString
+ * Signature: (I)Z
+ * 
+ * Must return true for JavaScript String objects as well as string primitives.
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1isString
+    (JNIEnv *, jclass, jint jsval)
+{
+  if (!jsval) {
+    return JNI_FALSE;
+  }
+  JSValue* jsValue = reinterpret_cast<JSValue*>(jsval);
+  if(jsValue->isString()) return JNI_TRUE;
+  // check for JavaScript String objects
+  if(jsValue->isObject()) {
+    const JSObject* obj = jsValue->getObject();
+    const ClassInfo* cinfo = obj->classInfo();
+    if (cinfo && !strcmp(cinfo->className, "String")) {
+      return JNI_TRUE;
+    }
+  }
+  return JNI_FALSE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _isObject
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1isObject
+    (JNIEnv *, jclass, jint jsval)
+{
+  if (!jsval) {
+    return JNI_FALSE;
+  }
+  return reinterpret_cast<JSValue*>(jsval)->isObject() ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _isWrappedDispatch
+ * Signature: (I[Z)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1isWrappedDispatch
+    (JNIEnv* env, jclass, jint jsval, jbooleanArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1isWrappedDispatch");
+  if (!jsval) {
+    return JNI_FALSE;
+  }
+
+  JSValue* val = (JSValue*)jsval;
+  jboolean result = val->isObject(&DispWrapper::info) ? JNI_TRUE : JNI_FALSE;
+
+  env->SetBooleanArrayRegion(rval, 0, 1, &result);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__1isWrappedDispatch");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _jsLock
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1jsLock
+    (JNIEnv *, jclass)
+{
+  JSLock::lock();
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _jsUnlock
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1jsUnlock
+    (JNIEnv *, jclass)
+{
+  JSLock::unlock();
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _raiseJavaScriptException
+ * Signature: (II)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1raiseJavaScriptException
+    (JNIEnv *env, jclass, jint execState, jint jsval)
+{
+  TRACE("ENTER LowLevelSaf__1raiseJavaScriptException");
+
+  if (!execState || !jsval) {
+    return JNI_FALSE;
+  }
+
+  reinterpret_cast<ExecState*>(execState)->setException(
+      reinterpret_cast<JSValue*>(jsval));
+  TRACE("SUCCESS LowLevelSaf__1raiseJavaScriptException");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _unwrapDispatch
+ * Signature: (I[Lcom/google/gwt/dev/shell/mac/LowLevelSaf/DispatchObject;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1unwrapDispatch
+    (JNIEnv* env, jclass, jint jsval, jobjectArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1unwrapDispatch");
+  if (!jsval) {
+    return JNI_FALSE;
+  }
+
+  JSValue* val = reinterpret_cast<JSValue*>(jsval);
+  if (!val->isObject(&DispWrapper::info)) {
+    return JNI_FALSE;
+  }
+
+  DispWrapper* wrapper = static_cast<DispWrapper*>(val);
+  env->SetObjectArrayElement(rval, 0, wrapper->getDispObj());
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__1unwrapDispatch");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _wrapDispatch
+ * Signature: (Lcom/google/gwt/dev/shell/mac/LowLevelSaf/DispatchObject;[I)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1wrapDispatch
+    (JNIEnv* env, jclass, jobject dispObj, jintArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1wrapDispatch");
+  jobject dispObjRef = env->NewGlobalRef(dispObj);
+  if (!dispObjRef || env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+  
+  DispWrapper* wrapper = new DispWrapper(dispObjRef);
+
+  gwtGCProtect(wrapper);
+
+  env->SetIntArrayRegion(rval, 0, 1, (jint*)&wrapper);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__1wrapDispatch");
+  return JNI_TRUE;
+}
+
+/*
+ * Class:     com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method:    _wrapFunction
+ * Signature: (Ljava/lang/String;Lcom/google/gwt/dev/shell/mac/LowLevelSaf/DispatchMethod;[I)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1wrapFunction
+    (JNIEnv* env, jclass, jstring name, jobject dispMeth, jintArray rval)
+{
+  TRACE("ENTER LowLevelSaf__1wrapFunction");
+
+  jobject dispMethRef = env->NewGlobalRef(dispMeth);
+  if (!dispMethRef || env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+  
+  JStringWrap jname(env, name);
+  if (!jname.jstr()) {
+    return JNI_FALSE;
+  }
+  
+  FuncWrapper* wrapper = new FuncWrapper(UString((const UChar*)jname.jstr(),
+      jname.length()), dispMethRef);
+
+  gwtGCProtect(wrapper);
+  env->SetIntArrayRegion(rval, 0, 1, (jint*)&wrapper);
+  if (env->ExceptionCheck()) {
+    return JNI_FALSE;
+  }
+
+  TRACE("SUCCESS LowLevelSaf__1wrapFunction");
+  return JNI_TRUE;
+}
+
+#ifdef FILETRACE
+FILE* gout = 0;
+void filetrace(const char* s) {
+   fprintf(gout, s);
+   fprintf(gout, "\n");
+   fflush(gout);
+}
+#endif // FILETRACE
+
+#ifdef JAVATRACE
+jmethodID gTraceMethod = 0;
+void javatrace(const char* s) {
+   if (!gEnv->ExceptionCheck()) {
+      jstring out = gEnv->NewStringUTF(s);
+      if (!gEnv->ExceptionCheck()) {
+        gEnv->CallStaticVoidMethod(gClass, gTraceMethod, out);
+      } else {
+        gEnv->ExceptionClear();
+      }
+   }
+}
+#endif // JAVATRACE
diff --git a/jni/mac/10.5/gwt-webkit.h b/jni/mac/10.5/gwt-webkit.h
new file mode 100644
index 0000000..573e49b
--- /dev/null
+++ b/jni/mac/10.5/gwt-webkit.h
@@ -0,0 +1,93 @@
+/* 
+ * Copyright 2007 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+#ifndef GWT_WEBKIT_H
+#define GWT_WEBKIT_H
+
+#include <jni.h>
+#include <kjs/object.h>
+#include <kjs/internal.h>
+#include <kjs/interpreter.h>
+#include <kjs/JSGlobalObject.h>
+#include "JStringWrap.h"
+
+extern JNIEnv* gEnv;
+extern jclass gClass;
+extern jclass gDispObjCls;
+extern jclass gDispMethCls;
+extern jmethodID gSetFieldMeth;
+extern jmethodID gGetFieldMeth;
+extern jmethodID gInvokeMeth;
+extern jmethodID gToStringMeth;
+
+//#define FILETRACE
+//#define JAVATRACE
+
+#if defined(FILETRACE) || defined(JAVATRACE)
+#define ENABLE_TRACING
+#endif
+
+#if defined(FILETRACE) && defined(JAVATRACE)
+#define TRACE(s) filetrace(s),javatrace(s)
+#elif defined(FILETRACE)
+#define TRACE(s) filetrace(s)
+#elif defined(JAVATRACE)
+#define TRACE(s) javatrace(s)
+#else
+#define TRACE(s) ((void)0)
+#endif
+
+#ifdef FILETRACE
+extern FILE* gout;
+void filetrace(const char* s);
+#endif // FILETRACE
+
+#ifdef JAVATRACE
+extern jmethodID gTraceMethod;
+void javatrace(const char* s);
+#endif // JAVATRACE
+
+void PrintJSValue(KJS::JSValue*, char* prefix="");
+void gcProtectHook(KJS::JSValue*);
+void gcUnprotectHook(KJS::JSValue*, const char* trace);
+
+/*
+ * Lock KJS GC and protect the supplied value.
+ * 
+ * value JSValue* to protect from GC
+ */
+inline void gwtGCProtect(KJS::JSValue* value) {
+  KJS::JSLock lock;
+  gcProtectNullTolerant(value);
+#ifdef ENABLE_TRACING
+  gcProtectHook(value);
+#endif
+}
+
+/*
+ * Lock KJS GC and unprotect the supplied value.
+ *
+ * value JSValue* to unprotect from GC
+ * trace human-readable string describing object creation location
+ */
+inline void gwtGCUnprotect(KJS::JSValue* value, const char* trace) {
+  KJS::JSLock lock;
+#ifdef ENABLE_TRACING
+  gcUnprotectHook(value, trace);
+#endif
+  gcUnprotectNullTolerant(value);
+}
+
+#endif
diff --git a/jni/mac/10.5/localize-framework-install-names.rb b/jni/mac/10.5/localize-framework-install-names.rb
new file mode 100644
index 0000000..b00f1e9
--- /dev/null
+++ b/jni/mac/10.5/localize-framework-install-names.rb
@@ -0,0 +1,93 @@
+#!/usr/bin/env ruby
+require 'ostruct';
+require 'pathname';
+
+$CONFIG = OpenStruct.new
+$CONFIG.root = File.dirname(__FILE__)
+$CONFIG.frameworks = "#{$CONFIG.root}/Frameworks"
+
+class Framework
+  attr_reader :libs,:id
+  def initialize(framework)
+    @path = "#{$CONFIG.frameworks}/#{framework}.framework/Versions/Current/#{framework}"
+    reload
+    puts @libs.inspect
+  end
+  
+  def id=(name)
+    system(
+      "install_name_tool",
+      "-id",
+      name,
+      @path)
+    reload
+  end
+
+  def get_install_name(lib)
+    return @libs[lib]
+  end
+
+  def set_install_name(lib,val)
+    puts "lib=#{lib}/#{@libs[lib]}, val=#{val}"
+    system(
+      "install_name_tool",
+      "-change",
+      @libs[lib],
+      val,
+      @path)
+    reload
+  end
+
+  private
+  def reload
+    @libs = IO.popen("otool -L '#{@path}'") { |fh|
+      fh.readline
+      if fh.readline =~ /([^(]*)/
+        @id = $1.strip
+      else
+        raise "Unable to read otool of framework (#{@path})"
+      end
+      fh.inject({}) { |coll,line|
+        if line =~ /(\w+)\.framework/
+          name = $1
+          if line =~ /([^(]*)/
+            coll.update(name => $1.strip)
+          else
+            raise "Unable to read otool of framework (#{@path})"
+          end
+        end
+        coll
+      }
+    }.freeze
+  end
+end
+
+def create_frameworks
+  ["WebKit","WebCore","JavaScriptCore"].map { |name|
+    Framework.new(name)
+  }
+end
+
+def create_framework_ids
+  path = Pathname.new(File.dirname(__FILE__)).realpath
+  ["WebKit", "WebCore", "JavaScriptCore"].map { |name|
+    "#{path}/Frameworks/#{name}.framework/Versions/A/#{name}"
+  }
+end
+
+def localize_install_names
+  wk_fr, wc_fr, js_fr = create_frameworks
+  #wk_id, wc_id, js_id = "gwt/WebKit.framework", "gwt/WebCore.framework", "gwt/JavaScriptCore.framework"
+  wk_id, wc_id, js_id = create_framework_ids
+
+  js_fr.id = js_id
+
+  wc_fr.id = wc_id
+  wc_fr.set_install_name "JavaScriptCore", js_id
+
+  wk_fr.id = wk_id
+  wk_fr.set_install_name "JavaScriptCore", js_id
+  wk_fr.set_install_name "WebCore", wc_id
+end
+
+localize_install_names
diff --git a/jni/mac/org.eclipse.swt/make_macosx.mak b/jni/mac/10.5/org.eclipse.swt/make_macosx.mak
similarity index 90%
copy from jni/mac/org.eclipse.swt/make_macosx.mak
copy to jni/mac/10.5/org.eclipse.swt/make_macosx.mak
index af9ea3b..55eb481 100644
--- a/jni/mac/org.eclipse.swt/make_macosx.mak
+++ b/jni/mac/10.5/org.eclipse.swt/make_macosx.mak
@@ -30,9 +30,9 @@
 #SWT_DEBUG = -g
 ARCHS = -arch i386 -arch ppc
 CFLAGS = -c $(ARCHS) -DSWT_VERSION=$(SWT_VERSION) $(NATIVE_STATS) $(SWT_DEBUG) -DCARBON -I /System/Library/Frameworks/JavaVM.framework/Headers
-LFLAGS = -bundle $(ARCHS) -framework JavaVM -framework Carbon -isysroot /Developer/SDKs/MacOSX10.4u.sdk
+LFLAGS = -bundle $(ARCHS) -framework JavaVM -framework Carbon
 WEBKITCFLAGS = -c $(ARCHS) -xobjective-c -I /System/Library/Frameworks/JavaVM.framework/Headers -I /System/Library/Frameworks/Cocoa.framework/Headers -I /System/Library/Frameworks/WebKit.framework/Headers
-WEBKITLFLAGS = $(LFLAGS) -framework WebKit -framework Cocoa -framework WebCore -framework JavaScriptCore -F../Frameworks
+WEBKITLFLAGS = $(LFLAGS) -framework WebKit -framework Cocoa -F../Frameworks
 AGLLFLAGS = $(LFLAGS) -framework OpenGL -framework AGL
 SWT_OBJECTS = swt.o callback.o
 SWTPI_OBJECTS = swt.o os.o os_custom.o os_structs.o os_stats.o
diff --git a/jni/mac/org.eclipse.swt/webkit.c b/jni/mac/10.5/org.eclipse.swt/webkit.c
similarity index 100%
copy from jni/mac/org.eclipse.swt/webkit.c
copy to jni/mac/10.5/org.eclipse.swt/webkit.c
diff --git a/jni/mac/10.5/prebuilt/libgwt-ll.jnilib b/jni/mac/10.5/prebuilt/libgwt-ll.jnilib
new file mode 100755
index 0000000..01db6a1
--- /dev/null
+++ b/jni/mac/10.5/prebuilt/libgwt-ll.jnilib
Binary files differ
diff --git a/jni/mac/10.5/prebuilt/libgwt-webkit.jnilib b/jni/mac/10.5/prebuilt/libgwt-webkit.jnilib
new file mode 100755
index 0000000..879c831
--- /dev/null
+++ b/jni/mac/10.5/prebuilt/libgwt-webkit.jnilib
Binary files differ
diff --git a/jni/mac/build.xml b/jni/mac/build.xml
index 2bb1631..3fd4572 100755
--- a/jni/mac/build.xml
+++ b/jni/mac/build.xml
@@ -3,11 +3,21 @@
 	<property name="project.tail" value="jni/mac" />
 	<import file="${gwt.root}/common.ant.xml" />
 
-	<target name="build" description="Builds a JNI lib">
-		<mkdir dir="${project.jni}" />
+	<target name="build" depends="build_10.4, build_10.5">
+        </target>
+
+	<target name="build_10.4" description="Builds a JNI lib">
+		<mkdir dir="${project.jni}_10.4" />
 		<!-- TODO: Actually build this from source! -->
-		<copy todir="${project.jni}">
-			<fileset dir="prebuilt" />
+		<copy todir="${project.jni}_10.4">
+			<fileset dir="10.4/prebuilt" />
+		</copy>
+	</target>
+	<target name="build_10.5" description="Builds a JNI lib">
+		<mkdir dir="${project.jni}_10.5" />
+		<!-- TODO: Actually build this from source! -->
+		<copy todir="${project.jni}_10.5">
+			<fileset dir="10.5/prebuilt" />
 		</copy>
 	</target>
 
diff --git a/user/src/com/google/gwt/junit/JUnitShell.java b/user/src/com/google/gwt/junit/JUnitShell.java
index 35e3c53..95b06e0 100644
--- a/user/src/com/google/gwt/junit/JUnitShell.java
+++ b/user/src/com/google/gwt/junit/JUnitShell.java
@@ -159,7 +159,8 @@
    */
   private static JUnitShell getUnitTestShell() {
     if (unitTestShell == null) {
-      BootStrapPlatform.go();
+      BootStrapPlatform.init();
+      BootStrapPlatform.applyPlatformHacks();
       JUnitShell shell = new JUnitShell();
       String[] args = shell.synthesizeArgs();
       if (!shell.processArgs(args)) {
diff --git a/user/test/com/google/gwt/dev/cfg/TagSuite.java b/user/test/com/google/gwt/dev/cfg/TagSuite.java
index 7a9d44b..35642fb 100644
--- a/user/test/com/google/gwt/dev/cfg/TagSuite.java
+++ b/user/test/com/google/gwt/dev/cfg/TagSuite.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.dev.cfg;
 
+import com.google.gwt.dev.BootStrapPlatform;
 import com.google.gwt.junit.tools.GWTTestSuite;
 
 import junit.framework.Test;
@@ -24,6 +25,15 @@
  */
 public class TagSuite {
 
+  static {
+    /*
+     * Required for OS X Leopard. This call ensures we have a valid context
+     * ClassLoader. Many of the tests test low-level RPC mechanisms and rely on
+     * a ClassLoader to resolve classes and resources.
+     */
+    BootStrapPlatform.applyPlatformHacks();
+  }
+  
   public static Test suite() {
     GWTTestSuite suite = new GWTTestSuite(
         "Tests for public, source, and super-source tags");
diff --git a/user/test/com/google/gwt/user/RPCSuite.java b/user/test/com/google/gwt/user/RPCSuite.java
index 384d3cf..9e63432 100644
--- a/user/test/com/google/gwt/user/RPCSuite.java
+++ b/user/test/com/google/gwt/user/RPCSuite.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.user;
 
+import com.google.gwt.dev.BootStrapPlatform;
 import com.google.gwt.junit.tools.GWTTestSuite;
 import com.google.gwt.user.client.rpc.CollectionsTest;
 import com.google.gwt.user.client.rpc.CustomFieldSerializerTest;
@@ -35,6 +36,16 @@
  * A collection of TestCases for the RPC system.
  */
 public class RPCSuite {
+
+  static {
+    /*
+     * Required for OS X Leopard. This call ensures we have a valid context
+     * ClassLoader. Many of the tests test low-level RPC mechanisms and rely on
+     * a ClassLoader to resolve classes and resources.
+     */
+    BootStrapPlatform.applyPlatformHacks();
+  }
+
   public static Test suite() {
     GWTTestSuite suite = new GWTTestSuite(
         "Test for com.google.gwt.user.client.rpc");