Initial subversion import.
The following lines are to recognize contributions made before the switch
to Subversion.
Patch by: bruce, jgw, scottb, mmendez, ecc, hcc, knorton, haeberling, samgross, mat.gessel
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/jni/build.xml b/jni/build.xml
new file mode 100755
index 0000000..c7724c7
--- /dev/null
+++ b/jni/build.xml
@@ -0,0 +1,24 @@
+<project name="jni" default="all" basedir=".">
+ <property name="gwt.root" location=".." />
+ <property name="project.tail" value="jni" />
+ <import file="${gwt.root}/common.ant.xml" />
+
+ <target name="linux" description="Builds jni/linux">
+ <ant dir="linux" inheritall="false"/>
+ </target>
+
+ <target name="windows" description="Builds jni/linux">
+ <ant dir="windows" inheritall="false"/>
+ </target>
+
+ <target name="mac" description="Builds jni/linux">
+ <ant dir="mac" inheritall="false"/>
+ </target>
+
+ <target name="clean" description="Cleans this project's intermediate and output files">
+ <delete dir="${project.build}" failonerror="false" />
+ </target>
+
+ <target name="all" depends="linux,windows,mac" description="Builds all platforms" />
+
+</project>
diff --git a/jni/core/gwt-ll.cpp b/jni/core/gwt-ll.cpp
new file mode 100644
index 0000000..4076aea
--- /dev/null
+++ b/jni/core/gwt-ll.cpp
@@ -0,0 +1,66 @@
+// Copyright 2005-2006 Google Inc.
+// All Rights Reserved.
+
+// A slim and portable set of JNI methods for GWT hosted mode
+
+#include <jni.h>
+#include <stdlib.h>
+
+extern "C" {
+
+/*
+ * Class: com_google_gwt_dev_shell_LowLevel
+ * Method: newGlobalRefInt
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_com_google_gwt_dev_shell_LowLevel__1newGlobalRefInt(JNIEnv* env, jclass, jobject o) {
+ return reinterpret_cast<int>(env->NewGlobalRef(o));
+}
+/*
+ * Class: com_google_gwt_dev_shell_LowLevel
+ * Method: objFromGlobalRefInt
+ * Signature: (I)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_google_gwt_dev_shell_LowLevel__1objFromGlobalRefInt(JNIEnv* env, jclass, jint globalRef) {
+ return reinterpret_cast<jobject>(globalRef);
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_LowLevel
+ * Method: deleteGlobalRefInt
+ * Signature: (I)I
+ */
+JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_LowLevel__1deleteGlobalRefInt(JNIEnv* env, jclass, jint globalRef) {
+ env->DeleteGlobalRef(reinterpret_cast<jobject>(globalRef));
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_LowLevel
+ * Method: getEnv
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_google_gwt_dev_shell_LowLevel__1getEnv(JNIEnv* env, jclass, jstring key) {
+ if (!key) {
+ // null -> null
+ return 0;
+ }
+
+ const char* keyPtr = env->GetStringUTFChars(key, 0);
+ if (!keyPtr) {
+ // There will be a pending OutOfMemoryException on this thread, so leave immediately and let it be thrown.
+ return 0;
+ }
+
+ const char* valuePtr = getenv(keyPtr);
+ env->ReleaseStringUTFChars(key, keyPtr);
+
+ if (!valuePtr) {
+ // no match found
+ return 0;
+ }
+
+ // return the result
+ return env->NewStringUTF(valuePtr);
+}
+
+} // extern "C"
diff --git a/jni/linux/Makefile b/jni/linux/Makefile
new file mode 100644
index 0000000..35b88fe
--- /dev/null
+++ b/jni/linux/Makefile
@@ -0,0 +1,101 @@
+# Copyright 2006 Google Inc. All Rights Reserved.
+#
+#-------------------------------------------------------------------------------
+# Macros
+#-------------------------------------------------------------------------------
+SHELL = /bin/sh
+
+##
+# Target settings
+##
+ROOTDIR = ./
+PLATFORM:= linux
+PROGNAME:= gwt-ll
+PROG := lib$(PROGNAME).so
+PROGDIR := ./
+OBJDIR := $(PROGDIR)objs/
+OUT := $(PROGDIR)image/$(PROG)
+
+##
+# Tools
+##
+CXX := gcc
+AR := ar
+STRIP := strip
+LD := $(CXX)
+
+##
+# List of source, object, and dependency paths plus the path to them
+##
+SRCDIRS := ./:../gwt-ll-core/
+VPATH := .:../gwt-ll-core
+SRCS := gwt-ll.cpp Moz.cpp
+OBJS := $(addprefix $(OBJDIR),$(SRCS:.cpp=.o))
+DEPS := $(addprefix $(OBJDIR),$(SRCS:.cpp=.d))
+
+##
+# Include path configuration
+##
+SYSINCS := \
+ $(ROOTDIR)../../third_party/j2sdk1.4.2_09/include \
+ $(ROOTDIR)../../third_party/j2sdk1.4.2_09/include/$(PLATFORM) \
+ $(ROOTDIR)../../third_party/gecko-sdk-linux/include \
+ $(ROOTDIR)../../third_party/gecko-sdk-linux/include/extra
+
+INCS := $(addprefix -i ,$(INCS)) $(addprefix -isystem ,$(SYSINCS))
+
+##
+# Libraries and library path
+##
+LIBS = xpcomglue_s
+LIBPATH = -L../../third_party/gecko-sdk-linux/lib
+LIBS := $(addprefix -l,$(LIBS))
+
+# for notes on auto-dependency generation, see
+# http://make.paulandlesley.org/autodep.html
+# -MP obviates the need for sed hackery
+CFLAGS := -Os -fPIC -fno-omit-frame-pointer -fno-strict-aliasing -D_REENTRANT -c -MMD -MP -Wno-system-headers $(CFLAGS)
+LDFLAGS := -s -fPIC -fno-omit-frame-pointer -fno-strict-aliasing -D_REENTRANT -Wl,-shared-gcc $(LDFLAGS)
+
+##
+# Clean macros
+##
+CLEANDIRS := $(CLEANDIRS) $(OBJDIR)
+CLEANFILES := $(CLEANFILES) $(OUT)
+
+#-------------------------------------------------------------------------------
+# Rules
+#-------------------------------------------------------------------------------
+
+##
+# default rule
+##
+all: $(OUT)
+
+##
+# Include the dependency rules
+##
+-include $(DEPS)
+
+##
+# Compilation rule for cpp files
+##
+$(OBJDIR)%.o : $(SRCDIR)%.cpp
+ @[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
+ $(CXX) $(CFLAGS) $(INCS) -o $@ $<
+
+##
+# Actual output file
+##
+$(OUT): $(OBJS)
+ @[ -d $(PROGDIR) ] || mkdir -p $(PROGDIR)
+ @[ -d $(PROGDIR)image ] || mkdir -p $(PROGDIR)image
+ $(LD) -shared $(LDFLAGS) $(LIBPATH) -o $@ $^ $(LIBS)
+ $(STRIP) --strip-unneeded $@
+
+##
+# Clean rule
+##
+clean:
+ @-rm -f $(CLEANFILES)
+ @-rm -rf $(CLEANDIRS)
diff --git a/jni/linux/Moz.cpp b/jni/linux/Moz.cpp
new file mode 100644
index 0000000..6a174a6
--- /dev/null
+++ b/jni/linux/Moz.cpp
@@ -0,0 +1,1097 @@
+// Copyright 2005 Google Inc.
+// All Rights Reserved.
+
+// Mozilla-specific hosted-mode methods
+
+// Mozilla header files
+#include "nsIServiceManagerUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsICategoryManager.h"
+#include "nsIScriptNameSpaceManager.h"
+#include "nsIScriptObjectOwner.h"
+#include "nsIScriptGlobalObject.h"
+#include "nsIScriptContext.h"
+#include "nsIDOMWindow.h"
+#include "nsIXPConnect.h"
+#include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
+
+#include <jni.h>
+
+static JNIEnv* gEnv = 0;
+static jclass gClass = 0;
+
+//#define FILETRACE
+//#define JAVATRACE
+#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
+static FILE* gout = 0;
+static void filetrace(const char* s)
+{
+ fprintf(gout, s);
+ fprintf(gout, "\n");
+ fflush(gout);
+}
+#endif // FILETRACE
+
+#ifdef JAVATRACE
+static jmethodID gTraceMethod = 0;
+static 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
+
+static bool InitGlobals(JNIEnv* env, jclass llClass)
+{
+ if (gEnv)
+ return true;
+
+#ifdef FILETRACE
+ gout = fopen("gwt-ll.log", "w");
+ filetrace("LOG STARTED");
+#endif // FILETRACE
+
+ gClass = static_cast<jclass>(env->NewGlobalRef(llClass));
+ if (!gClass || env->ExceptionCheck())
+ return false;
+
+#ifdef JAVATRACE
+ gTraceMethod = env->GetStaticMethodID(gClass, "trace", "(Ljava/lang/String;)V");
+ if (!gTraceMethod || env->ExceptionCheck())
+ return false;
+#endif // JAVATRACE
+
+ gEnv = env;
+ return true;
+}
+
+struct JStringWrap
+{
+ JStringWrap(JNIEnv* env, jstring str): env(env), s(str), p(0), jp(0) { }
+ ~JStringWrap() { if (p) env->ReleaseStringUTFChars(s, p); if (jp) env->ReleaseStringChars(s, jp); }
+ const char* str() { if (!p) p = env->GetStringUTFChars(s, 0); return p; }
+ const jchar* jstr() { if (!jp) jp = env->GetStringChars(s, 0); return jp; }
+private:
+ JNIEnv* env;
+ jstring s;
+ const char* p;
+ const jchar* jp;
+};
+
+static void hextrace(int val) {
+ char buf[20];
+ const char* hex = "0123456789ABCDEF";
+ for (int i = 7; i >= 0; --i) {
+ buf[i] = hex[val & 0xF];
+ val >>= 4;
+ }
+ buf[8] = 0;
+ TRACE(buf);
+}
+
+static JSBool gwt_invoke(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ TRACE("ENTER gwt_invoke");
+
+ // I kid you not; this is how XPConnect gets their function object so they can
+ // multiplex dispatch the call from a common site. See XPCDispObject.cpp(466)
+ //
+ // I now have a secondary confirmation that this trick is legit. brandon@mozilla.org
+ // writes:
+ //
+ // argv[-2] is part of the JS API, unabstracted. Just as argv[0] is the
+ // first argument (if argc != 0), argv[-1] is the |this| parameter (equal
+ // to OBJECT_TO_JSVAL(obj) in a native method with the standard |obj|
+ // second formal parameter name), and argv[-2] is the callee object, tagged
+ // as a jsval.
+ if (JS_TypeOfValue(cx, argv[-2]) != JSTYPE_FUNCTION)
+ return TRACE("FAIL gwt_invoke: JSTYPE_FUNCTION"), JS_FALSE;
+
+ JSObject* funObj = JSVAL_TO_OBJECT(argv[-2]);
+ jsval jsCleanupObj;
+
+ // Pull the wrapper object out of the funObj's reserved slot
+ if (!JS_GetReservedSlot(cx, funObj, 0, &jsCleanupObj))
+ return TRACE("FAIL gwt_invoke: JS_GetReservedSlot"), JS_FALSE;
+
+ JSObject* cleanupObj = JSVAL_TO_OBJECT(jsCleanupObj);
+ if (!cleanupObj)
+ return TRACE("FAIL gwt_invoke: cleanupObj"), JS_FALSE;
+
+ // Get dispMeth global ref out of the wrapper object
+ jobject dispMeth = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, cleanupObj));
+ if (!dispMeth)
+ return TRACE("FAIL gwt_invoke: dispMeth"), JS_FALSE;
+
+ jclass dispClass = gEnv->GetObjectClass(dispMeth);
+ if (!dispClass || gEnv->ExceptionCheck())
+ return TRACE("FAIL gwt_invoke: GetObjectClass"), JS_FALSE;
+
+ jmethodID invokeID = gEnv->GetMethodID(dispClass, "invoke", "(I[I)I");
+ if (!invokeID || gEnv->ExceptionCheck())
+ return TRACE("FAIL gwt_invoke: GetMethodID"), JS_FALSE;
+
+ jintArray jsargs = gEnv->NewIntArray(argc);
+ if (!jsargs || gEnv->ExceptionCheck())
+ return TRACE("FAIL gwt_invoke: NewIntArray"), JS_FALSE;
+
+ gEnv->SetIntArrayRegion(jsargs, 0, argc, (jint*)argv);
+ if (gEnv->ExceptionCheck())
+ return TRACE("FAIL gwt_invoke: SetIntArrayRegion"), JS_FALSE;
+
+ *rval = gEnv->CallIntMethod(dispMeth, invokeID, argv[-1], jsargs);
+ if (gEnv->ExceptionCheck())
+ return TRACE("FAIL gwt_invoke: java exception is active"), JS_FALSE;
+
+ if (JS_IsExceptionPending(cx))
+ return TRACE("FAIL gwt_invoke: js exception is active"), JS_FALSE;
+
+ TRACE("SUCCESS gwt_invoke");
+ return JS_TRUE;
+}
+
+static JSBool getJavaPropertyStats(JSContext *cx, JSObject *obj, jsval id, jclass& dispClass, jobject& dispObj, jstring& jident)
+{
+ if (!JSVAL_IS_STRING(id))
+ return JS_FALSE;
+
+ jident = gEnv->NewString(JS_GetStringChars(JSVAL_TO_STRING(id)), JS_GetStringLength(JSVAL_TO_STRING(id)));
+ if (!jident || gEnv->ExceptionCheck())
+ return JS_FALSE;
+
+ dispObj = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, obj));
+ if (!dispObj)
+ return JS_FALSE;
+
+ dispClass = gEnv->GetObjectClass(dispObj);
+ if (gEnv->ExceptionCheck())
+ return JS_FALSE;
+
+ return JS_TRUE;
+}
+
+static JSBool JS_DLL_CALLBACK gwt_nativewrapper_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ TRACE("ENTER gwt_nativewrapper_setProperty");
+
+ jclass dispClass;
+ jobject dispObj;
+ jstring ident;
+ if (!getJavaPropertyStats(cx,obj,id,dispClass,dispObj,ident))
+ return JS_FALSE;
+
+ jmethodID setFieldMeth = gEnv->GetMethodID(dispClass, "setField", "(Ljava/lang/String;I)V");
+ if (!setFieldMeth || gEnv->ExceptionCheck())
+ return JS_FALSE;
+
+ gEnv->CallVoidMethod(dispObj, setFieldMeth, ident, *vp);
+ if (gEnv->ExceptionCheck())
+ return JS_FALSE;
+
+ TRACE("SUCCESS gwt_nativewrapper_setProperty");
+ return JS_TRUE;
+}
+
+static JSBool JS_DLL_CALLBACK gwt_nativewrapper_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ TRACE("ENTER gwt_nativewrapper_getProperty");
+
+ if (*vp != JSVAL_VOID)
+ return TRACE("SUCCESS, already defined"), JS_TRUE;
+
+ jclass dispClass;
+ jobject dispObj;
+ jstring ident;
+ if (!getJavaPropertyStats(cx,obj,id,dispClass,dispObj,ident))
+ return JS_FALSE;
+
+ jmethodID getFieldMeth = gEnv->GetMethodID(dispClass, "getField", "(Ljava/lang/String;)I");
+ if (!getFieldMeth || gEnv->ExceptionCheck())
+ return JS_FALSE;
+
+ *vp = gEnv->CallIntMethod(dispObj, getFieldMeth, ident);
+ if (gEnv->ExceptionCheck())
+ return JS_FALSE;
+
+ TRACE("SUCCESS gwt_nativewrapper_getProperty");
+ return JS_TRUE;
+}
+
+static void JS_DLL_CALLBACK gwt_nativewrapper_finalize(JSContext *cx, JSObject *obj)
+{
+ jobject dispObj = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, obj));
+ if (dispObj)
+ gEnv->DeleteGlobalRef(dispObj);
+}
+
+static JSClass gwt_functionwrapper_class = {
+ "gwt_functionwrapper_class", JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, gwt_nativewrapper_finalize,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSClass gwt_nativewrapper_class = {
+ "gwt_nativewrapper_class", JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub, gwt_nativewrapper_getProperty, gwt_nativewrapper_setProperty,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, gwt_nativewrapper_finalize,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool gwtOnLoad(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ TRACE("ENTER gwtOnLoad");
+
+ if (argc < 2)
+ return JS_FALSE;
+
+ JSObject* scriptWindow = 0;
+ if (argv[0] != JSVAL_NULL && argv[0] != JSVAL_VOID) {
+ if (!JS_ValueToObject(cx, argv[0], &scriptWindow))
+ return JS_FALSE;
+ }
+
+ JSString* moduleName = 0;
+ if (argv[1] != JSVAL_NULL && argv[1] != JSVAL_VOID) {
+ moduleName = JS_ValueToString(cx, argv[1]);
+ }
+
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(0);
+ if (scriptWindow) {
+ nsCOMPtr<nsIXPConnect> xpConnect = do_GetService(nsIXPConnect::GetCID());
+ nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
+ xpConnect->GetWrappedNativeOfJSObject(cx, scriptWindow, getter_AddRefs(wrappedNative));
+ if (wrappedNative) {
+ nsCOMPtr<nsISupports> native;
+ wrappedNative->GetNative(getter_AddRefs(native));
+ scriptGlobal = do_QueryInterface(native);
+ }
+ }
+
+ jstring jModuleName(0);
+ if (moduleName) {
+ jModuleName = gEnv->NewString(JS_GetStringChars(moduleName), JS_GetStringLength(moduleName));
+ if (!jModuleName || gEnv->ExceptionCheck())
+ return JS_FALSE;
+ }
+
+ jobject externalObject = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, obj));
+ jclass objClass = gEnv->GetObjectClass(externalObject);
+ if (!objClass || gEnv->ExceptionCheck())
+ return JS_FALSE;
+
+ jmethodID methodID = gEnv->GetMethodID(objClass, "gwtOnLoad", "(ILjava/lang/String;)Z");
+ if (!methodID || gEnv->ExceptionCheck())
+ return JS_FALSE;
+
+ jboolean result = gEnv->CallBooleanMethod(externalObject, methodID, NS_REINTERPRET_CAST(jint, scriptGlobal.get()), jModuleName);
+ if (gEnv->ExceptionCheck())
+ return JS_FALSE;
+
+ *rval = BOOLEAN_TO_JSVAL((result == JNI_FALSE) ? JS_FALSE : JS_TRUE);
+ TRACE("SUCCESS gwtOnLoad");
+ return JS_TRUE;
+}
+
+class ExternalWrapper : public nsIScriptObjectOwner
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject);
+ NS_IMETHOD SetScriptObject(void* aScriptObject);
+ ExternalWrapper(): mScriptObject(0) { }
+private:
+ ~ExternalWrapper() { }
+ void *mScriptObject;
+};
+
+NS_IMPL_ISUPPORTS1(ExternalWrapper, nsIScriptObjectOwner)
+
+static JSBool JS_DLL_CALLBACK gwt_external_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ return JS_FALSE;
+}
+
+static JSBool JS_DLL_CALLBACK gwt_external_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ TRACE("ENTER gwt_external_getProperty");
+
+ if (*vp != JSVAL_VOID)
+ return TRACE("SUCCESS, already defined"), JS_TRUE;
+
+ if (!JSVAL_IS_STRING(id))
+ return TRACE("FAIL 1"), JS_FALSE;
+
+ jstring jident = gEnv->NewString(JS_GetStringChars(JSVAL_TO_STRING(id)), JS_GetStringLength(JSVAL_TO_STRING(id)));
+ if (!jident || gEnv->ExceptionCheck())
+ return TRACE("FAIL 2"), JS_FALSE;
+
+ jobject externalObject = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, obj));
+ jclass objClass = gEnv->GetObjectClass(externalObject);
+ if (!objClass || gEnv->ExceptionCheck())
+ return TRACE("FAIL 4"), JS_FALSE;
+
+ jmethodID methodID = gEnv->GetMethodID(objClass, "resolveReference", "(Ljava/lang/String;)I");
+ if (!methodID || gEnv->ExceptionCheck())
+ return TRACE("FAIL 5"), JS_FALSE;
+ int retval = gEnv->CallIntMethod(externalObject, methodID, jident);
+ if (gEnv->ExceptionCheck())
+ return TRACE("FAIL 6"), JS_FALSE;
+ *vp = retval;
+
+ TRACE("SUCCESS gwt_external_getProperty");
+ return JS_TRUE;
+}
+
+static void JS_DLL_CALLBACK gwt_external_finalize(JSContext *cx, JSObject *obj)
+{
+ jobject externalObject = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, obj));
+ if (externalObject)
+ gEnv->DeleteGlobalRef(externalObject);
+ JS_FinalizeStub(cx,obj);
+}
+
+static JSClass gwt_external_class = {
+ "gwt_external_class", JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub, gwt_external_getProperty, gwt_external_setProperty,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, gwt_external_finalize,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+class nsJSObjectLocker : public nsISupports
+{
+public:
+ NS_DECL_ISUPPORTS
+ nsJSObjectLocker(JSContext* cx, jsval val): mCx(cx), mVal(val) { if (mCx && mVal) JSVAL_LOCK(mCx,mVal); }
+
+ JSContext* const mCx;
+ const jsval mVal;
+
+ // Major hack; compare other object's vtable ptrs to this one to do crude RTTI
+ static nsJSObjectLocker sJSObjectLocker;
+
+private:
+ ~nsJSObjectLocker() { if (mCx && mVal) JSVAL_UNLOCK(mCx,mVal); }
+};
+NS_IMPL_ISUPPORTS0(nsJSObjectLocker)
+
+// Major hack; compare other object's vtable ptrs to this one to do crude RTTI
+nsJSObjectLocker nsJSObjectLocker::sJSObjectLocker(0,0);
+
+NS_IMETHODIMP ExternalWrapper::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject)
+{
+ TRACE("ENTER ExternalWrapper::GetScriptObject");
+
+ if (!aScriptObject)
+ return TRACE("FAIL 0"), NS_ERROR_INVALID_POINTER;
+
+ if (!mScriptObject)
+ {
+ *aScriptObject = 0;
+
+ nsIScriptGlobalObject* globalObject = aContext->GetGlobalObject();
+ nsCOMPtr<nsIDOMWindow> domWindow(do_QueryInterface(globalObject));
+ if (!domWindow)
+ return TRACE("FAIL 1"), NS_ERROR_UNEXPECTED;
+
+ nsCOMPtr<nsIDOMWindow> topWindow;
+ domWindow->GetTop(getter_AddRefs(topWindow));
+ if (!topWindow)
+ return TRACE("FAIL 2"), NS_ERROR_UNEXPECTED;
+
+ jmethodID methodID = gEnv->GetStaticMethodID(gClass, "createExternalObjectForDOMWindow", "(I)Lcom/google/gwt/dev/shell/moz/LowLevelMoz$ExternalObject;");
+ if (!methodID || gEnv->ExceptionCheck())
+ return TRACE("FAIL 3"), NS_ERROR_UNEXPECTED;
+
+ jobject externalObject = gEnv->CallStaticObjectMethod(gClass, methodID, NS_REINTERPRET_CAST(jint, topWindow.get()));
+ if (!externalObject || gEnv->ExceptionCheck())
+ return TRACE("FAIL 4"), NS_ERROR_UNEXPECTED;
+ externalObject = gEnv->NewGlobalRef(externalObject);
+ if (!externalObject || gEnv->ExceptionCheck())
+ return TRACE("FAIL 5"), NS_ERROR_UNEXPECTED;
+
+ JSContext* cx = NS_REINTERPRET_CAST(JSContext*,aContext->GetNativeContext());
+ if (!cx)
+ return TRACE("FAIL 6"), NS_ERROR_UNEXPECTED;
+ JSObject* newObj = JS_NewObject(cx, &gwt_external_class, 0, globalObject->GetGlobalJSObject());
+ if (!newObj)
+ return TRACE("FAIL 7"), NS_ERROR_OUT_OF_MEMORY;
+ if (!JS_SetPrivate(cx, newObj, externalObject)) {
+ gEnv->DeleteGlobalRef(externalObject);
+ return TRACE("FAIL 8"), NS_ERROR_UNEXPECTED;
+ }
+ if (!JS_DefineFunction(cx, newObj, "gwtOnLoad", gwtOnLoad, 3,
+ JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
+ return TRACE("FAIL 9"), NS_ERROR_UNEXPECTED;
+
+ mScriptObject = newObj;
+ }
+
+ *aScriptObject = mScriptObject;
+ TRACE("SUCCESS ExternalWrapper::GetScriptObject");
+ return NS_OK;
+}
+
+NS_IMETHODIMP ExternalWrapper::SetScriptObject(void* aScriptObject)
+{
+ mScriptObject = aScriptObject;
+ return NS_OK;
+}
+
+class nsRpExternalFactory : public nsIFactory
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFACTORY
+ nsRpExternalFactory() { }
+private:
+ ~nsRpExternalFactory() { }
+};
+
+NS_IMPL_ISUPPORTS1(nsRpExternalFactory, nsIFactory)
+
+NS_IMETHODIMP nsRpExternalFactory::CreateInstance(nsISupports *aOuter, const nsIID & aIID, void** aResult)
+{
+ TRACE("ENTER nsRpExternalFactory::CreateInstance");
+
+ if (!aResult)
+ return NS_ERROR_INVALID_POINTER;
+
+ *aResult = NULL;
+
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsISupports* object = new ExternalWrapper();
+ if (!object)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult result = object->QueryInterface(aIID, aResult);
+ if (!*aResult || NS_FAILED(result))
+ delete object;
+ else
+ TRACE("SUCCESS nsRpExternalFactory::CreateInstance");
+ return result;
+}
+
+NS_IMETHODIMP nsRpExternalFactory::LockFactory(PRBool lock)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#define GWT_EXTERNAL_FACTORY_CID \
+{ 0xF56E23F8, 0x5D06, 0x47F9, \
+{ 0x88, 0x5A, 0xD9, 0xCA, 0xC3, 0x38, 0x41, 0x7F } }
+#define GWT_EXTERNAL_CONTRACTID "@com.google/GWT/external;1"
+
+static NS_DEFINE_CID(kGwtExternalCID, GWT_EXTERNAL_FACTORY_CID);
+
+extern "C" {
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _coerceTo31Bits
+ * Signature: (II[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1coerceTo31Bits
+ (JNIEnv* env, jclass, jint scriptObjInt, jint v, jintArray rval)
+{
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+
+ jint r;
+ if (!JS_ValueToECMAInt32(cx, v, &r))
+ return JNI_FALSE;
+ env->SetIntArrayRegion(rval, 0, 1, &r);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _coerceToBoolean
+ * Signature: (II[Z)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1coerceToBoolean
+ (JNIEnv* env, jclass, jint scriptObjInt, jint v, jbooleanArray rval)
+{
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+
+ JSBool r;
+ if (!JS_ValueToBoolean(cx, v, &r))
+ return JNI_FALSE;
+ jboolean jr = (r == JS_FALSE) ? JNI_FALSE : JNI_TRUE;
+ env->SetBooleanArrayRegion(rval, 0, 1, &jr);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _coerceToDouble
+ * Signature: (II[D)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1coerceToDouble
+ (JNIEnv* env, jclass, jint scriptObjInt, jint v, jdoubleArray rval)
+{
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+
+ jdouble r;
+ if (!JS_ValueToNumber(cx, v, &r))
+ return JNI_FALSE;
+ env->SetDoubleArrayRegion(rval, 0, 1, &r);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _coerceToString
+ * Signature: (II[Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1coerceToString
+ (JNIEnv* env, jclass, jint scriptObjInt, jint v, jobjectArray rval)
+{
+ jstring jr(0);
+ if (v != JSVAL_NULL && v != JSVAL_VOID) {
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+
+ JSString* str = JS_ValueToString(cx, v);
+ if (!str)
+ return JNI_FALSE;
+ jr = env->NewString(JS_GetStringChars(str), JS_GetStringLength(str));
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+ }
+ env->SetObjectArrayElement(rval, 0, jr);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _convert31Bits
+ * Signature: (II[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1convert31Bits
+ (JNIEnv* env, jclass, int scriptObjInt, jint v, jintArray rval)
+{
+ jint r = INT_TO_JSVAL(v);
+ env->SetIntArrayRegion(rval, 0, 1, &r);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _convertBoolean
+ * Signature: (IZ[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1convertBoolean
+ (JNIEnv* env, jclass, int scriptObjInt, jboolean v, jintArray rval)
+{
+ jint r = BOOLEAN_TO_JSVAL((v == JNI_FALSE) ? JS_FALSE : JS_TRUE);
+ env->SetIntArrayRegion(rval, 0, 1, &r);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _convertDouble
+ * Signature: (ID[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1convertDouble
+ (JNIEnv* env, jclass, int scriptObjInt, jdouble v, jintArray rval)
+{
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+
+ jsval rv;
+ if (!JS_NewDoubleValue(cx, jsdouble(v), &rv))
+ return JNI_FALSE;
+ jint r = rv;
+ env->SetIntArrayRegion(rval, 0, 1, &r);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _convertString
+ * Signature: (ILjava/lang/String;[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1convertString
+ (JNIEnv* env, jclass, int scriptObjInt, jstring v, jintArray rval)
+{
+ jint r = 0;
+ if (v) {
+ JStringWrap jv(env, v);
+ if (!jv.jstr())
+ return JNI_FALSE;
+
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+
+ JSString* str = JS_NewUCStringCopyZ(cx, jv.jstr());
+ if (!str)
+ return JNI_FALSE;
+
+ r = STRING_TO_JSVAL(str);
+ }
+
+ env->SetIntArrayRegion(rval, 0, 1, &r);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _executeScript
+ * Signature: (ILjava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1executeScript
+ (JNIEnv* env, jclass llClass, jint scriptObject, jstring code)
+{
+ JStringWrap jcode(env, code);
+ if (!jcode.jstr())
+ return JNI_FALSE;
+
+ nsIScriptGlobalObject* globalObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObject);
+ nsCOMPtr<nsIScriptContext> scriptContext(globalObject->GetContext());
+ nsXPIDLString scriptString;
+ scriptString = jcode.jstr();
+
+ nsXPIDLString aRetValue;
+ PRBool aIsUndefined;
+ if (NS_FAILED(scriptContext->EvaluateString(scriptString, globalObject->GetGlobalJSObject(),
+ 0, __FILE__, __LINE__, 0, aRetValue, &aIsUndefined)))
+ return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _executeScriptWithInfo
+ * Signature: (ILjava/lang/String;Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1executeScriptWithInfo
+ (JNIEnv* env, jclass llClass, jint scriptObject, jstring code, jstring file, jint line)
+{
+ JStringWrap jcode(env, code);
+ if (!jcode.jstr())
+ return JNI_FALSE;
+
+ JStringWrap jfile(env, file);
+ if (!jfile.str())
+ return JNI_FALSE;
+
+ nsIScriptGlobalObject* globalObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObject);
+ nsCOMPtr<nsIScriptContext> scriptContext(globalObject->GetContext());
+ nsXPIDLString scriptString;
+ scriptString = jcode.jstr();
+
+ nsXPIDLString aRetValue;
+ PRBool aIsUndefined;
+ if (NS_FAILED(scriptContext->EvaluateString(scriptString, globalObject->GetGlobalJSObject(),
+ 0, jfile.str(), line, 0, aRetValue, &aIsUndefined)))
+ return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _invoke
+ * Signature: (ILjava/lang/String;II[I[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1invoke
+ (JNIEnv* env, jclass, int scriptObjInt, jstring methodName, jint jsthisval, jint jsargc, jintArray jsargs, jintArray rval)
+{
+ TRACE("ENTER Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1invoke");
+
+ JStringWrap methodStr(env,methodName);
+ if (!methodStr.str())
+ return TRACE("FAIL 1"), JNI_FALSE;
+
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return TRACE("FAIL 2"), JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+ JSObject* scriptWindow = (JSObject*)scriptObject->GetGlobalJSObject();
+
+ jsval fval;
+ if (!JS_GetProperty(cx, scriptWindow, methodStr.str(), &fval))
+ return TRACE("FAIL 3"), JNI_FALSE;
+ if (!JS_ValueToFunction(cx, fval))
+ return TRACE("FAIL 4"), JNI_FALSE;
+
+ nsAutoArrayPtr<jint> jsargvals(new jint[jsargc]);
+ if (!jsargvals)
+ return TRACE("FAIL 5"), JNI_FALSE;
+
+ env->GetIntArrayRegion(jsargs, 0, jsargc, jsargvals);
+ if (env->ExceptionCheck())
+ return TRACE("FAIL 6"), JNI_FALSE;
+
+ jsval jsrval;
+ JSObject* jsthis = (jsthisval == JSVAL_NULL) ? scriptWindow : JSVAL_TO_OBJECT(jsthisval);
+ if (!JS_CallFunctionValue(cx, jsthis, fval, jsargc, (jsval*)jsargvals.get(), &jsrval))
+ return TRACE("FAIL 7"), JNI_FALSE;
+
+ env->SetIntArrayRegion(rval, 0, 1, (jint*)&jsrval);
+ if (env->ExceptionCheck())
+ return TRACE("FAIL 8"), JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1invoke");
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _isWrappedDispatch
+ * Signature: (II[Z)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1isWrappedDispatch
+ (JNIEnv* env, jclass, jint scriptObjInt, jint jsobjval, jbooleanArray rval)
+{
+ TRACE("ENTER Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1isWrappedDispatch");
+
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+
+ jboolean r = JNI_FALSE;
+ if (JSVAL_IS_OBJECT(jsobjval))
+ {
+ JSObject* jsobj = JSVAL_TO_OBJECT(jsobjval);
+ if (JS_InstanceOf(cx, jsobj, &gwt_nativewrapper_class, 0))
+ r = JNI_TRUE;
+ }
+
+ env->SetBooleanArrayRegion(rval, 0, 1, &r);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1isWrappedDispatch");
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _raiseJavaScriptException
+ * Signature: (II)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1raiseJavaScriptException
+ (JNIEnv* env, jclass, jint scriptObjInt, jint jsarg)
+{
+ TRACE("ENTER Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1raiseJavaScriptException");
+
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+ JS_SetPendingException(cx, jsarg);
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1raiseJavaScriptException");
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _registerExternalFactoryHandler
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1registerExternalFactoryHandler
+ (JNIEnv* env, jclass llClass)
+{
+ if (!InitGlobals(env, llClass))
+ return JNI_FALSE;
+
+ TRACE("ENTER Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1registerExternalFactoryHandler");
+
+ // Register "window.external" as our own class
+ if (NS_FAILED(nsComponentManager::RegisterFactory(
+ kGwtExternalCID, "externalFactory", GWT_EXTERNAL_CONTRACTID,
+ new nsRpExternalFactory(), PR_TRUE)))
+ return JNI_FALSE;
+
+ nsCOMPtr<nsICategoryManager> categoryManager = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
+ if (!categoryManager)
+ return JNI_FALSE;
+
+ nsXPIDLCString previous;
+ if (NS_FAILED(categoryManager->AddCategoryEntry(JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY,
+ "external", GWT_EXTERNAL_CONTRACTID,
+ PR_TRUE, PR_TRUE, getter_Copies(previous))))
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1registerExternalFactoryHandler");
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _unwrapDispatch
+ * Signature: (II[Lcom/google/gwt/dev/shell/moz/LowLevelMoz/DispatchObject;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1unwrapDispatch
+ (JNIEnv* env, jclass, jint scriptObjInt, jint jsobjval, jobjectArray rval)
+{
+ TRACE("ENTER Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1unwrapDispatch");
+
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+
+ if (!JSVAL_IS_OBJECT(jsobjval))
+ return JNI_FALSE;
+
+ JSObject* jsobj = JSVAL_TO_OBJECT(jsobjval);
+ if (!JS_InstanceOf(cx, jsobj, &gwt_nativewrapper_class, 0))
+ return JNI_FALSE;
+
+ jobject dispObj = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, jsobj));
+ if (!dispObj)
+ return JNI_FALSE;
+
+ env->SetObjectArrayElement(rval, 0, dispObj);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1unwrapDispatch");
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _unwrapJSObject
+ * Signature: (I[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1unwrapJSObject
+ (JNIEnv* env, jclass, jint nsISupportsPtr, jintArray rval)
+{
+ TRACE("ENTER Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1unwrapJSObject");
+
+ // MAJOR HACK: check the vtable ptr against a known "good" as a very crude RTTI
+ long *vt1 = NS_REINTERPRET_CAST(long*,NS_STATIC_CAST(nsISupports*, &nsJSObjectLocker::sJSObjectLocker));
+ long *vt2 = NS_REINTERPRET_CAST(long*,nsISupportsPtr);
+ if (*vt1 != *vt2)
+ return JNI_FALSE;
+
+ // probably safe
+ nsJSObjectLocker* jsObjectLocker = NS_STATIC_CAST(nsJSObjectLocker*, NS_REINTERPRET_CAST(nsISupports*,nsISupportsPtr));
+ jsval r = jsObjectLocker->mVal;
+ if (!JSVAL_IS_OBJECT(r))
+ return JNI_FALSE;
+
+ env->SetIntArrayRegion(rval, 0, 1, (jint*)&r);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1unwrapJSObject");
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _wrapDispatch
+ * Signature: (ILcom/google/gwt/dev/shell/moz/LowLevelMoz/DispatchObject;[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1wrapDispatch
+ (JNIEnv* env, jclass, jint scriptObjInt, jobject dispObj, jintArray rval)
+{
+ TRACE("ENTER Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1wrapDispatch");
+
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+ JSObject* scriptWindow = (JSObject*)scriptObject->GetGlobalJSObject();
+
+ JSObject* newObj = JS_NewObject(cx, &gwt_nativewrapper_class, 0, scriptWindow);
+ if (!newObj)
+ return JNI_FALSE;
+
+ jobject dispObjRef = env->NewGlobalRef(dispObj);
+ if (!dispObjRef || env->ExceptionCheck())
+ return JNI_FALSE;
+
+ if (!JS_SetPrivate(cx, newObj, dispObjRef))
+ {
+ env->DeleteGlobalRef(dispObjRef);
+ return JNI_FALSE;
+ }
+
+ // forcibly setup a "toString" method to override the default
+ jclass dispClass = env->GetObjectClass(dispObj);
+ if (env->ExceptionCheck())
+ return JS_FALSE;
+
+ jmethodID getFieldMeth = env->GetMethodID(dispClass, "getField", "(Ljava/lang/String;)I");
+ if (!getFieldMeth || env->ExceptionCheck())
+ return JS_FALSE;
+
+ jstring ident = env->NewStringUTF("@java.lang.Object::toString()");
+ if (!ident || env->ExceptionCheck())
+ return JS_FALSE;
+
+ jsval toStringFunc = env->CallIntMethod(dispObj, getFieldMeth, ident);
+ if (env->ExceptionCheck())
+ return JS_FALSE;
+
+ if (!JS_DefineProperty(cx, newObj, "toString", toStringFunc, JS_PropertyStub, JS_PropertyStub, JSPROP_READONLY | JSPROP_PERMANENT))
+ return JNI_FALSE;
+
+ env->SetIntArrayRegion(rval, 0, 1, (jint*)&newObj);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1wrapDispatch");
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _wrapFunction
+ * Signature: (ILjava/lang/String;Lcom/google/gwt/dev/shell/moz/LowLevelMoz/DispatchMethod;[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1wrapFunction
+ (JNIEnv* env, jclass, jint scriptObjInt, jstring name, jobject dispMeth, jintArray rval)
+{
+ TRACE("ENTER Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1wrapFunction");
+
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+ JSObject* scriptWindow = (JSObject*)scriptObject->GetGlobalJSObject();
+
+ JStringWrap nameStr(env, name);
+ if (!nameStr.str())
+ return JNI_FALSE;
+
+ JSFunction* function = JS_NewFunction(cx, gwt_invoke, 0, JSFUN_LAMBDA, 0, nameStr.str());
+ if (!function)
+ return JNI_FALSE;
+
+ JSObject* funObj = JS_GetFunctionObject(function);
+ if (!funObj)
+ return JNI_FALSE;
+
+ // Create a wrapper object to hold and clean up dispMeth
+ JSObject* cleanupObj = JS_NewObject(cx, &gwt_functionwrapper_class, 0, scriptWindow);
+ if (!cleanupObj)
+ return JNI_FALSE;
+
+ jobject dispMethRef = env->NewGlobalRef(dispMeth);
+ if (!dispMethRef || env->ExceptionCheck())
+ return JNI_FALSE;
+
+ // Store our global ref in the wrapper object
+ if (!JS_SetPrivate(cx, cleanupObj, dispMethRef))
+ {
+ env->DeleteGlobalRef(dispMethRef);
+ return JNI_FALSE;
+ }
+
+ // Store the wrapper object in funObj's reserved slot
+ if(!JS_SetReservedSlot(cx, funObj, 0, OBJECT_TO_JSVAL(cleanupObj)))
+ return JS_FALSE;
+
+ env->SetIntArrayRegion(rval, 0, 1, (jint*)&funObj);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1wrapFunction");
+ return JNI_TRUE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_moz_LowLevelMoz
+ * Method: _wrapJSObject
+ * Signature: (II[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1wrapJSObject
+ (JNIEnv* env, jclass, jint scriptObjInt, jint jsobjval, jintArray rval)
+{
+ TRACE("ENTER Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1wrapJSObject");
+
+ if (!JSVAL_IS_OBJECT(jsobjval))
+ return JNI_FALSE;
+
+ nsIScriptGlobalObject* scriptObject = NS_REINTERPRET_CAST(nsIScriptGlobalObject*, scriptObjInt);
+ nsCOMPtr<nsIScriptContext> scriptContext(scriptObject->GetContext());
+ if (!scriptContext)
+ return JNI_FALSE;
+ JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
+
+ nsISupports* objLocker = new nsJSObjectLocker(cx, jsobjval);
+ if (!objLocker)
+ return JNI_FALSE;
+
+ jint r = (jint)objLocker;
+ env->SetIntArrayRegion(rval, 0, 1, &r);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ objLocker->AddRef();
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_moz_LowLevelMoz__1wrapJSObject");
+ return JNI_TRUE;
+}
+
+} // extern "C"
diff --git a/jni/linux/build.xml b/jni/linux/build.xml
new file mode 100755
index 0000000..db0db0f
--- /dev/null
+++ b/jni/linux/build.xml
@@ -0,0 +1,20 @@
+<project name="jni-linux" default="all" basedir=".">
+ <property name="gwt.root" location="../.." />
+ <property name="project.tail" value="jni/linux" />
+ <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>
+
+ <target name="all" depends="build" description="Builds and packages this project" />
+</project>
diff --git a/jni/linux/prebuilt/libgwt-ll.so b/jni/linux/prebuilt/libgwt-ll.so
new file mode 100755
index 0000000..ee03c5e
--- /dev/null
+++ b/jni/linux/prebuilt/libgwt-ll.so
Binary files differ
diff --git a/jni/mac/DispWrapper.cpp b/jni/mac/DispWrapper.cpp
new file mode 100644
index 0000000..68eb09f
--- /dev/null
+++ b/jni/mac/DispWrapper.cpp
@@ -0,0 +1,89 @@
+// Copyright 2005 Google Inc.
+// All Rights Reserved.
+
+#include "DispWrapper.h"
+#include "FunctionObject.h"
+
+using namespace KJS;
+
+const ClassInfo DispWrapper::info = {"DispWrapper", 0, 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();
+}
+
+DispWrapper::DispWrapper(jobject dispObj): dispObj(dispObj) {
+}
+
+DispWrapper::~DispWrapper() {
+ gEnv->DeleteGlobalRef(dispObj);
+}
+
+bool DispWrapper::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) {
+ slot.setCustom(this, getter);
+ return true;
+}
+
+bool DispWrapper::canPut(ExecState *exec, const Identifier &propertyName) const {
+ return true;
+}
+
+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;
+ }
+
+ gEnv->CallVoidMethod(dispObj, gSetFieldMeth, jpropName, (jint)value);
+ if (gEnv->ExceptionCheck()) {
+ gEnv->ExceptionClear();
+ return;
+ }
+ TRACE("SUCCESS DispWrapper::put");
+}
+
+bool DispWrapper::deleteProperty(ExecState *exec, const Identifier &propertyName) {
+ return false;
+}
+
+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()));
+ }
+}
+
+bool DispWrapper::implementsCall() const {
+ return false;
+}
+
+JSValue *DispWrapper::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) {
+ return jsUndefined();
+}
diff --git a/jni/mac/DispWrapper.h b/jni/mac/DispWrapper.h
new file mode 100644
index 0000000..4eed813
--- /dev/null
+++ b/jni/mac/DispWrapper.h
@@ -0,0 +1,43 @@
+// Copyright 2005 Google Inc.
+// All Rights Reserved.
+
+#ifndef DISP_WRAPPER_H
+#define DISP_WRAPPER_H
+
+#include "gwt-webkit.h"
+#include <kjs/object.h>
+
+// This class actually wraps Java objects
+class DispWrapper : public KJS::JSObject {
+public:
+ // dispObj MUST be a global ref
+ DispWrapper(jobject dispObj);
+ virtual ~DispWrapper();
+ jobject getDispObj();
+
+public:
+ // implementations of JSObject methods
+ const KJS::ClassInfo *classInfo() const { return &info; }
+
+ virtual bool getOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&);
+ virtual bool canPut(KJS::ExecState*, const KJS::Identifier&) const;
+ virtual void put(KJS::ExecState*, const KJS::Identifier&, KJS::JSValue*, int);
+ virtual bool deleteProperty(KJS::ExecState*, const KJS::Identifier&);
+ virtual KJS::JSValue *defaultValue(KJS::ExecState*, KJS::JSType) const;
+ virtual bool implementsCall() const;
+ virtual KJS::JSValue *callAsFunction(KJS::ExecState*, KJS::JSObject*, const KJS::List&);
+
+ static const KJS::ClassInfo info;
+
+private:
+ static KJS::JSValue* getter(KJS::ExecState*, KJS::JSObject*, const KJS::Identifier&, const KJS::PropertySlot&);
+
+private:
+ jobject dispObj;
+};
+
+inline jobject DispWrapper::getDispObj() {
+ return dispObj;
+}
+
+#endif
diff --git a/jni/mac/FuncWrapper.cpp b/jni/mac/FuncWrapper.cpp
new file mode 100644
index 0000000..e44ca03
--- /dev/null
+++ b/jni/mac/FuncWrapper.cpp
@@ -0,0 +1,42 @@
+// Copyright 2005 Google Inc.
+// All Rights Reserved.
+
+#include "FuncWrapper.h"
+#include <kjs/array_object.h>
+
+using namespace KJS;
+
+// FuncWrapper
+FuncWrapper::FuncWrapper(const UString& name, jobject funcObj): FunctionObject(name)
+, funcObj(funcObj) {
+}
+
+FuncWrapper::~FuncWrapper() {
+ gEnv->DeleteGlobalRef(funcObj);
+}
+
+JSValue *FuncWrapper::callAsFunction(ExecState* execState, JSObject* thisObj, const List& args) {
+ TRACE("ENTER FuncWrapper::callAsFunction");
+
+ int argc = args.size();
+ jintArray jsargs = gEnv->NewIntArray(argc);
+ if (!jsargs || gEnv->ExceptionCheck())
+ return TRACE("FAIL FuncWrapper::callAsFunction: NewIntArray"), jsUndefined();
+
+ for (int i = 0; i < argc; ++i) {
+ JSValue* arg = args[i];
+ gEnv->SetIntArrayRegion(jsargs, i, 1, (jint*)&arg);
+ if (gEnv->ExceptionCheck())
+ return TRACE("FAIL FuncWrapper::callAsFunction: SetIntArrayRegion"), jsUndefined();
+ }
+
+ jint result = gEnv->CallIntMethod(funcObj, gInvokeMeth, execState, thisObj, jsargs);
+ if (gEnv->ExceptionCheck())
+ return TRACE("FAIL FuncWrapper::callAsFunction: java exception is active"), jsUndefined();
+
+ if (execState->hadException())
+ return TRACE("FAIL FuncWrapper::callAsFunction: js exception is active"), jsUndefined();
+
+ TRACE("SUCCESS FuncWrapper::callAsFunction");
+ return (JSValue*)result;
+}
diff --git a/jni/mac/FuncWrapper.h b/jni/mac/FuncWrapper.h
new file mode 100644
index 0000000..8019754
--- /dev/null
+++ b/jni/mac/FuncWrapper.h
@@ -0,0 +1,29 @@
+// Copyright 2005 Google Inc.
+// All Rights Reserved.
+
+#ifndef FUNC_WRAPPER_H
+#define FUNC_WRAPPER_H
+
+#include "FunctionObject.h"
+#include <jni.h>
+
+// This class actually wraps Java method objects
+class FuncWrapper : public FunctionObject {
+public:
+ // funcObj MUST be a global ref
+ FuncWrapper(const KJS::UString& name, jobject funcObj);
+ virtual ~FuncWrapper();
+ jobject getFuncObj();
+
+public:
+ virtual KJS::JSValue *callAsFunction(KJS::ExecState*, KJS::JSObject*, const KJS::List&);
+
+private:
+ jobject funcObj;
+};
+
+inline jobject FuncWrapper::getFuncObj() {
+ return funcObj;
+}
+
+#endif
diff --git a/jni/mac/FunctionObject.cpp b/jni/mac/FunctionObject.cpp
new file mode 100644
index 0000000..8e013cd
--- /dev/null
+++ b/jni/mac/FunctionObject.cpp
@@ -0,0 +1,132 @@
+// Copyright 2005 Google Inc.
+// All Rights Reserved.
+
+#include "FunctionObject.h"
+#include <kjs/array_object.h>
+
+using namespace KJS;
+
+const ClassInfo FunctionObject::info = {"Function", 0, 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->dynamicInterpreter()->globalObject();
+ else
+ callThis = thisArg->toObject(exec);
+
+ return func->call(exec, callThis, args.copyTail());
+ }
+};
+
+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->dynamicInterpreter()->globalObject();
+ 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, lengthPropertyName)->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/FunctionObject.h
new file mode 100644
index 0000000..0860f5b
--- /dev/null
+++ b/jni/mac/FunctionObject.h
@@ -0,0 +1,43 @@
+// Copyright 2005 Google Inc.
+// All Rights Reserved.
+
+#ifndef FUNCTION_OBJECT_H
+#define FUNCTION_OBJECT_H
+
+#include "gwt-webkit.h"
+#include <kjs/object.h>
+
+class FunctionObject : public KJS::JSObject {
+protected:
+ FunctionObject(const KJS::UString& name);
+
+public:
+ const KJS::ClassInfo *classInfo() const { return &info; }
+
+ // shared implementations of JSObject methods
+ virtual bool getOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&);
+ virtual bool canPut(KJS::ExecState*, const KJS::Identifier&) const;
+ virtual void put(KJS::ExecState*, const KJS::Identifier&, KJS::JSValue*, int);
+ virtual bool deleteProperty(KJS::ExecState*, const KJS::Identifier&);
+ virtual KJS::JSValue *defaultValue(KJS::ExecState*, KJS::JSType) const;
+ virtual bool implementsCall() const;
+
+ // subclasses must implement
+ virtual KJS::JSValue *callAsFunction(KJS::ExecState*, KJS::JSObject*, const KJS::List&) = 0;
+
+ static const KJS::ClassInfo info;
+
+private:
+ static KJS::JSValue* getter(KJS::ExecState*, KJS::JSObject*, const KJS::Identifier&, const KJS::PropertySlot&);
+
+private:
+ KJS::UString name;
+};
+
+class ToStringFunction : public FunctionObject {
+public:
+ ToStringFunction();
+ virtual KJS::JSValue *callAsFunction(KJS::ExecState*, KJS::JSObject*, const KJS::List&);
+};
+
+#endif
diff --git a/jni/mac/JStringWrap.h b/jni/mac/JStringWrap.h
new file mode 100644
index 0000000..2bb5c35
--- /dev/null
+++ b/jni/mac/JStringWrap.h
@@ -0,0 +1,23 @@
+// Copyright 2005 Google Inc.
+// All Rights Reserved.
+
+#ifndef JSTRINGWRAP_H
+#define JSTRINGWRAP_H
+
+#include <jni.h>
+
+struct JStringWrap
+{
+ JStringWrap(JNIEnv* env, jstring str): env(env), s(str), p(0), jp(0) { }
+ ~JStringWrap() { if (p) env->ReleaseStringUTFChars(s, p); if (jp) env->ReleaseStringChars(s, jp); }
+ const char* str() { if (!p) p = env->GetStringUTFChars(s, 0); return p; }
+ const jchar* jstr() { if (!jp) jp = env->GetStringChars(s, 0); return jp; }
+ jsize length() { return env->GetStringLength(s); }
+private:
+ JNIEnv* env;
+ jstring s;
+ const char* p;
+ const jchar* jp;
+};
+
+#endif
diff --git a/jni/mac/Makefile b/jni/mac/Makefile
new file mode 100644
index 0000000..ea0cf31
--- /dev/null
+++ b/jni/mac/Makefile
@@ -0,0 +1,31 @@
+# NOTE: THIS MAKEFILE DOES NOT WORK IN OUR BUILD SYSTEM. IT IS USED
+# TO DO THE ISOLATED BUILD OF THE MAC LIBS AND DEPENDS ON A DIFFERENT
+# DIRECTORY STRUCTURE. IT IS PUT HERE FOR ARCHIVE ONLY.
+
+GWT_LIB=../dist/libgwt-ll.jnilib
+
+CC = g++
+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
+WEBKITCFLAGS = $(CFLAGS) -I../WebKit-15921/JavaScriptCore
+WEBKITLFLAGS = $(LFLAGS) -framework JavaScriptCore -F../dist/Frameworks
+GWT_OBJECTS = gwt-ll.o
+WEBKIT_OBJECTS = gwt-webkit.o DispWrapper.o FuncWrapper.o FunctionObject.o
+
+all: $(GWT_LIB)
+
+%.o: %.cpp
+ $(CC) -c -o $@ $< $(WEBKITCFLAGS)
+
+gwt-ll.o: ../gwt-ll-core/gwt-ll.cpp
+ $(CC) $(CFLAGS) gwt-ll.cpp
+
+$(GWT_LIB): $(GWT_OBJECTS) $(WEBKIT_OBJECTS)
+ $(CC) -o $(WEBKIT_LIB) $(WEBKITLFLAGS) $(WEBKIT_OBJECTS)
+
+install: all
+ cp *.jnilib $(OUTPUT_DIR)
+
+clean:
+ rm -f $(GWT_LIB) $(WEBKIT_LIB) *.o
diff --git a/jni/mac/build.xml b/jni/mac/build.xml
new file mode 100755
index 0000000..37146d8
--- /dev/null
+++ b/jni/mac/build.xml
@@ -0,0 +1,20 @@
+<project name="jni-mac" default="all" 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>
+
+ <target name="all" depends="build" description="Builds and packages this project" />
+</project>
diff --git a/jni/mac/gwt-ll.h b/jni/mac/gwt-ll.h
new file mode 100644
index 0000000..a2df826
--- /dev/null
+++ b/jni/mac/gwt-ll.h
@@ -0,0 +1,237 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_google_gwt_dev_shell_mac_LowLevelSaf */
+
+#ifndef _Included_com_google_gwt_dev_shell_mac_LowLevelSaf
+#define _Included_com_google_gwt_dev_shell_mac_LowLevelSaf
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * 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 *, jclass, jint);
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: isUndefined
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isUndefined
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: jsNull
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_jsNull
+ (JNIEnv *, jclass);
+
+/*
+ * 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 *, jclass);
+
+/*
+ * 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 *, jclass, jint, jint, jbooleanArray);
+
+/*
+ * 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 *, jclass, jint, jint, jdoubleArray);
+
+/*
+ * 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 *, jclass, jint, jint, jobjectArray);
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: _convertBoolean
+ * Signature: (Z[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1convertBoolean
+ (JNIEnv *, jclass, jboolean, jintArray);
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: _convertDouble
+ * Signature: (D[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1convertDouble
+ (JNIEnv *, jclass, jdouble, jintArray);
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: _convertString
+ * Signature: (Ljava/lang/String;[I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1convertString
+ (JNIEnv *, jclass, jstring, jintArray);
+
+/*
+ * 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 *, jclass, jint, jstring);
+
+/*
+ * 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 *, jclass, jint, jstring, jstring, jint);
+
+/*
+ * 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);
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: _gcUnlock
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1gcUnlock
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: _getArgc
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1getArgc
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: _getArgv
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1getArgv
+ (JNIEnv *, jclass, jint);
+
+/*
+ * 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 *, jclass, jint, jintArray);
+
+/*
+ * 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 *, jclass, jclass, jclass);
+
+/*
+ * 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 *, jclass, jint, jint, jstring, jint, jint, jintArray, jintArray);
+
+/*
+ * 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);
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: _isString
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1isString
+ (JNIEnv *, jclass, jint);
+
+/*
+ * 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 *, jclass, jint, jbooleanArray);
+
+/*
+ * 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);
+
+/*
+ * 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);
+
+/*
+ * 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 *, jclass, jint, jint);
+
+/*
+ * 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 *, jclass, jint, jobjectArray);
+
+/*
+ * 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 *, jclass, jobject, jintArray);
+
+/*
+ * 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 *, jclass, jstring, jobject, jintArray);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/jni/mac/gwt-webkit.cpp b/jni/mac/gwt-webkit.cpp
new file mode 100644
index 0000000..ec2dfaf
--- /dev/null
+++ b/jni/mac/gwt-webkit.cpp
@@ -0,0 +1,609 @@
+// Copyright 2005 Google Inc.
+// All Rights Reserved.
+
+#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;
+
+/*
+ * 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 Java_com_google_gwt_dev_shell_mac_LowLevelSaf__isNull");
+
+ JSValue* val = (JSValue*)jsval;
+ if (!val)
+ return JNI_FALSE;
+
+ TRACE("SUCESS Java_com_google_gwt_dev_shell_mac_LowLevelSaf__isNull");
+ return val->isNull();
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: isUndefined
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isUndefined
+ (JNIEnv *env, jclass, jint jsval) {
+ TRACE("ENTER Java_com_google_gwt_dev_shell_mac_LowLevelSaf__isUndefined");
+ JSValue* val = (JSValue*)jsval;
+ if (!val)
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_LowLevelSaf__isUndefined");
+ return val->isUndefined();
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: jsNull
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_jsNull
+ (JNIEnv *, jclass) {
+ return (jint)jsNull();
+}
+
+/*
+ * 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 (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 Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1convertBoolean");
+
+ JSValue *jsval = (jval == JNI_FALSE) ? jsBoolean(false) : jsBoolean(true);
+ if (!jsval)
+ return JNI_FALSE;
+
+ env->SetIntArrayRegion(rval,0,1,(const jint*)&jsval);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1convertDouble");
+
+ JSValue *jsval = jsNumber(jval);
+ if (!jsval)
+ return JNI_FALSE;
+
+ env->SetIntArrayRegion(rval,0,1,(const jint*)&jsval);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1convertString");
+
+ JStringWrap jstr(env, jval);
+ if (!jstr.jstr())
+ return JNI_FALSE;
+
+ JSValue *jsval = jsString(UString((const UChar*)jstr.jstr(), jstr.length()));
+ /*
+ * TODO / LEAK / HACK: We will be persisting these objects on the java side,
+ * so in order to keep the JS GC from collecting our objects when they are
+ * away, we need to add them to the protect list. This should be refactored
+ * out in favor of better memory mgmt scheme.
+ */
+ gcProtectNullTolerant(jsval);
+ if (!jsval)
+ return JNI_FALSE;
+
+ env->SetIntArrayRegion(rval,0,1,(const jint*)&jsval);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1executeScript");
+ if (!execState || !code)
+ return JNI_FALSE;
+
+ JStringWrap jcode(env, code);
+ if (!jcode.jstr())
+ return JNI_FALSE;
+
+ Interpreter* interp = ((ExecState*)execState)->dynamicInterpreter();
+ if (!interp)
+ return JNI_FALSE;
+
+ interp->evaluate(UString(), 0, (const UChar*)jcode.jstr(), jcode.length());
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1executeScript");
+ return JNI_TRUE;
+}
+
+/*
+ * 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 Java_com_google_gwt_dev_shell_mac_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;
+
+ Interpreter* interp = ((ExecState*)execState)->dynamicInterpreter();
+ if (!interp)
+ return JNI_FALSE;
+
+ interp->evaluate(UString((const UChar*)jfile.jstr(), jfile.length()), line, (const UChar*)jcode.jstr(), jcode.length());
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1executeScriptWithInfo");
+ return JNI_TRUE;
+}
+
+/*
+ * 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) {
+ gcProtectNullTolerant((JSValue*)jsval);
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: _gcUnlock
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1gcUnlock
+ (JNIEnv *, jclass, jint jsval) {
+ gcUnprotectNullTolerant((JSValue*)jsval);
+}
+
+/*
+ * 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 Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1getGlobalExecState");
+
+ if (!scriptObject || !((JSValue*)scriptObject)->isObject())
+ return JNI_FALSE;
+
+ Interpreter* interp = Interpreter::interpreterWithGlobalObject((JSObject*)scriptObject);
+ if (!interp)
+ return JNI_FALSE;
+
+ ExecState* execState = interp->globalExec();
+ env->SetIntArrayRegion(rval, 0, 1, (jint*)&execState);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_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("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 Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1invoke");
+
+ if (!jsexecState || !jsScriptObject || !method || !rval)
+ return JNI_FALSE;
+
+ ExecState* execState = (ExecState*)jsexecState;
+
+ JSObject* scriptObj = (JSObject*)jsScriptObject;
+ if (!scriptObj->isObject())
+ return JNI_FALSE;
+
+ JStringWrap jmethod(env, method);
+ 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;
+
+ if (argi) {
+ args.append((JSValue*)argi);
+ } else {
+ args.append(jsNull());
+ }
+ }
+
+ JSValue* result = func->call(execState, thisObj, args);
+ env->SetIntArrayRegion(rval, 0, 1, (jint*)&result);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1invoke");
+ return JNI_TRUE;
+}
+
+/*
+ * 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 ((JSValue*)jsval)->isObject() ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: com_google_gwt_dev_shell_mac_LowLevelSaf
+ * Method: _isString
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1isString
+ (JNIEnv *, jclass, jint jsval) {
+ if (!jsval)
+ return JNI_FALSE;
+ return ((JSValue*)jsval)->isString() ? 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 Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1raiseJavaScriptException");
+
+ if (!execState || !jsval)
+ return JNI_FALSE;
+
+ ((ExecState*)execState)->setException((JSValue*)jsval);
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1unwrapDispatch");
+ if (!jsval)
+ return JNI_FALSE;
+
+ JSValue* val = (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 Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_LowLevelSaf__1wrapDispatch");
+
+ jobject dispObjRef = env->NewGlobalRef(dispObj);
+ if (!dispObjRef || env->ExceptionCheck())
+ return JNI_FALSE;
+
+ DispWrapper* wrapper = new DispWrapper(dispObjRef);
+ /*
+ * TODO / LEAK / HACK: We will be persisting these objects on the java side,
+ * so in order to keep the JS GC from collecting our objects when they are
+ * away, we need to add them to the protect list. This should be refactored
+ * out in favor of better memory mgmt scheme.
+ */
+ gcProtectNullTolerant(wrapper);
+ env->SetIntArrayRegion(rval, 0, 1, (jint*)&wrapper);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_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 Java_com_google_gwt_dev_shell_mac_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);
+ /*
+ * TODO / LEAK / HACK: We will be persisting these objects on the java side,
+ * so in order to keep the JS GC from collecting our objects when they are
+ * away, we need to add them to the protect list. This should be refactored
+ * out in favor of better memory mgmt scheme.
+ */
+ gcProtectNullTolerant(wrapper);
+ env->SetIntArrayRegion(rval, 0, 1, (jint*)&wrapper);
+ if (env->ExceptionCheck())
+ return JNI_FALSE;
+
+ TRACE("SUCCESS Java_com_google_gwt_dev_shell_mac_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/gwt-webkit.h b/jni/mac/gwt-webkit.h
new file mode 100644
index 0000000..88db9f7
--- /dev/null
+++ b/jni/mac/gwt-webkit.h
@@ -0,0 +1,41 @@
+// Copyright 2005 Google Inc.
+// All Rights Reserved.
+
+#ifndef GWT_WEBKIT_H
+#define GWT_WEBKIT_H
+
+#include <jni.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 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
+
+#endif
diff --git a/jni/mac/prebuilt/libgwt-ll.jnilib b/jni/mac/prebuilt/libgwt-ll.jnilib
new file mode 100755
index 0000000..2d036c6
--- /dev/null
+++ b/jni/mac/prebuilt/libgwt-ll.jnilib
Binary files differ
diff --git a/jni/mac/prebuilt/libgwt-webkit.jnilib b/jni/mac/prebuilt/libgwt-webkit.jnilib
new file mode 100755
index 0000000..0fdd5b4
--- /dev/null
+++ b/jni/mac/prebuilt/libgwt-webkit.jnilib
Binary files differ
diff --git a/jni/windows/IE6.cpp b/jni/windows/IE6.cpp
new file mode 100644
index 0000000..0014768
--- /dev/null
+++ b/jni/windows/IE6.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2006 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.
+ */
+
+// A very slim and portable set of JNI methods for GWT.
+
+#include <jni.h>
+#include <windows.h>
+#include "wininet.h"
+
+// A home-brewed vector class to eliminate dependence on STL.
+// Reuse at your own peril, it hasn't been tested to do anything
+// more than we're actually using it for here.
+struct char_vector {
+ char_vector(long initSize=0): sz(0), cap(0), buf(0) {
+ resize(initSize);
+ }
+
+ ~char_vector() {
+ clear();
+ }
+
+ char& operator[](long i) {
+ return buf[i];
+ }
+
+ void append(const char* start, const char* end) {
+ long len = end - start;
+ long cursize = sz;
+ resize(sz + len);
+ memcpy(&buf[cursize], start, len);
+ }
+
+ void clear() {
+ if (buf)
+ free(buf);
+ buf = 0;
+ sz = cap = 0;
+ }
+
+ void reserve(long newcap) {
+ if (newcap <= cap)
+ return;
+ char* newbuf = (char*)malloc(newcap);
+ if (!newbuf)
+ return;
+ if (buf) {
+ memcpy(newbuf, buf, sz);
+ free(buf);
+ }
+ buf = newbuf;
+ cap = newcap;
+ }
+
+ void resize(long newsize) {
+ reserve(newsize);
+ sz = newsize;
+ }
+
+ long size() {
+ return sz;
+ }
+
+private:
+ long sz;
+ long cap;
+ char* buf;
+};
+
+// Does an HTTP GET on the specified URL using the WinInet subsystem, which respects proxy settings.
+// Returns a status code such that
+// 0 Success
+// < 0 Failure at some step (see the code below)
+// > 0 Windows system error code
+//
+int fetch(const char* userAgent, const char* url, char_vector& response) {
+ int status = -1;
+ HINTERNET h1 = InternetOpenA(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
+ if (h1 != NULL) {
+ status = -2;
+ DWORD flags = INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI;
+ HINTERNET h2 = InternetOpenUrlA(h1, url, "", -1L, flags, 0);
+ if (h2 != NULL) {
+ status = -3;
+ const int MAX_BUFFER = 1024 * 1024; // don't grow past this ever
+ bool notDone = true;
+ response.clear();
+ response.reserve(4096);
+ char_vector chunk(4096); // initial buffer size
+ while (notDone && chunk.size() < MAX_BUFFER) {
+ DWORD toRead = (DWORD)chunk.size();
+ DWORD didRead;
+ while (true) {
+ if (InternetReadFile(h2, (LPVOID)&chunk[0], toRead, &didRead)) {
+ if (didRead != 0) {
+ // Copy to response.
+ //
+ response.append(&chunk[0], &chunk[0] + didRead);
+
+ // Keep going.
+ //
+ } else {
+ // EOF.
+ //
+ status = 0;
+ notDone = false;
+ break;
+ }
+ } else {
+ // Oops -- why?
+ //
+ DWORD err = GetLastError();
+ if (err == ERROR_INSUFFICIENT_BUFFER) {
+ // Grow the buffer and retry.
+ //
+ chunk.resize(toRead * 2);
+ break;
+ } else {
+ // Give up.
+ //
+ status = err;
+ notDone = false;
+ break;
+ }
+ }
+ }
+ }
+ InternetCloseHandle(h2);
+ }
+ InternetCloseHandle(h1);
+ }
+ return status;
+}
+
+extern "C" {
+
+class UTFChars {
+public:
+ UTFChars(JNIEnv* env, jstring str): m_env(env), m_str(str) {
+ m_ptr = env->GetStringUTFChars(str, NULL);
+ }
+
+ ~UTFChars() {
+ if (m_ptr) {
+ m_env->ReleaseStringUTFChars(m_str, m_ptr);
+ }
+ }
+
+ operator const char*() const {
+ return m_ptr;
+ }
+
+ JNIEnv* m_env;
+ jstring m_str;
+ const char* m_ptr;
+};
+
+/*
+ * Class: com_google_gwt_dev_shell_ie_LowLevelIE6
+ * Method: _httpGet
+ * Signature: (Ljava/lang/String;Ljava/lang/String;[[B)I
+ */
+JNIEXPORT jint JNICALL Java_com_google_gwt_dev_shell_ie_LowLevelIE6__1httpGet(JNIEnv* env, jclass, jstring userAgent, jstring url, jobjectArray out) {
+ UTFChars userAgentChars(env, userAgent);
+ if (!userAgentChars || env->ExceptionCheck()) {
+ return -100;
+ }
+
+ UTFChars urlChars(env, url);
+ if (!urlChars || env->ExceptionCheck()) {
+ return -101;
+ }
+
+ // Do the fetch.
+ //
+ char_vector response;
+ int status = fetch(userAgentChars, urlChars, response);
+
+ if (status != 0) {
+ // Failure.
+ //
+ return status;
+ }
+
+ // Copy the response.
+ //
+ jbyteArray byteArray = env->NewByteArray(response.size());
+ if (!byteArray || env->ExceptionCheck()) {
+ return -102;
+ }
+
+ jbyte* bytes = env->GetByteArrayElements(byteArray, NULL);
+ if (!bytes || env->ExceptionCheck()) {
+ return -103;
+ }
+
+ memcpy(bytes, &response[0], response.size());
+
+ env->ReleaseByteArrayElements(byteArray, bytes, 0);
+
+ // May throw immediately after return if out array is bad.
+ //
+ env->SetObjectArrayElement(out, 0, byteArray);
+
+ return 0;
+}
+
+} // extern "C"
diff --git a/jni/windows/Makefile b/jni/windows/Makefile
new file mode 100644
index 0000000..b00624c
--- /dev/null
+++ b/jni/windows/Makefile
@@ -0,0 +1,107 @@
+# Copyright 2006 Google Inc. All Rights Reserved.
+#
+#-------------------------------------------------------------------------------
+# Macros
+#-------------------------------------------------------------------------------
+SHELL = /bin/sh
+
+##
+# Target settings
+##
+ROOTDIR = ./
+PROGNAME:= gwt-ll
+PROG := $(PROGNAME).dll
+PROGDIR := ./
+OBJDIR := $(PROGDIR)objs/
+OUT := $(PROGDIR)image/$(PROG)
+
+##
+# Tools
+##
+CXX := mingw-gcc
+AR := mingw-ar
+STRIP := mingw-strip
+LD := $(CXX)
+
+##
+# List of source, object, and dependency paths plus the path to them
+##
+SRCDIRS := ./:../gwt-ll-core/
+VPATH := .:../gwt-ll-core
+SRCS := gwt-ll.cpp IE6.cpp
+OBJS := $(addprefix $(OBJDIR),$(SRCS:.cpp=.o))
+DEPS := $(addprefix $(OBJDIR),$(SRCS:.cpp=.d))
+
+##
+# Include path configuration
+##
+SYSINCS := $(ROOTDIR)../../third_party/j2sdk1.4.2_09/include \
+ $(ROOTDIR)../../third_party/j2sdk1.4.2_09/include/win32
+INCS := $(addprefix -isystem ,$(SYSINCS))
+
+##
+# Libraries and library path
+##
+LIBS := wininet
+LIBPATH := -L$(OBJDIR)
+LIBS := $(addprefix -l,$(LIBS))
+
+# for notes on auto-dependency generation, see
+# http://make.paulandlesley.org/autodep.html
+# -MP obviates the need for sed hackery
+CFLAGS := -Os -fno-exceptions -fshort-wchar -c -MMD -MP -Wno-system-headers $(CFLAGS)
+LDFLAGS := -s -Wl,--kill-at $(LDFLAGS)
+
+##
+# Clean macros
+##
+CLEANDIRS := $(CLEANDIRS) $(OBJDIR)
+CLEANFILES := $(CLEANFILES) $(OUT)
+
+#-------------------------------------------------------------------------------
+# Rules
+#-------------------------------------------------------------------------------
+
+##
+# default rule
+##
+all: $(OBJDIR)libwininet.a $(OUT)
+
+##
+# Include the dependency rules
+##
+-include $(DEPS)
+
+##
+# Compilation rule for cpp files
+##
+$(OBJDIR)%.o : $(SRCDIR)%.cpp
+ @[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
+ $(CXX) $(CFLAGS) $(INCS) -o $@ $<
+
+##
+# Compilation rule for .def files to lib*.a files
+##
+$(OBJDIR)lib%.a : $(SRCDIR)%.def
+ @[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
+ mingw-dlltool -k -d $< -l $@
+
+##
+# Actual output file
+##
+$(OUT): $(OBJS)
+ @[ -d $(PROGDIR) ] || mkdir -p $(PROGDIR)
+ @[ -d $(PROGDIR)image ] || mkdir -p $(PROGDIR)image
+ $(LD) -shared $(LDFLAGS) $(LIBPATH) -o $@ $^ $(LIBS)
+ $(STRIP) --strip-unneeded $@
+
+##
+# Clean rule
+##
+clean: clean-wininet
+ @-rm -f $(CLEANFILES)
+ @-rm -rf $(CLEANDIRS)
+
+clean-wininet:
+ @-rm -f $(OBJDIR)libwininet.a
+
diff --git a/jni/windows/build.xml b/jni/windows/build.xml
new file mode 100755
index 0000000..9c65e9a
--- /dev/null
+++ b/jni/windows/build.xml
@@ -0,0 +1,20 @@
+<project name="jni-windows" default="all" basedir=".">
+ <property name="gwt.root" location="../.." />
+ <property name="project.tail" value="jni/windows" />
+ <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>
+
+ <target name="all" depends="build" description="Builds and packages this project" />
+</project>
diff --git a/jni/windows/gwt-ll.vcproj b/jni/windows/gwt-ll.vcproj
new file mode 100644
index 0000000..18fee56
--- /dev/null
+++ b/jni/windows/gwt-ll.vcproj
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="gwt-ll"
+ ProjectGUID="{AA853538-40A6-4413-A5B1-74031CB4E887}"
+ RootNamespace="gwt-ll"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="2"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""$(ProjectDir)..\..\..\..\..\third_party\j2sdk1.4.2_09\include";"$(ProjectDir)..\..\..\..\..\third_party\j2sdk1.4.2_09\include\win32""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL"
+ MinimalRebuild="TRUE"
+ ExceptionHandling="FALSE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ ForceConformanceInForLoopScope="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wininet.lib"
+ OutputFile="$(OutDir)\$(ProjectName).dll"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
+ SubSystem="2"
+ ImportLibrary="$(OutDir)/$(ProjectName).lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="2"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)..\..\..\..\..\third_party\j2sdk1.4.2_09\include";"$(ProjectDir)..\..\..\..\..\third_party\j2sdk1.4.2_09\include\win32""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL"
+ ExceptionHandling="FALSE"
+ RuntimeLibrary="0"
+ ForceConformanceInForLoopScope="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wininet.lib"
+ OutputFile="$(OutDir)\$(ProjectName).dll"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(OutDir)/$(ProjectName).lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\..\..\gwt-ll-core\src\main\cpp\gwt-ll.cpp">
+ </File>
+ <File
+ RelativePath=".\IE6.cpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/jni/windows/prebuilt/gwt-ll.dll b/jni/windows/prebuilt/gwt-ll.dll
new file mode 100755
index 0000000..49a0a1f
--- /dev/null
+++ b/jni/windows/prebuilt/gwt-ll.dll
Binary files differ
diff --git a/jni/windows/wininet.def b/jni/windows/wininet.def
new file mode 100644
index 0000000..83d6751
--- /dev/null
+++ b/jni/windows/wininet.def
@@ -0,0 +1,6 @@
+LIBRARY wininet.dll
+EXPORTS
+InternetOpenA@20 @264
+InternetOpenUrlA@24 @265
+InternetReadFile@16 @272
+InternetCloseHandle@4 @223
diff --git a/jni/windows/wininet.h b/jni/windows/wininet.h
new file mode 100644
index 0000000..935c615
--- /dev/null
+++ b/jni/windows/wininet.h
@@ -0,0 +1,20 @@
+#ifndef __wininet_h__
+#define __wininet_h__
+
+extern "C" {
+
+#define INTERNET_OPEN_TYPE_PRECONFIG 0
+#define INTERNET_FLAG_PRAGMA_NOCACHE 0x00000100
+#define INTERNET_FLAG_RELOAD 0x80000000
+#define INTERNET_FLAG_NO_COOKIES 0x00080000
+#define INTERNET_FLAG_NO_UI 0x00000200
+
+typedef void* HINTERNET;
+HINTERNET STDAPICALLTYPE InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType, LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags);
+HINTERNET STDAPICALLTYPE InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext);
+BOOL STDAPICALLTYPE InternetReadFile(HINTERNET hFile, void* lpBuffer, DWORD dwNumberOfBytesToRead, LPDWORD lpdwNumberOfBytesRead);
+BOOL STDAPICALLTYPE InternetCloseHandle(HINTERNET hInternet);
+
+}
+
+#endif // __wininet_h__