diff --git a/js/src/liveconnect/README.html b/js/src/liveconnect/README.html index ee1e9b51534..4bf28cb5bce 100644 --- a/js/src/liveconnect/README.html +++ b/js/src/liveconnect/README.html @@ -50,8 +50,7 @@ were integrated with Netscape Navigator versions 4.x and earlier.  For info on LiveConnect version 1, which was used in Navigator versions 3 and 4, and Enterprise Server 3, see Netscape's DevEdge site or any number of 3rd-party publications.) -

-LiveConnect version 3 (10/31/98)

+

LiveConnect version 3 (8/31/99)

diff --git a/js/src/liveconnect/jsj.c b/js/src/liveconnect/jsj.c index 45e2431e703..0ed147a7799 100644 --- a/js/src/liveconnect/jsj.c +++ b/js/src/liveconnect/jsj.c @@ -74,6 +74,7 @@ report_java_initialization_error(JNIEnv *jEnv, const char *js_error_msg) jclass jlObject; /* java.lang.Object */ jclass jlrMethod; /* java.lang.reflect.Method */ jclass jlrField; /* java.lang.reflect.Field */ +jclass jlrArray; /* java.lang.reflect.Array */ jclass jlVoid; /* java.lang.Void */ jclass jlrConstructor; /* java.lang.reflect.Constructor */ jclass jlThrowable; /* java.lang.Throwable */ @@ -106,6 +107,8 @@ jmethodID jlrField_getName; /* java.lang.reflect.Field.getName() */ jmethodID jlrField_getType; /* java.lang.reflect.Field.getType() */ jmethodID jlrField_getModifiers; /* java.lang.reflect.Field.getModifiers() */ +jmethodID jlrArray_newInstance; /* java.lang.reflect.Array.newInstance() */ + jmethodID jlBoolean_Boolean; /* java.lang.Boolean constructor */ jmethodID jlBoolean_booleanValue; /* java.lang.Boolean.booleanValue() */ jmethodID jlDouble_Double; /* java.lang.Double constructor */ @@ -229,6 +232,7 @@ init_java_VM_reflection(JSJavaVM *jsjava_vm, JNIEnv *jEnv) LOAD_CLASS(java/lang/reflect/Method, jlrMethod); LOAD_CLASS(java/lang/reflect/Constructor, jlrConstructor); LOAD_CLASS(java/lang/reflect/Field, jlrField); + LOAD_CLASS(java/lang/reflect/Array, jlrArray); LOAD_CLASS(java/lang/Throwable, jlThrowable); LOAD_CLASS(java/lang/System, jlSystem); LOAD_CLASS(java/lang/Boolean, jlBoolean); @@ -256,6 +260,9 @@ init_java_VM_reflection(JSJavaVM *jsjava_vm, JNIEnv *jEnv) LOAD_METHOD(java.lang.reflect.Field, getType, "()Ljava/lang/Class;", jlrField); LOAD_METHOD(java.lang.reflect.Field, getModifiers, "()I", jlrField); + LOAD_STATIC_METHOD(java.lang.reflect.Array, + newInstance, "(Ljava/lang/Class;I)Ljava/lang/Object;",jlrArray); + LOAD_METHOD(java.lang.Throwable, toString, "()Ljava/lang/String;", jlThrowable); LOAD_METHOD(java.lang.Throwable, getMessage, "()Ljava/lang/String;", jlThrowable); @@ -555,6 +562,7 @@ JSJ_DisconnectFromJavaVM(JSJavaVM *jsjava_vm) UNLOAD_CLASS(java/lang/reflect/Method, jlrMethod); UNLOAD_CLASS(java/lang/reflect/Constructor, jlrConstructor); UNLOAD_CLASS(java/lang/reflect/Field, jlrField); + UNLOAD_CLASS(java/lang/reflect/Array, jlrArray); UNLOAD_CLASS(java/lang/Throwable, jlThrowable); UNLOAD_CLASS(java/lang/System, jlSystem); UNLOAD_CLASS(java/lang/Boolean, jlBoolean); diff --git a/js/src/liveconnect/jsj_JSObject.c b/js/src/liveconnect/jsj_JSObject.c index 630b0093c3f..66f2a9c6b3f 100644 --- a/js/src/liveconnect/jsj_JSObject.c +++ b/js/src/liveconnect/jsj_JSObject.c @@ -838,7 +838,7 @@ Java_netscape_javascript_JSObject_getMember(JNIEnv *jEnv, property_name_ucs2 = NULL; if (!property_name_jstr) { JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NULL_MEMBER_NAME); + JSJMSG_NULL_MEMBER_NAME); member = NULL; goto done; } diff --git a/js/src/liveconnect/jsj_convert.c b/js/src/liveconnect/jsj_convert.c index 9b10d685e95..652e0f3bca4 100644 --- a/js/src/liveconnect/jsj_convert.c +++ b/js/src/liveconnect/jsj_convert.c @@ -76,6 +76,54 @@ convert_js_obj_to_JSObject_wrapper(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj return (*java_value != NULL); } +/* Copy an array from JS to Java; Create a new Java array and populate its + elements, one by one, with the result of converting each JS array element + to the type of the array component. */ +static JSBool +convert_js_array_to_java_array(JSContext *cx, JNIEnv *jEnv, JSObject *js_array, + JavaSignature *signature, + jobject *java_valuep) +{ + jsuint i; + jsval js_val; + jsuint length; + jclass component_class; + jarray java_array; + JavaSignature *array_component_signature; + + if (!JS_GetArrayLength(cx, js_array, &length)) + return JS_FALSE; + + /* Get the Java class of each element of the array */ + array_component_signature = signature->array_component_signature; + component_class = array_component_signature->java_class; + + /* Create a new empty Java array with the same length as the JS array */ + java_array = (*jEnv)->CallStaticObjectMethod(jEnv, jlrArray, jlrArray_newInstance, + component_class, length); + if (!java_array) { + jsj_ReportJavaError(cx, jEnv, "Error while constructing empty array of %s", + jsj_GetJavaClassName(cx, jEnv, component_class)); + return JS_FALSE; + } + + /* Convert each element of the JS array to an element of the Java array. + If an error occurs, there is no need to worry about releasing the + individual elements of the Java array - they will eventually be GC'ed + by the JVM. */ + for (i = 0; i < length; i++) { + if (!JS_LookupElement(cx, js_array, i, &js_val)) + return JS_FALSE; + + if (!jsj_SetJavaArrayElement(cx, jEnv, java_array, i, array_component_signature, js_val)) + return JS_FALSE; + } + + /* Return the result array */ + *java_valuep = java_array; + return JS_TRUE; +} + jstring jsj_ConvertJSStringToJavaString(JSContext *cx, JNIEnv *jEnv, JSString *js_str) { @@ -169,6 +217,15 @@ jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignatu return jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost, java_value, is_local_refp); + /* JS Arrays are converted, element by element, to Java arrays */ + } else if (JS_IsArrayObject(cx, js_obj) && (signature->type == JAVA_SIGNATURE_ARRAY)) { + if (convert_js_array_to_java_array(cx, jEnv, js_obj, signature, java_value)) { + if (java_value && *java_value) + *is_local_refp = JS_TRUE; + return JS_TRUE; + } + return JS_FALSE; + } else { /* Otherwise, see if the target type is the netscape.javascript.JSObject wrapper class or one of its subclasses, in which case a @@ -227,7 +284,9 @@ jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignatu /* Fall through, to attempt conversion to a java.lang.String ... */ } - /* If no other conversion is possible, see if the target type is java.lang.String */ + /* If the source JS type is either a string or undefined, or if no conversion + is possible from a number, boolean or JS object, see if the target type is + java.lang.String */ if ((*jEnv)->IsAssignableFrom(jEnv, jlString, target_java_class)) { /* Convert to JS string, if necessary, and then to a Java Unicode string */ @@ -503,6 +562,7 @@ conversion_error: if (java_value) { const char *jsval_string; + const char *class_name; JSString *jsstr; jsval_string = NULL; @@ -512,8 +572,11 @@ conversion_error: if (!jsval_string) jsval_string = ""; + class_name = jsj_ConvertJavaSignatureToHRString(cx, signature); JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_CANT_CONVERT_JS, jsval_string, signature->name); + JSJMSG_CANT_CONVERT_JS, jsval_string, + class_name); + return JS_FALSE; } return success; diff --git a/js/src/liveconnect/jsj_method.c b/js/src/liveconnect/jsj_method.c index e3d413c9131..25dfacced88 100644 --- a/js/src/liveconnect/jsj_method.c +++ b/js/src/liveconnect/jsj_method.c @@ -65,6 +65,7 @@ typedef enum JSJType { JSJTYPE_JAVACLASS, /* JavaClass */ JSJTYPE_JAVAOBJECT, /* JavaObject */ JSJTYPE_JAVAARRAY, /* JavaArray */ + JSJTYPE_JSARRAY, /* JS Array */ JSJTYPE_OBJECT, /* Any other JS Object, including functions */ JSJTYPE_LIMIT } JSJType; @@ -939,6 +940,8 @@ compute_jsj_type(JSContext *cx, jsval v) return JSJTYPE_JAVAARRAY; if (JS_InstanceOf(cx, js_obj, &JavaClass_class, 0)) return JSJTYPE_JAVACLASS; + if (JS_IsArrayObject(cx, js_obj)) + return JSJTYPE_JSARRAY; return JSJTYPE_OBJECT; } else if (JSVAL_IS_NUMBER(v)) { return JSJTYPE_NUMBER; @@ -978,7 +981,8 @@ static int rank_table[JSJTYPE_LIMIT][JAVA_SIGNATURE_LIMIT] = { {99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 1, 99, 2, 3, 4}, /* JavaClass */ {99, 7, 8, 6, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1}, /* JavaObject */ {99, 99, 99, 99, 99, 99, 99, 99, 0, 0, 99, 99, 99, 99, 0, 1}, /* JavaArray */ - {99, 9, 10, 8, 7, 6, 5, 4, 99, 99, 99, 99, 99, 1, 2, 3}, /* other JS object */ + {99, 99, 99, 99, 99, 99, 99, 99, 2, 99, 99, 99, 99, 1, 3, 4}, /* JS Array */ + {99, 9, 10, 8, 7, 6, 5, 4, 99, 99, 99, 99, 99, 1, 2, 3} /* other JS object */ }; /* diff --git a/js/src/liveconnect/jsj_private.h b/js/src/liveconnect/jsj_private.h index 2e74d02612a..3d1d9f58fc5 100644 --- a/js/src/liveconnect/jsj_private.h +++ b/js/src/liveconnect/jsj_private.h @@ -248,6 +248,7 @@ extern JSClass JavaMember_class; */ extern jclass jlObject; /* java.lang.Object */ extern jclass jlrConstructor; /* java.lang.reflect.Constructor */ +extern jclass jlrArray; /* java.lang.reflect.Array */ extern jclass jlThrowable; /* java.lang.Throwable */ extern jclass jlSystem; /* java.lang.System */ extern jclass jlClass; /* java.lang.Class */ @@ -278,6 +279,8 @@ extern jmethodID jlrField_getName; /* java.lang.reflect.Field.getNam extern jmethodID jlrField_getType; /* java.lang.reflect.Field.getType() */ extern jmethodID jlrField_getModifiers; /* java.lang.reflect.Field.getModifiers() */ +extern jmethodID jlrArray_newInstance; /* java.lang.reflect.Array.newInstance() */ + extern jmethodID jlThrowable_getMessage; /* java.lang.Throwable.getMessage() */ extern jmethodID jlThrowable_toString; /* java.lang.Throwable.toString() */