/* * Class: netscape_javascript_JSObject * Method: getSlot * Signature: (I)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getSlot(JNIEnv *jEnv, jobject java_wrapper_obj, jint slot) { JSContext *cx = NULL; JSObject *js_obj; jsval js_val; int dummy_cost; JSBool dummy_bool; JSErrorReporter saved_reporter; jobject member; JSJavaThreadState *jsj_env; jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); if (!jsj_env) return NULL; if (!JS_GetElement(cx, js_obj, slot, &js_val)) goto done; if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &member, &dummy_bool)) goto done; done: if (!jsj_exit_js(cx, jsj_env, saved_reporter)) return NULL; return member; }
/* * Class: netscape_javascript_JSObject * Method: getMember * Signature: (Ljava/lang/String;)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getMember(JNIEnv *jEnv, jobject java_wrapper_obj, jstring property_name_jstr) { JSContext *cx = NULL; JSObject *js_obj; jsval js_val; int dummy_cost; JSBool dummy_bool; const jchar *property_name_ucs2; jsize property_name_len; JSErrorReporter saved_reporter; jobject member; jboolean is_copy; JSJavaThreadState *jsj_env; jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); if (!jsj_env) return NULL; property_name_ucs2 = NULL; if (!property_name_jstr) { JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_NULL_MEMBER_NAME); member = NULL; goto done; } /* Get the Unicode string for the JS property name */ property_name_ucs2 = (*jEnv)->GetStringChars(jEnv, property_name_jstr, &is_copy); if (!property_name_ucs2) { JS_ASSERT(0); goto done; } property_name_len = (*jEnv)->GetStringLength(jEnv, property_name_jstr); if (!JS_GetUCProperty(cx, js_obj, property_name_ucs2, property_name_len, &js_val)) goto done; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &member, &dummy_bool); done: if (property_name_ucs2) (*jEnv)->ReleaseStringChars(jEnv, property_name_jstr, property_name_ucs2); if (!jsj_exit_js(cx, jsj_env, saved_reporter)) return NULL; return member; }
/** * get member of a Native JSObject for a given index. * * @param jEnv - JNIEnv on which the call is being made. * @param obj - A Native JS Object. * @param index - Index of a member. * @param pjobj - return parameter as a java object representing * the member. */ NS_METHOD nsCLiveconnect::GetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, void* principalsArray[], int numPrincipals, nsISupports *securitySupports, jobject *pjobj) { if(jEnv == NULL || obj == 0) { return NS_ERROR_FAILURE; } JSJavaThreadState *jsj_env = NULL; JSObjectHandle *handle = (JSObjectHandle*)obj; JSObject *js_obj = handle->js_obj; JSContext *cx = NULL; jobject member = NULL; jsval js_val; int dummy_cost = 0; JSBool dummy_bool = PR_FALSE; JSErrorReporter saved_state = NULL; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; // =-= sudu: check to see if slot can be passed in as is. // Should it be converted to a jsint? if (!JS_GetElement(cx, js_obj, slot, &js_val)) goto done; if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &member, &dummy_bool)) goto done; done: if (!jsj_exit_js(cx, jsj_env, saved_state)) return NS_ERROR_FAILURE; *pjobj = member; return NS_OK; }
/* * Class: netscape_javascript_JSObject * Method: getWindow * Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject; */ JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getWindow(JNIEnv *jEnv, jclass js_object_class, jobject java_applet_obj) { char *err_msg; JSContext *cx = NULL; JSObject *js_obj = NULL; jsval js_val; int dummy_cost; JSBool dummy_bool; JSErrorReporter saved_reporter; jobject java_obj; JSJavaThreadState *jsj_env; jsj_env = jsj_enter_js(jEnv, java_applet_obj, NULL, &cx, NULL, &saved_reporter, NULL, 0, NULL); if (!jsj_env) return NULL; err_msg = NULL; java_obj = NULL; if (JSJ_callbacks && JSJ_callbacks->map_java_object_to_js_object) js_obj = JSJ_callbacks->map_java_object_to_js_object(jEnv, java_applet_obj, &err_msg); if (!js_obj) { if (err_msg) { JS_ReportError(cx, err_msg); free(err_msg); } goto done; } js_val = OBJECT_TO_JSVAL(js_obj); jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &java_obj, &dummy_bool); done: if (!jsj_exit_js(cx, jsj_env, saved_reporter)) return NULL; return java_obj; }
/* * Convert a JS value to a Java value of the given type signature. The cost * variable is incremented if coercion is required, e.g. the source value is * a string, but the target type is a boolean. * * Returns JS_FALSE if no conversion is possible, either because the jsval has * a type that is wholly incompatible with the Java value, or because a scalar * jsval can't be represented in a variable of the target type without loss of * precision, e.g. the source value is "4.2" but the destination type is byte. * If conversion is not possible and java_value is non-NULL, the JS error * reporter is called with an appropriate message. */ JSBool jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v_arg, JavaSignature *signature, int *cost, jvalue *java_value, JSBool *is_local_refp) { JavaSignatureChar type; jsval v; JSBool success = JS_FALSE; /* Initialize to default case, in which no new Java object is synthesized to perform the conversion and, therefore, no JNI local references are being held. */ *is_local_refp = JS_FALSE; type = signature->type; v = v_arg; switch (type) { case JAVA_SIGNATURE_BOOLEAN: if (!JSVAL_IS_BOOLEAN(v)) { if (!JS_ConvertValue(cx, v, JSTYPE_BOOLEAN, &v)) goto conversion_error; if (JSVAL_IS_VOID(v)) goto conversion_error; (*cost)++; } if (java_value) java_value->z = (jboolean)(JSVAL_TO_BOOLEAN(v) == JS_TRUE); break; case JAVA_SIGNATURE_SHORT: JSVAL_TO_INTEGRAL_JVALUE(short, s, jshort, v, java_value); break; case JAVA_SIGNATURE_BYTE: JSVAL_TO_INTEGRAL_JVALUE(byte, b, jbyte, v, java_value); break; case JAVA_SIGNATURE_CHAR: /* A one-character string can be converted into a character */ if (JSVAL_IS_STRING(v) && (JS_GetStringLength(JSVAL_TO_STRING(v)) == 1)) { v = INT_TO_JSVAL(*JS_GetStringChars(JSVAL_TO_STRING(v))); } JSVAL_TO_INTEGRAL_JVALUE(char, c, jchar, v, java_value); break; case JAVA_SIGNATURE_INT: JSVAL_TO_INTEGRAL_JVALUE(int, i, jint, v, java_value); break; case JAVA_SIGNATURE_LONG: #if defined(XP_MAC) || (defined(XP_OS2) && !defined(HAVE_LONG_LONG)) JSVAL_TO_JLONG_JVALUE(j, jlong, v, java_value); #else JSVAL_TO_INTEGRAL_JVALUE(long, j, jlong, v, java_value); #endif break; case JAVA_SIGNATURE_FLOAT: if (!JSVAL_IS_NUMBER(v)) { if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) goto conversion_error; (*cost)++; } if (java_value) { if (JSVAL_IS_INT(v)) java_value->f = (jfloat) JSVAL_TO_INT(v); else java_value->f = (jfloat) *JSVAL_TO_DOUBLE(v); } break; case JAVA_SIGNATURE_DOUBLE: if (!JSVAL_IS_NUMBER(v)) { if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) goto conversion_error; (*cost)++; } if (java_value) { if (JSVAL_IS_INT(v)) java_value->d = (jdouble) JSVAL_TO_INT(v); else java_value->d = (jdouble) *JSVAL_TO_DOUBLE(v); } break; /* Non-primitive (reference) type */ default: JS_ASSERT(IS_REFERENCE_TYPE(type)); if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost, &java_value->l, is_local_refp)) goto conversion_error; break; case JAVA_SIGNATURE_UNKNOWN: case JAVA_SIGNATURE_VOID: JS_ASSERT(0); return JS_FALSE; } /* Success */ return JS_TRUE; numeric_conversion_error: success = JS_TRUE; /* Fall through ... */ conversion_error: if (java_value) { const char *jsval_string; const char *class_name; JSString *jsstr; jsval_string = NULL; jsstr = JS_ValueToString(cx, v_arg); if (jsstr) jsval_string = JS_GetStringBytes(jsstr); if (!jsval_string) jsval_string = ""; class_name = jsj_ConvertJavaSignatureToHRString(cx, signature); JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_CANT_CONVERT_JS, jsval_string, class_name); return JS_FALSE; } return success; }
/* * Convert a JS value to an instance of java.lang.Object or one of its subclasses, * performing any necessary type coercion. If non-trivial coercion is required, * the cost value is incremented. If the java_value pass-by-reference argument * is non-NULL, the resulting Java value is stored there. * * Returns JS_TRUE if the conversion is possible, JS_FALSE otherwise */ JSBool jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature, int *cost, jobject *java_value, JSBool *is_local_refp) { JSString *jsstr; jclass target_java_class; JS_ASSERT(IS_REFERENCE_TYPE(signature->type)); /* Initialize to default case, in which no new Java object is synthesized to perform the conversion and, therefore, no JNI local references are being held. */ *is_local_refp = JS_FALSE; /* Get the Java type of the target value */ target_java_class = signature->java_class; if (JSVAL_IS_OBJECT(v)) { JSObject *js_obj = JSVAL_TO_OBJECT(v); /* JS null is always assignable to a Java object */ if (!js_obj) { if (java_value) *java_value = NULL; return JS_TRUE; } if (JS_InstanceOf(cx, js_obj, &JavaObject_class, 0) || JS_InstanceOf(cx, js_obj, &JavaArray_class, 0)) { /* The source value is a Java object wrapped inside a JavaScript object. Unwrap the JS object and return the original Java object if it's class makes it assignment-compatible with the target class using Java's assignability rules. */ JavaObjectWrapper *java_wrapper = JS_GetPrivate(cx, js_obj); jobject java_obj = java_wrapper->java_obj; if ((*jEnv)->IsInstanceOf(jEnv, java_obj, target_java_class)) { if (java_value) *java_value = java_obj; return JS_TRUE; } /* Fall through, to attempt conversion to a Java string */ } else if (JS_InstanceOf(cx, js_obj, &JavaClass_class, 0)) { /* We're dealing with the reflection of a Java class */ JavaClassDescriptor *java_class_descriptor = JS_GetPrivate(cx, js_obj); /* Check if target type is java.lang.Class class */ if ((*jEnv)->IsAssignableFrom(jEnv, jlClass, target_java_class)) { if (java_value) *java_value = java_class_descriptor->java_class; return JS_TRUE; } /* Check if target type is netscape.javascript.JSObject wrapper class */ if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) { if (java_value && *java_value) *is_local_refp = JS_TRUE; return JS_TRUE; } /* Fall through, to attempt conversion to a Java string */ } else if (JS_InstanceOf(cx, js_obj, &JavaMember_class, 0)) { if (!JS_ConvertValue(cx, v, JSTYPE_OBJECT, &v)) return JS_FALSE; 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 reference is passed to the original JS object by wrapping it inside an instance of netscape.javascript.JSObject */ if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) { if (java_value && *java_value) *is_local_refp = JS_TRUE; return JS_TRUE; } /* Fall through, to attempt conversion to a Java string */ } } else if (JSVAL_IS_NUMBER(v)) { /* JS numbers, integral or not, can be converted to instances of java.lang.Double */ if ((*jEnv)->IsAssignableFrom(jEnv, jlDouble, target_java_class)) { if (java_value) { jsdouble d; if (!JS_ValueToNumber(cx, v, &d)) goto conversion_error; *java_value = (*jEnv)->NewObject(jEnv, jlDouble, jlDouble_Double, d); if (*java_value) { *is_local_refp = JS_TRUE; } else { jsj_UnexpectedJavaError(cx, jEnv, "Couldn't construct instance of java.lang.Double"); return JS_FALSE; } } return JS_TRUE; } /* Fall through, to attempt conversion to a java.lang.String ... */ } else if (JSVAL_IS_BOOLEAN(v)) { /* JS boolean values can be converted to instances of java.lang.Boolean */ if ((*jEnv)->IsAssignableFrom(jEnv, jlBoolean, target_java_class)) { if (java_value) { JSBool b; if (!JS_ValueToBoolean(cx, v, &b)) goto conversion_error; *java_value = (*jEnv)->NewObject(jEnv, jlBoolean, jlBoolean_Boolean, b); if (*java_value) { *is_local_refp = JS_TRUE; } else { jsj_UnexpectedJavaError(cx, jEnv, "Couldn't construct instance " "of java.lang.Boolean"); return JS_FALSE; } } return JS_TRUE; } /* Fall through, to attempt conversion to a 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 */ jsstr = JS_ValueToString(cx, v); if (jsstr) { if (java_value) { *java_value = jsj_ConvertJSStringToJavaString(cx, jEnv, jsstr); if (*java_value) { *is_local_refp = JS_TRUE; } else { return JS_FALSE; } } return JS_TRUE; } } conversion_error: return JS_FALSE; }
/* * This is called upon returning from JS back into Java. Any JS errors * reported during that time will be converted into Java exceptions. It's * possible that a JS error was actually triggered by Java at some point, in * which case the original Java exception is thrown. */ static void throw_any_pending_js_error_as_a_java_exception(JSJavaThreadState *jsj_env) { CapturedJSError *error; JNIEnv *jEnv; jstring message_jstr, linebuf_jstr, filename_jstr; jint index, lineno; JSErrorReport *report; JSContext *cx; jsval pending_exception; jobject java_obj; int dummy_cost; JSBool is_local_refp; JSType primitive_type; jthrowable java_exception; message_jstr = linebuf_jstr = filename_jstr = java_exception = NULL; /* Get the Java JNI environment */ jEnv = jsj_env->jEnv; cx = jsj_env->cx; /* Get the pending JS exception if it exists */ if (cx&&JS_IsExceptionPending(cx)) { if (!JS_GetPendingException(cx, &pending_exception)) goto out_of_memory; /* Find out the JSTYPE of this jsval. */ primitive_type = JS_TypeOfValue(cx, pending_exception); /* Convert jsval exception to a java object and then use it to create an instance of JSException. */ if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, pending_exception, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &java_obj, &is_local_refp)) goto done; java_exception = (*jEnv)->NewObject(jEnv, njJSException, njJSException_JSException_wrap, primitive_type, java_obj); if (is_local_refp) (*jEnv)->DeleteLocalRef(jEnv, java_obj); if (!java_exception) goto out_of_memory; /* Throw the newly-created JSException */ if ((*jEnv)->Throw(jEnv, java_exception) < 0) { JS_ASSERT(0); jsj_LogError("Couldn't throw JSException\n"); goto done; } JS_ClearPendingException(cx); return; } if (!jsj_env->pending_js_errors) { #ifdef DEBUG /* Any exception should be cleared as soon as it's detected, so there shouldn't be any pending. */ if ((*jEnv)->ExceptionOccurred(jEnv)) { /* A Java exception occurred, but nobody in JS-land noticed. */ JS_ASSERT(0); (*jEnv)->ExceptionClear(jEnv); } #endif return; } /* Get the deepest (oldest) saved JS error */ /* XXX - What's the right thing to do about newer errors ? For now we just throw them away */ error = jsj_env->pending_js_errors; while (error->next) error = error->next; /* * If the JS error was originally the result of a Java exception, rethrow * the original exception. */ if (error->java_exception) { (*jEnv)->Throw(jEnv, error->java_exception); goto done; } /* Propagate any JS errors that did not originate as Java exceptions into Java as an instance of netscape.javascript.JSException */ /* First, marshall the arguments to the JSException constructor */ message_jstr = NULL; if (error->message) { message_jstr = (*jEnv)->NewStringUTF(jEnv, error->message); if (!message_jstr) goto out_of_memory; } report = &error->report; filename_jstr = NULL; if (report->filename) { filename_jstr = (*jEnv)->NewStringUTF(jEnv, report->filename); if (!filename_jstr) goto out_of_memory; } linebuf_jstr = NULL; if (report->linebuf) { linebuf_jstr = (*jEnv)->NewStringUTF(jEnv, report->linebuf); if (!linebuf_jstr) goto out_of_memory; } lineno = report->lineno; index = report->linebuf ? report->tokenptr - report->linebuf : 0; /* Call the JSException constructor */ java_exception = (*jEnv)->NewObject(jEnv, njJSException, njJSException_JSException, message_jstr, filename_jstr, lineno, linebuf_jstr, index); if (!java_exception) goto out_of_memory; /* Throw the newly-created JSException */ if ((*jEnv)->Throw(jEnv, java_exception) < 0) { JS_ASSERT(0); jsj_UnexpectedJavaError(cx, jEnv, "Couldn't throw JSException\n"); } goto done; out_of_memory: /* No recovery possible */ JS_ASSERT(0); jsj_LogError("Out of memory while attempting to throw JSException\n"); done: jsj_ClearPendingJSErrors(jsj_env); /* * Release local references to Java objects, since some JVMs seem reticent * about collecting them otherwise. */ if (message_jstr) (*jEnv)->DeleteLocalRef(jEnv, message_jstr); if (filename_jstr) (*jEnv)->DeleteLocalRef(jEnv, filename_jstr); if (linebuf_jstr) (*jEnv)->DeleteLocalRef(jEnv, linebuf_jstr); if (java_exception) (*jEnv)->DeleteLocalRef(jEnv, java_exception); }
/* * Class: netscape_javascript_JSObject * Method: eval * Signature: (Ljava/lang/String;)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_eval(JNIEnv *jEnv, jobject java_wrapper_obj, jstring eval_jstr) { const char *codebase; JSPrincipals *principals; JSContext *cx = NULL; JSBool eval_succeeded; JSObject *js_obj; jsval js_val; int dummy_cost; JSBool dummy_bool; const jchar *eval_ucs2; jsize eval_len; JSErrorReporter saved_reporter; jboolean is_copy; jobject result; JSJavaThreadState *jsj_env; jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); if (!jsj_env) return NULL; result = NULL; eval_ucs2 = NULL; if (!eval_jstr) { JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_NULL_EVAL_ARG); goto done; } /* Get the string to eval as raw Unicode characters */ eval_ucs2 = (*jEnv)->GetStringChars(jEnv, eval_jstr, &is_copy); if (!eval_ucs2) { JS_ASSERT(0); goto done; } eval_len = (*jEnv)->GetStringLength(jEnv, eval_jstr); /* Set up security stuff */ principals = NULL; if (JSJ_callbacks && JSJ_callbacks->get_JSPrincipals_from_java_caller) principals = JSJ_callbacks->get_JSPrincipals_from_java_caller(jEnv, cx, NULL, 0, NULL); codebase = principals ? principals->codebase : NULL; /* Have the JS engine evaluate the unicode string */ eval_succeeded = JS_EvaluateUCScriptForPrincipals(cx, js_obj, principals, eval_ucs2, eval_len, codebase, 0, &js_val); if (!eval_succeeded) goto done; /* Convert result to a subclass of java.lang.Object */ jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &result, &dummy_bool); done: if (eval_ucs2) (*jEnv)->ReleaseStringChars(jEnv, eval_jstr, eval_ucs2); if (!jsj_exit_js(cx, jsj_env, saved_reporter)) return NULL; return result; }
/* * Class: netscape_javascript_JSObject * Method: call * Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_call(JNIEnv *jEnv, jobject java_wrapper_obj, jstring function_name_jstr, jobjectArray java_args) { int i, argc, arg_num; jsval *argv; JSContext *cx = NULL; JSObject *js_obj; jsval js_val, function_val; int dummy_cost; JSBool dummy_bool; const jchar *function_name_ucs2; jsize function_name_len; JSErrorReporter saved_reporter; jboolean is_copy; jobject result; JSJavaThreadState *jsj_env; jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); if (!jsj_env) return NULL; function_name_ucs2 = NULL; result = NULL; if (!function_name_jstr) { JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_NULL_FUNCTION_NAME); goto done; } /* Get the function name to eval as raw Unicode characters */ function_name_ucs2 = (*jEnv)->GetStringChars(jEnv, function_name_jstr, &is_copy); if (!function_name_ucs2) { JS_ASSERT(0); goto done; } function_name_len = (*jEnv)->GetStringLength(jEnv, function_name_jstr); /* Allocate space for JS arguments */ if (java_args) { argc = (*jEnv)->GetArrayLength(jEnv, java_args); argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval)); } else { argc = 0; argv = 0; } /* Convert arguments from Java to JS values */ for (arg_num = 0; arg_num < argc; arg_num++) { jobject arg = (*jEnv)->GetObjectArrayElement(jEnv, java_args, arg_num); if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num])) goto cleanup_argv; JS_AddNamedRoot(cx, &argv[arg_num], "&argv[arg_num]"); } if (!JS_GetUCProperty(cx, js_obj, function_name_ucs2, function_name_len, &function_val)) goto cleanup_argv; if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val)) goto cleanup_argv; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &result, &dummy_bool); cleanup_argv: if (argv) { for (i = 0; i < arg_num; i++) JS_RemoveRoot(cx, &argv[i]); JS_free(cx, argv); } done: if (function_name_ucs2) (*jEnv)->ReleaseStringChars(jEnv, function_name_jstr, function_name_ucs2); if (!jsj_exit_js(cx, jsj_env, saved_reporter)) return NULL; return result; }
NS_METHOD nsCLiveconnect::Eval(JNIEnv *jEnv, lcjsobject obj, const jchar *script, jsize length, void* principalsArray[], int numPrincipals, nsISupports *securitySupports, jobject *pjobj) { if(jEnv == NULL || obj == 0) { return NS_ERROR_FAILURE; } JSJavaThreadState *jsj_env = NULL; JSObjectHandle *handle = (JSObjectHandle*)obj; JSObject *js_obj = handle->js_obj; JSContext *cx = NULL; jsval js_val; int dummy_cost = 0; JSBool dummy_bool = PR_FALSE; JSErrorReporter saved_state = NULL; jobject result = NULL; const char *codebase = NULL; JSPrincipals *principals = NULL; JSBool eval_succeeded = PR_FALSE; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; result = NULL; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; if (!script) { JS_ReportError(cx, "illegal null string eval argument"); goto done; } /* Set up security stuff */ if (JSJ_callbacks && JSJ_callbacks->get_JSPrincipals_from_java_caller) principals = JSJ_callbacks->get_JSPrincipals_from_java_caller(jEnv, cx, principalsArray, numPrincipals, securitySupports); codebase = principals ? principals->codebase : NULL; /* Have the JS engine evaluate the unicode string */ eval_succeeded = JS_EvaluateUCScriptForPrincipals(cx, js_obj, principals, script, length, codebase, 0, &js_val); if (!eval_succeeded) goto done; /* Convert result to a subclass of java.lang.Object */ jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &result, &dummy_bool); done: if (principals) JSPRINCIPALS_DROP(cx, principals); if (!jsj_exit_js(cx, jsj_env, saved_state)) return NS_ERROR_FAILURE; *pjobj = result; return NS_OK; }
/** * call a method of Native JSObject. * * @param jEnv - JNIEnv on which the call is being made. * @param obj - A Native JS Object. * @param name - Name of a method. * @param jobjArr - Array of jobjects representing parameters of method being caled. * @param pjobj - return value. */ NS_METHOD nsCLiveconnect::Call(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobjectArray java_args, void* principalsArray[], int numPrincipals, nsISupports *securitySupports, jobject *pjobj) { if(jEnv == NULL || obj == 0) { return NS_ERROR_FAILURE; } int i = 0; int argc = 0; int arg_num = 0; jsval *argv = 0; JSJavaThreadState *jsj_env = NULL; JSObjectHandle *handle = (JSObjectHandle*)obj; JSObject *js_obj = handle->js_obj; JSContext *cx = NULL; jsval js_val; jsval function_val = 0; int dummy_cost = 0; JSBool dummy_bool = PR_FALSE; JSErrorReporter saved_state = NULL; jobject result = NULL; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; result = NULL; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; if (!name) { JS_ReportError(cx, "illegal null JavaScript function name"); goto done; } /* Allocate space for JS arguments */ argc = java_args ? jEnv->GetArrayLength(java_args) : 0; if (argc) { argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval)); if (!argv) goto done; } else { argv = 0; } /* Convert arguments from Java to JS values */ for (arg_num = 0; arg_num < argc; arg_num++) { jobject arg = jEnv->GetObjectArrayElement(java_args, arg_num); JSBool ret = jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num]); jEnv->DeleteLocalRef(arg); if (!ret) goto cleanup_argv; JS_AddRoot(cx, &argv[arg_num]); } if (!JS_GetUCProperty(cx, js_obj, name, length, &function_val)) goto cleanup_argv; if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val)) goto cleanup_argv; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &result, &dummy_bool); cleanup_argv: if (argv) { for (i = 0; i < arg_num; i++) JS_RemoveRoot(cx, &argv[i]); JS_free(cx, argv); } done: if (!jsj_exit_js(cx, jsj_env, saved_state)) return NS_ERROR_FAILURE; *pjobj = result; return NS_OK; }
NS_INTERFACE_MAP_END //////////////////////////////////////////////////////////////////////////// // from nsILiveconnect: /** * get member of a Native JSObject for a given name. * * @param jEnv - JNIEnv on which the call is being made. * @param obj - A Native JS Object. * @param name - Name of a member. * @param pjobj - return parameter as a java object representing * the member. If it is a basic data type it is converted to * a corresponding java type. If it is a NJSObject, then it is * wrapped up as java wrapper netscape.javascript.JSObject. */ NS_METHOD nsCLiveconnect::GetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[], int numPrincipals, nsISupports *securitySupports, jobject *pjobj) { if(jEnv == NULL || obj == 0) { return NS_ERROR_FAILURE; } JSJavaThreadState *jsj_env = NULL; JSObjectHandle *handle = (JSObjectHandle*)obj; JSObject *js_obj = handle->js_obj; JSContext *cx = NULL; jobject member = NULL; jsval js_val; int dummy_cost = 0; JSBool dummy_bool = PR_FALSE; JSErrorReporter saved_state = NULL; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; if (!name) { JS_ReportError(cx, "illegal null member name"); member = NULL; goto done; } if (!JS_GetUCProperty(cx, js_obj, name, length, &js_val)) goto done; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &member, &dummy_bool); done: if (!jsj_exit_js(cx, jsj_env, saved_state)) return NS_ERROR_FAILURE; *pjobj = member; return NS_OK; }