⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsj_jsobject.c

📁 caffeine-monkey java实现的js模拟引擎
💻 C
📖 第 1 页 / 共 3 页
字号:
 * possible that a JS error was actually triggered by Java at some point, in * which case the original Java exception is thrown. */static voidthrow_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);}/* * This function is called up returning from Java back into JS as a result of * a thrown netscape.javascript.JSException, which itself must have been caused * by a JS error when Java called into JS.  The original JS error is * reconstituted from the JSException and re-reported as a JS error. * * Returns JS_FALSE if an internal error occurs, JS_TRUE otherwise. */JSBooljsj_ReportUncaughtJSException(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception){    JSBool success;    JSErrorReport report;    const char *linebuf, *filename, *message, *tokenptr;    jint lineno, token_index;    jstring linebuf_jstr, filename_jstr, message_jstr;    /* Initialize everything to NULL */    memset(&report, 0, sizeof(JSErrorReport));    success = JS_FALSE;    filename_jstr = linebuf_jstr = message_jstr = NULL;    filename = message = linebuf = tokenptr = NULL;    lineno = (*jEnv)->GetIntField(jEnv, java_exception, njJSException_lineno);    report.lineno = lineno;    filename_jstr = (*jEnv)->GetObjectField(jEnv, java_exception, njJSException_filename);    if ((*jEnv)->ExceptionOccurred(jEnv)) {        jsj_UnexpectedJavaError(cx, jEnv, "Unable to access filename field of a JSException");        goto done;    }    if (filename_jstr)        filename = (*jEnv)->GetStringUTFChars(jEnv, filename_jstr, 0);    report.filename = filename;    linebuf_jstr = (*jEnv)->GetObjectField(jEnv, java_exception, njJSException_source);    if ((*jEnv)->ExceptionOccurred(jEnv)) {        jsj_UnexpectedJavaError(cx, jEnv, "Unable to access source field of a JSException");        goto done;    }    if (linebuf_jstr)        linebuf = (*jEnv)->GetStringUTFChars(jEnv, linebuf_jstr, 0);    report.linebuf = linebuf;    token_index = (*jEnv)->GetIntField(jEnv, java_exception, njJSException_lineno);    report.tokenptr = linebuf + token_index;    message_jstr = (*jEnv)->CallObjectMethod(jEnv, java_exception, jlThrowable_getMessage);    if ((*jEnv)->ExceptionOccurred(jEnv)) {        jsj_UnexpectedJavaError(cx, jEnv, "Unable to access message of a JSException");        goto done;    }    if (message_jstr)        message = (*jEnv)->GetStringUTFChars(jEnv, message_jstr, 0);    js_ReportErrorAgain(cx, message, &report);    success = JS_TRUE;done:    if (filename_jstr && filename)        (*jEnv)->ReleaseStringUTFChars(jEnv, filename_jstr, filename);    if (linebuf_jstr && linebuf)        (*jEnv)->ReleaseStringUTFChars(jEnv, linebuf_jstr, linebuf);    if (message_jstr && message)        (*jEnv)->ReleaseStringUTFChars(jEnv, message_jstr, message);    return success;}/*************** Utilities for calling JavaScript from Java *****************//* * This routine is called just prior to invoking any JS API function from * Java.  It performs a common set of chores, such as obtaining the LiveConnect * state for the invoking Java thread and determining the JSContext to be * used for this thread. * * Returns NULL on failure. */JSJavaThreadState *jsj_enter_js(JNIEnv *jEnv, void* applet_obj, jobject java_wrapper_obj,             JSContext **cxp, JSObject **js_objp, JSErrorReporter *old_error_reporterp,             void **pNSIPrincipaArray, int numPrincipals, void *pNSISecurityContext){    JSContext *cx;    char *err_msg;    JSObject *js_obj;    JSJavaThreadState *jsj_env;    cx = NULL;    err_msg = NULL;    /* Invoke callback, presumably used to implement concurrency constraints */    if (JSJ_callbacks && JSJ_callbacks->enter_js_from_java) {#ifdef OJI        if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg, pNSIPrincipaArray, numPrincipals, pNSISecurityContext,applet_obj))#else        if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg))#endif            goto entry_failure;    }    /* Check the JSObject pointer in the wrapper object. */    if (js_objp) {#ifdef PRESERVE_JSOBJECT_IDENTITY#if JS_BYTES_PER_LONG == 8        js_obj = (JSObject *)((*jEnv)->GetLongField(jEnv, java_wrapper_obj, njJSObject_long_internal));#else        js_obj = (JSObject *)((*jEnv)->GetIntField(jEnv, java_wrapper_obj, njJSObject_internal));#endif#else   /* !PRESERVE_JSOBJECT_IDENTITY */        js_obj = jsj_UnwrapJSObjectWrapper(jEnv, java_wrapper_obj);#endif  /* PRESERVE_JSOBJECT_IDENTITY */        JS_ASSERT(js_obj);        if (!js_obj)            goto error;        *js_objp = js_obj;    }    /* Get the per-thread state corresponding to the current Java thread */    jsj_env = jsj_MapJavaThreadToJSJavaThreadState(jEnv, &err_msg);    if (!jsj_env)        goto error;    /* Get the JSContext that we're supposed to use for this Java thread */    cx = jsj_env->cx;    if (!cx) {        /* We called spontaneously into JS from Java, rather than from JS into           Java and back into JS.  Invoke a callback to obtain/create a           JSContext for us to use. */        if (JSJ_callbacks && JSJ_callbacks->map_jsj_thread_to_js_context) {#ifdef OJI            cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env,                                                             applet_obj,                                                             jEnv, &err_msg);#else            cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env,                                                             jEnv, &err_msg);#endif            if (!cx)                goto error;        } else {            err_msg = JS_smprintf("Unable to find/create JavaScript execution "                                  "context for JNI thread 0x%08x", jEnv);            goto error;        }    }    *cxp = cx;    /*     * Capture all JS error reports so that they can be thrown into the Java     * caller as an instance of netscape.javascript.JSException.     */    *old_error_reporterp =        JS_SetErrorReporter(cx, capture_js_error_reports_for_java);#ifdef JSJ_THREADSAFE    JS_BeginRequest(cx);#endif    return jsj_env;error:    /* Invoke callback, presumably used to implement concurrency constraints */    if (JSJ_callbacks && JSJ_callbacks->exit_js)        JSJ_callbacks->exit_js(jEnv, cx);entry_failure:    if (err_msg) {        if (cx)            JS_ReportError(cx, err_msg);        else            jsj_LogError(err_msg);        free(err_msg);    }    return NULL;}/* * This utility function is called just prior to returning into Java from JS. */JSBooljsj_exit_js(JSContext *cx, JSJavaThreadState *jsj_env, JSErrorReporter original_reporter){    JNIEnv *jEnv;#ifdef JSJ_THREADSAFE    JS_EndRequest(cx);#endif    /* Restore the JS error reporter */    JS_SetErrorReporter(cx, original_reporter);    jEnv = jsj_env->jEnv;#ifdef DEBUG    /* Any Java exceptions should have been noticed and reported already */    if ((*jEnv)->ExceptionOccurred(jEnv)) {        JS_ASSERT(0);        jsj_LogError("Unhandled Java exception detected");        return JS_FALSE;    }#endif    /*     * Convert reported JS errors to JSExceptions, unless the errors were     * themselves the result of Java exceptions, in which case the original     * Java exception is simply propagated.     */    throw_any_pending_js_error_as_a_java_exception(jsj_env);    /* Invoke callback, presumably used to implement concurrency constraints */    if (JSJ_callbacks && JSJ_callbacks->exit_js)        JSJ_callbacks->exit_js(jEnv, cx);    return JS_TRUE;}/* Get the JavaClassDescriptor that corresponds to java.lang.Object */JavaClassDescriptor *jsj_get_jlObject_descriptor(JSContext *cx, JNIEnv *jEnv){    /* The JavaClassDescriptor for java.lang.Object */    static JavaClassDescriptor *jlObject_descriptor = NULL;    if (!jlObject_descriptor)        jlObject_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, jlObject);    return jlObject_descriptor;}/****************** Implementation of methods of JSObject *******************//* * Class:     netscape_javascript_JSObject * Method:    initClass * Signature: ()V */JNIEXPORT void JNICALLJava_netscape_javascript_JSObject_initClass(JNIEnv *jEnv, jclass java_class){    jsj_init_js_obj_reflections_table();}/* * Class:     netscape_javascript_JSObject * Method:    getMember * Signature: (Ljava/lang/String;)Ljava/lang/Object; */JNIEXPORT jobject JNICALLJava_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;    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -