Fixed <rdar://problem/3887930> Must use new Java plug-in API to get/set fields so...
authorrjw <rjw@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Jan 2005 22:03:55 +0000 (22:03 +0000)
committerrjw <rjw@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Jan 2005 22:03:55 +0000 (22:03 +0000)
Use the new dispatching API to invoke JNI, rather than calling JNI
directly.

        Reviewed by David Harrison.

        * bindings/jni/jni_instance.cpp:
        (JavaInstance::invokeMethod):
        * bindings/jni/jni_runtime.cpp:
        (JavaField::dispatchValueFromInstance):
        (JavaField::valueFromInstance):
        (JavaField::dispatchSetValueToInstance):
        (JavaField::setValueToInstance):
        * bindings/jni/jni_runtime.h:
        * bindings/jni/jni_utility.cpp:
        (KJS::Bindings::convertValueToJValue):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8344 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/bindings/jni/jni_instance.cpp
JavaScriptCore/bindings/jni/jni_runtime.cpp
JavaScriptCore/bindings/jni/jni_runtime.h
JavaScriptCore/bindings/jni/jni_utility.cpp

index 777c1bb0f4193fd71f0297c1d8ba642540d16bea..4fe1a82d5ab08ba92496e05220385c77613c0f1e 100644 (file)
@@ -1,3 +1,23 @@
+2005-01-11  Richard Williamson   <rjw@apple.com>
+
+       Fixed <rdar://problem/3887930> Must use new Java plug-in API to get/set fields so exception handling works (fixes many LiveConnect crashes)
+
+       Use the new dispatching API to invoke JNI, rather than calling JNI
+       directly.
+
+        Reviewed by David Harrison.
+
+        * bindings/jni/jni_instance.cpp:
+        (JavaInstance::invokeMethod):
+        * bindings/jni/jni_runtime.cpp:
+        (JavaField::dispatchValueFromInstance):
+        (JavaField::valueFromInstance):
+        (JavaField::dispatchSetValueToInstance):
+        (JavaField::setValueToInstance):
+        * bindings/jni/jni_runtime.h:
+        * bindings/jni/jni_utility.cpp:
+        (KJS::Bindings::convertValueToJValue):
+
 === Safari-178 ===
 
 === Safari-177 ===
index 54e3295cb5d1f49f0a617b2e415c55522a51c1a3..acbbe0cfcb9694ec5c3ee3d66b15f0383a23db42 100644 (file)
@@ -146,6 +146,7 @@ Value JavaInstance::invokeMethod (KJS::ExecState *exec, const MethodList &method
     for (i = 0; i < count; i++) {
         JavaParameter *aParameter = static_cast<JavaParameter *>(jMethod->parameterAt(i));
         jArgs[i] = convertValueToJValue (exec, args.at(i), aParameter->getJNIType(), aParameter->type());
+       JS_LOG("arg[%d] = %s\n", i, args.at(i).toString(exec).ascii());
     }
         
 
index 0b95f9b8fe65467504f851d15c56114b5d3f3add..c49f10360b1b53ba78c9f5e18ba24c05f0790365 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <runtime_array.h>
 #include <runtime_object.h>
+#include <runtime_root.h>
 
 using namespace KJS;
 using namespace KJS::Bindings;
@@ -65,15 +66,44 @@ KJS::Value JavaArray::convertJObjectToArray (KJS::ExecState *exec, jobject anObj
     return KJS::Object(new RuntimeArrayImp(exec, new JavaArray ((jobject)anObject, type, r)));
 }
 
-KJS::Value JavaField::valueFromInstance(KJS::ExecState *exec, const Instance *i) const 
+jvalue JavaField::dispatchValueFromInstance(KJS::ExecState *exec, const JavaInstance *instance, const char *name, const char *sig, JNIType returnType) const
 {
-    const JavaInstance *instance = static_cast<const JavaInstance *>(i);
     jobject jinstance = instance->javaInstance();
     jobject fieldJInstance = _field->javaInstance();
+    JNIEnv *env = getJNIEnv();
+    jvalue result;
+
+    bzero (&result, sizeof(jvalue));
+    jclass cls = env->GetObjectClass(fieldJInstance);
+    if ( cls != NULL ) {
+       jmethodID mid = env->GetMethodID(cls, name, sig);
+       if ( mid != NULL )
+       {
+           const RootObject *execContext = instance->executionContext();
+           if (execContext && execContext->nativeHandle()) {
+               Value exceptionDescription;
+               jvalue args[1];
+               
+               args[0].l = jinstance;
+               dispatchJNICall (execContext->nativeHandle(), fieldJInstance, false, returnType, mid, args, result, 0, exceptionDescription);
+               if (!exceptionDescription.isNull()) {
+                   Object error = Error::create(exec, GeneralError, exceptionDescription.toString(exec).UTF8String().c_str());
+                   exec->setException(error);
+               }
+           }
+       }
+    }
+    return result;
+}
+
+KJS::Value JavaField::valueFromInstance(KJS::ExecState *exec, const Instance *i) const 
+{
+    const JavaInstance *instance = static_cast<const JavaInstance *>(i);
 
     switch (_JNIType) {
         case object_type: {
-            jobject anObject = callJNIObjectMethod(_field->javaInstance(), "get", "(Ljava/lang/Object;)Ljava/lang/Object;", jinstance);
+           jvalue result = dispatchValueFromInstance (exec, instance, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", object_type);
+           jobject anObject = result.l;
 
             const char *arrayType = type();
             if (arrayType[0] == '[') {
@@ -86,7 +116,8 @@ KJS::Value JavaField::valueFromInstance(KJS::ExecState *exec, const Instance *i)
         break;
             
         case boolean_type: {
-            jboolean value = callJNIBooleanMethod(fieldJInstance, "getBoolean", "(Ljava/lang/Object;)Z", jinstance);
+           jvalue result = dispatchValueFromInstance (exec, instance, "getBoolean", "(Ljava/lang/Object;)Z", boolean_type);
+           jboolean value = result.z;
             return KJS::Boolean((bool)value);
         }
         break;
@@ -97,14 +128,16 @@ KJS::Value JavaField::valueFromInstance(KJS::ExecState *exec, const Instance *i)
         
         case int_type:
             jint value;
-            value = callJNIIntMethod(fieldJInstance, "getInt", "(Ljava/lang/Object;)I", jinstance);
+           jvalue result = dispatchValueFromInstance (exec, instance, "getInt", "(Ljava/lang/Object;)I", int_type);
+           value = result.i;
             return Number((int)value);
 
         case long_type:
         case float_type:
         case double_type: {
             jdouble value;
-            value = callJNIDoubleMethod(fieldJInstance, "getDouble", "(Ljava/lang/Object;)D", jinstance);
+           jvalue result = dispatchValueFromInstance (exec, instance, "getDouble", "(Ljava/lang/Object;)D", double_type);
+           value = result.i;
             return Number((double)value);
         }
         break;
@@ -114,56 +147,83 @@ KJS::Value JavaField::valueFromInstance(KJS::ExecState *exec, const Instance *i)
     return Undefined();
 }
 
-void JavaField::setValueToInstance(KJS::ExecState *exec, const Instance *i, const KJS::Value &aValue) const
+void JavaField::dispatchSetValueToInstance(KJS::ExecState *exec, const JavaInstance *instance, jvalue javaValue, const char *name, const char *sig) const
 {
-    const JavaInstance *instance = static_cast<const JavaInstance *>(i);
     jobject jinstance = instance->javaInstance();
     jobject fieldJInstance = _field->javaInstance();
+    JNIEnv *env = getJNIEnv();
+
+    jclass cls = env->GetObjectClass(fieldJInstance);
+    if ( cls != NULL ) {
+       jmethodID mid = env->GetMethodID(cls, name, sig);
+       if ( mid != NULL )
+       {
+           const RootObject *execContext = instance->executionContext();
+           if (execContext && execContext->nativeHandle()) {
+               Value exceptionDescription;
+               jvalue args[2];
+               jvalue result;
+               
+               args[0].l = jinstance;
+               args[1] = javaValue;
+               dispatchJNICall (execContext->nativeHandle(), fieldJInstance, false, void_type, mid, args, result, 0, exceptionDescription);
+               if (!exceptionDescription.isNull()) {
+                   Object error = Error::create(exec, GeneralError, exceptionDescription.toString(exec).UTF8String().c_str());
+                   exec->setException(error);
+               }
+           }
+       }
+    }
+}
+
+void JavaField::setValueToInstance(KJS::ExecState *exec, const Instance *i, const KJS::Value &aValue) const
+{
+    const JavaInstance *instance = static_cast<const JavaInstance *>(i);
     jvalue javaValue = convertValueToJValue (exec, aValue, _JNIType, type());
 
     switch (_JNIType) {
         case object_type: {
-            callJNIVoidMethod(fieldJInstance, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", jinstance, javaValue.l);
+           dispatchSetValueToInstance (exec, instance, javaValue, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V");
         }
         break;
             
         case boolean_type: {
-            callJNIVoidMethod(fieldJInstance, "setBoolean", "(Ljava/lang/Object;Z)V", jinstance, javaValue.z);
+           dispatchSetValueToInstance (exec, instance, javaValue, "setBoolean", "(Ljava/lang/Object;Z)V");
         }
         break;
             
         case byte_type: {
-            callJNIVoidMethod(fieldJInstance, "setByte", "(Ljava/lang/Object;B)V", jinstance, javaValue.b);
+           dispatchSetValueToInstance (exec, instance, javaValue, "setByte", "(Ljava/lang/Object;B)V");
         }
         break;
 
         case char_type: {
-            callJNIVoidMethod(fieldJInstance, "setChar", "(Ljava/lang/Object;C)V", jinstance, javaValue.c);
+           dispatchSetValueToInstance (exec, instance, javaValue, "setChar", "(Ljava/lang/Object;C)V");
         }
         break;
 
         case short_type: {
-            callJNIVoidMethod(fieldJInstance, "setShort", "(Ljava/lang/Object;S)V", jinstance, javaValue.s);
+           dispatchSetValueToInstance (exec, instance, javaValue, "setShort", "(Ljava/lang/Object;S)V");
         }
         break;
 
         case int_type: {
-            callJNIVoidMethod(fieldJInstance, "setInt", "(Ljava/lang/Object;I)V", jinstance, javaValue.i);
+           dispatchSetValueToInstance (exec, instance, javaValue, "setInt", "(Ljava/lang/Object;I)V");
         }
         break;
 
         case long_type: {
-            callJNIVoidMethod(fieldJInstance, "setLong", "(Ljava/lang/Object;J)V", jinstance, javaValue.j);
+           dispatchSetValueToInstance (exec, instance, javaValue, "setLong", "(Ljava/lang/Object;J)V");
         }
         break;
 
         case float_type: {
-            callJNIVoidMethod(fieldJInstance, "setFloat", "(Ljava/lang/Object;F)V", jinstance, javaValue.f);
+           dispatchSetValueToInstance (exec, instance, javaValue, "setFloat", "(Ljava/lang/Object;F)V");
         }
         break;
 
         case double_type: {
-            callJNIVoidMethod(fieldJInstance, "setDouble", "(Ljava/lang/Object;D)V", jinstance, javaValue.d);
+           dispatchSetValueToInstance (exec, instance, javaValue, "setDouble", "(Ljava/lang/Object;D)V");
         }
         break;
         default:
index 181fa68a07be51e3409094f9421c73c0c7572e60..c9c7ddcace29ad2200141506059113dc0be5c625 100644 (file)
@@ -191,6 +191,9 @@ public:
     JNIType getJNIType() const { return _JNIType; }
     
 private:
+    void JavaField::dispatchSetValueToInstance(KJS::ExecState *exec, const JavaInstance *instance, jvalue javaValue, const char *name, const char *sig) const;
+    jvalue JavaField::dispatchValueFromInstance(KJS::ExecState *exec, const JavaInstance *instance, const char *name, const char *sig, JNIType returnType) const;
+
     JavaString _name;
     JavaString _type;
     JNIType _JNIType;
index 3f1adf791d137eb4599608201c39d835cc2c4cfc..53eaf0b89ff2e64beb6a52185fb9b14d6c4daa42 100644 (file)
@@ -724,11 +724,24 @@ jvalue KJS::Bindings::convertValueToJValue (KJS::ExecState *exec, KJS::Value val
             
             // Now convert value to a string if the target type is a java.lang.string, and we're not
             // converting from a Null.
-            if (result.l == 0 && strcmp(javaClassName, "java.lang.String") == 0 && value.type() != KJS::NullType) {
-                KJS::UString stringValue = value.toString(exec);
-                JNIEnv *env = getJNIEnv();
-                jobject javaString = env->functions->NewString (env, (const jchar *)stringValue.data(), stringValue.size());
-                result.l = javaString;
+            if (result.l == 0 && strcmp(javaClassName, "java.lang.String") == 0) {
+#if CONVERT_NULL_TO_EMPTY_STRING
+               if (value.type() == KJS::NullType) {
+                   JNIEnv *env = getJNIEnv();
+                   jchar buf[2];
+                   jobject javaString = env->functions->NewString (env, buf, 0);
+                   result.l = javaString;
+               }
+               else 
+#else
+               if (value.type() != KJS::NullType)
+#endif
+               {
+                   KJS::UString stringValue = value.toString(exec);
+                   JNIEnv *env = getJNIEnv();
+                   jobject javaString = env->functions->NewString (env, (const jchar *)stringValue.data(), stringValue.size());
+                   result.l = javaString;
+               }
             }
         }
         break;