Esempio n. 1
0
JavaClass_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                       jsval *statep, jsid *idp)
{
    JavaMemberDescriptor *member_descriptor;
    JavaClassDescriptor *class_descriptor;
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;
    
    class_descriptor = JS_GetPrivate(cx, obj);

    /* Check for prototype JavaClass object */
    if (!class_descriptor) {
        *statep = JSVAL_NULL;
        if (idp)
            *idp = INT_TO_JSVAL(0);
        return JS_TRUE;
    }
    
    switch(enum_op) {
    case JSENUMERATE_INIT:
        /* Get the Java per-thread environment pointer for this JSContext */
        jsj_env = jsj_EnterJava(cx, &jEnv);
        if (!jEnv)
            return JS_FALSE;
        member_descriptor = jsj_GetClassStaticMembers(cx, jEnv, class_descriptor);
        *statep = PRIVATE_TO_JSVAL(member_descriptor);
        if (idp)
            *idp = INT_TO_JSVAL(class_descriptor->num_instance_members);
	jsj_ExitJava(jsj_env);
        return JS_TRUE;
        
    case JSENUMERATE_NEXT:
        member_descriptor = JSVAL_TO_PRIVATE(*statep);
        if (member_descriptor) {

            /* Don't enumerate explicit-signature methods, i.e. enumerate toValue,
               but not toValue(int), toValue(double), etc. */
            while (member_descriptor->methods && member_descriptor->methods->is_alias) {
                member_descriptor = member_descriptor->next;
                if (!member_descriptor) {
                    *statep = JSVAL_NULL;
                    return JS_TRUE;
                }
            }

            *idp = member_descriptor->id;
            *statep = PRIVATE_TO_JSVAL(member_descriptor->next);
            return JS_TRUE;
        }
        /* Fall through ... */

    case JSENUMERATE_DESTROY:
        *statep = JSVAL_NULL;
        return JS_TRUE;

    default:
        JS_ASSERT(0);
        return JS_FALSE;
    }
}
Esempio n. 2
0
static JSBool
JavaArray_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
                         JSObject **objp, JSProperty **propp)
{
    JNIEnv *jEnv;
    JSErrorReporter old_reporter;
    JSJavaThreadState *jsj_env;

    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;

    old_reporter = JS_SetErrorReporter(cx, NULL);
    if (access_java_array_element(cx, jEnv, obj, id, NULL, JS_FALSE)) {
        *objp = obj;
        *propp = (JSProperty*)1;
        js_SetObjectWeakRoot(cx, obj);
    } else {
        *objp = NULL;
        *propp = NULL;
    }
    JS_SetErrorReporter(cx, old_reporter);
    jsj_ExitJava(jsj_env);
    return JS_TRUE;
}
Esempio n. 3
0
JavaClass_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
                         JSObject **objp, JSProperty **propp
#if defined JS_THREADSAFE && defined DEBUG
                            , const char *file, uintN line
#endif
                            )
{
    JNIEnv *jEnv;
    JSErrorReporter old_reporter;
    JSJavaThreadState *jsj_env;

    /* printf("In JavaClass_lookupProperty()\n"); */
    
    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;

    old_reporter = JS_SetErrorReporter(cx, NULL);
    if (lookup_static_member_by_id(cx, jEnv, obj, NULL, id, NULL)) {
        *objp = obj;
        *propp = (JSProperty*)1;
    } else {
        *objp = NULL;
        *propp = NULL;
    }

    JS_SetErrorReporter(cx, old_reporter);
    jsj_ExitJava(jsj_env);
    return JS_TRUE;
}
Esempio n. 4
0
JavaClass_hasInstance(JSContext *cx, JSObject *obj, jsval candidate_jsval,
                      JSBool *has_instancep)
{
    JavaClassDescriptor *class_descriptor;
    JavaObjectWrapper *java_wrapper;
    JSClass *js_class;
    JSBool has_instance;
    JSObject *candidate_obj;
    jclass java_class;
    jobject java_obj;
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;
    
    has_instance = JS_FALSE;
    class_descriptor = JS_GetPrivate(cx, obj);
    if (!class_descriptor) {
        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                                                    JSJMSG_BAD_OP_JCLASS);
        return JS_FALSE;
    }

    /*
     * Make sure that the thing to the left of the instanceof operator is a
     * Java object.
     */
    if (!JSVAL_IS_OBJECT(candidate_jsval))
        goto done;
    candidate_obj = JSVAL_TO_OBJECT(candidate_jsval);
#ifdef JS_THREADSAFE
    js_class = JS_GetClass(cx, candidate_obj);
#else
    js_class = JS_GetClass(candidate_obj);
#endif
    if ((js_class != &JavaObject_class) && (js_class != &JavaArray_class))
        goto done;

    java_class = class_descriptor->java_class;
    java_wrapper = JS_GetPrivate(cx, candidate_obj);
    if (!java_wrapper) {
        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                                                JSJMSG_BAD_OP_PROTO);
        return JS_FALSE;
    }
    java_obj = java_wrapper->java_obj;
    /* Get JNI pointer */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    has_instance = (*jEnv)->IsInstanceOf(jEnv, java_obj, java_class);
    jsj_ExitJava(jsj_env);

done:
    *has_instancep = has_instance;
    return JS_TRUE;
}
Esempio n. 5
0
static JSBool
JavaArray_setPropertyById(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;
    JSBool result;
    
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;
    result = access_java_array_element(cx, jEnv, obj, id, vp, JS_TRUE);
    jsj_ExitJava(jsj_env);
    return result;
}
Esempio n. 6
0
JavaClass_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
    jclass java_class;
    const char *member_name;
    JavaClassDescriptor *class_descriptor;
    JavaMemberDescriptor *member_descriptor;
    jsval idval;
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;
    JSBool result;

    /* printf("In JavaClass_setProperty\n"); */

    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;
    
    if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor)) {
	jsj_ExitJava(jsj_env);
        return JS_FALSE;
    }

    /* Check for the case where there is a method with the given name, but no field
       with that name */
    if (!member_descriptor->field)
        goto no_such_field;

    /* Silently fail if field value is final (immutable), as required by ECMA spec */
    if (member_descriptor->field->modifiers & ACC_FINAL) {
	jsj_ExitJava(jsj_env);
        return JS_TRUE;
    }

    java_class = class_descriptor->java_class;
    result = jsj_SetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, *vp);
    jsj_ExitJava(jsj_env);
    return result;

no_such_field:
    JS_IdToValue(cx, id, &idval);
    member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
    JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                   JSJMSG_MISSING_STATIC,
                   member_name, class_descriptor->name);
    jsj_ExitJava(jsj_env);
    return JS_FALSE;
}
Esempio n. 7
0
/* Utility routine to wrap a Java object inside a JS object, having a 
   a result type of either JavaObject or JavaArray. */
JSBool
JSJ_ConvertJavaObjectToJSValue(JSContext *cx, jobject java_obj, jsval *vp)
{
    JNIEnv *jEnv;
    JSBool result;
    JSJavaThreadState *jsj_env;
            
    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;

    result = jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, vp);
    jsj_ExitJava(jsj_env);
    return result;
}
Esempio n. 8
0
JavaClass_finalize(JSContext *cx, JSObject *obj)
{
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;

    JavaClassDescriptor *class_descriptor = JS_GetPrivate(cx, obj);
    if (!class_descriptor)
        return;
    
    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return;

    /* printf("Finalizing %s\n", class_descriptor->name); */
    jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor);
    jsj_ExitJava(jsj_env);
}
Esempio n. 9
0
JavaClass_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    JSObject *obj_arg, *JavaClass_obj;
    JavaObjectWrapper *java_wrapper;
    JavaClassDescriptor *class_descriptor;
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;

    if (argc != 1 ||
	!JSVAL_IS_OBJECT(argv[0]) ||
	!(obj_arg = JSVAL_TO_OBJECT(argv[0])) ||
	!JS_InstanceOf(cx, obj_arg, &JavaObject_class, 0) ||
	((java_wrapper = JS_GetPrivate(cx, obj_arg)) == NULL)) {
        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                             JSJMSG_NEED_JCLASS_ARG);
        return JS_FALSE;
    }

    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;

    class_descriptor = java_wrapper->class_descriptor;
    if (!(*jEnv)->IsSameObject(jEnv, class_descriptor->java_class, jlClass)) {
	JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                             JSJMSG_NEED_JCLASS_ARG);
	jsj_ExitJava(jsj_env);
        return JS_FALSE;
    }

    class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_wrapper->java_obj);
    JavaClass_obj = jsj_new_JavaClass(cx, jEnv, NULL, class_descriptor);
    if (!JavaClass_obj) {
	jsj_ExitJava(jsj_env);
        return JS_FALSE;
    }

    *rval = OBJECT_TO_JSVAL(JavaClass_obj);
    jsj_ExitJava(jsj_env);
    return JS_TRUE;
}
Esempio n. 10
0
getClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    JSObject *obj_arg, *JavaClass_obj;
    JavaObjectWrapper *java_wrapper;
    JavaClassDescriptor *class_descriptor;
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;

    if (argc != 1 ||
    !JSVAL_IS_OBJECT(argv[0]) ||
    !(obj_arg = JSVAL_TO_OBJECT(argv[0])) ||
    (!JS_InstanceOf(cx, obj_arg, &JavaObject_class, 0) &&
         !JS_InstanceOf(cx, obj_arg, &JavaArray_class, 0))) {
        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                                                JSJMSG_NEED_JOBJECT_ARG);
        return JS_FALSE;
    }

    java_wrapper = JS_GetPrivate(cx, obj_arg);
    if (!java_wrapper) {
        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                                                JSJMSG_PROTO_GETCLASS);
        return JS_FALSE;
    }

    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;
    
    class_descriptor = java_wrapper->class_descriptor;

    JavaClass_obj = jsj_new_JavaClass(cx, jEnv, NULL, class_descriptor);
    if (!JavaClass_obj) {
	jsj_ExitJava(jsj_env);
        return JS_FALSE;
    }

    *rval = OBJECT_TO_JSVAL(JavaClass_obj);
    jsj_ExitJava(jsj_env);
    return JS_TRUE;
}
Esempio n. 11
0
static JSBool
JavaArray_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                       jsval *statep, jsid *idp)
{
    JavaObjectWrapper *java_wrapper;
    JSJavaThreadState *jsj_env;
    JNIEnv *jEnv;
    jsize array_length, index;
    JSBool ok = JS_TRUE;

    java_wrapper = JS_GetPrivate(cx, obj);
    /* Check for prototype object */
    if (!java_wrapper) {
        *statep = JSVAL_NULL;
        if (idp)
            *idp = INT_TO_JSVAL(0);
        return JS_TRUE;
    }
        
    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;

    array_length = jsj_GetJavaArrayLength(cx, jEnv, java_wrapper->java_obj);
    if (array_length < 0) {
        jsj_ExitJava(jsj_env);
        return JS_FALSE;
    }

    switch(enum_op) {
    case JSENUMERATE_INIT:
        *statep = INT_TO_JSVAL(0);

        if (idp)
            *idp = INT_TO_JSVAL(array_length);
        break;
        
    case JSENUMERATE_NEXT:
        index = JSVAL_TO_INT(*statep);
        if (index < array_length) {
            JS_ValueToId(cx, INT_TO_JSVAL(index), idp);
            index++;
            *statep = INT_TO_JSVAL(index);
            break;
        }

        /* Fall through ... */

    case JSENUMERATE_DESTROY:
        *statep = JSVAL_NULL;
        break;

    default:
        JS_ASSERT(0);
        ok = JS_FALSE;
        break;
    }

    jsj_ExitJava(jsj_env);
    return ok;
}
Esempio n. 12
0
capture_js_error_reports_for_java(JSContext *cx, const char *message,
                                  JSErrorReport *report)
{
    CapturedJSError *new_error;
    JSJavaThreadState *jsj_env;
    jthrowable java_exception, tmp_exception;
    JNIEnv *jEnv;

    /* Warnings are not propagated as Java exceptions - they are simply
       ignored.  Ditto for exceptions that are duplicated in the form
       of error reports. */
    if (report && (report->flags & (JSREPORT_WARNING | JSREPORT_EXCEPTION)))
        return;

    /* Create an empty struct to hold the saved JS error state */
    new_error = malloc(sizeof(CapturedJSError));
    if (!new_error)
        goto out_of_memory;
    memset(new_error, 0, sizeof(CapturedJSError));

    /* Copy all the error info out of the original report into a private copy */
    if (message) {
        new_error->message = strdup(message);
        if (!new_error->message)
            goto out_of_memory;
    }
    if (report) {
        new_error->report.lineno = report->lineno;

        if (report->filename) {
            new_error->report.filename = strdup(report->filename);
            if (!new_error->report.filename)
                goto out_of_memory;
        }

        if (report->linebuf) {
            new_error->report.linebuf = strdup(report->linebuf);
            if (!new_error->report.linebuf)
                goto out_of_memory;
            new_error->report.tokenptr =
                new_error->report.linebuf + (report->tokenptr - report->linebuf);
        }
    }

    /* Get the head of the list of pending JS errors */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jsj_env)
        goto abort;

    /* If there's a Java exception associated with this error, save it too. */
    java_exception = (*jEnv)->ExceptionOccurred(jEnv);
    if (java_exception) {
        (*jEnv)->ExceptionClear(jEnv);
        tmp_exception = java_exception;     /* Make a copy */
        java_exception = (*jEnv)->NewGlobalRef(jEnv, java_exception);
        new_error->java_exception = java_exception;
        (*jEnv)->DeleteLocalRef(jEnv, tmp_exception);
    }

    /* Push this error onto the list of pending JS errors */
    new_error->next = jsj_env->pending_js_errors;
    jsj_env->pending_js_errors = new_error;
    jsj_ExitJava(jsj_env);
    return;

abort:
out_of_memory:
    /* No recovery action possible */
    JS_ASSERT(0);
    destroy_saved_js_error(jEnv, new_error);
    return;
}
Esempio n. 13
0
JavaPackage_resolve(JSContext *cx, JSObject *obj, jsval id)
{
    JavaPackage_Private *package;
    JSBool ok = JS_TRUE;
    jclass jclazz;
    char *subPath, *newPath;
    const char *path;
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;

    /* Painful hack for pre_define_java_packages() */
    if (quiet_resolve_failure)
        return JS_FALSE;
                
    package = (JavaPackage_Private *)JS_GetPrivate(cx, obj);
    if (!package)
        return JS_TRUE;

    if (!JSVAL_IS_STRING(id))
        return JS_TRUE;
    subPath = JS_GetStringBytes(JSVAL_TO_STRING(id));

    /*
     * There will be an attempt to invoke the toString() method when producing
     * the string representation of a JavaPackage.  When this occurs, avoid
     * creating a bogus toString package.  (This means that no one can ever
     * create a package with the simple name "toString", but we'll live with
     * that limitation.)
     */
    if (!strcmp(subPath, "toString"))
        return JS_FALSE;

    path = package->path;
    newPath = JS_smprintf("%s%s%s", path, (path[0] ? "/" : ""), subPath);
    if (!newPath) {
        JS_ReportOutOfMemory(cx);
        return JS_FALSE;
    }

    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv) {
        ok = JS_FALSE;
        goto out;
    }

    /*
        Unfortunately, Java provides no way to find out whether a particular
        name is a package or not.  The only way to tell is to try to load the
        name as a class file and, if that fails, assume it's a package.  This
        makes things work as expected for the most part, but it has three
        noticeable problems that keep coming up:

        - You can refer to a package like java.lang.i.buried.paul without
          generating a complaint.  Of course, you'll never be able to refer to
          any classes through it.

        - An annoying consequence of the above is that misspelling a class name
          results in a cryptic error about packages.

        - In a browser context, i.e. where applets are involved, figuring out
          whether something is a class may require looking for it over the net
          using the current classloader.  This means that the first time you
          refer to java.lang.System in a js context, there will be an attempt
          to search for [[DOCBASE]]/java.class on the server.
    
        A solution is to explicitly tell jsjava the names of all the (local)
        packages on the CLASSPATH.  (Not implemented yet.)

    */
    jclazz = (*jEnv)->FindClass(jEnv, newPath);
    if (jclazz) {
        JSObject *newClass;

        newClass = jsj_define_JavaClass(cx, jEnv, obj, subPath, jclazz);
        (*jEnv)->DeleteLocalRef(jEnv, jclazz);
        if (!newClass) {
            ok = JS_FALSE;
            goto out;
        }
    } else {

        /* We assume that any failed attempt to load a class is because it
           doesn't exist.  If we wanted to do a better job, we would check
           the exception type and make sure that it's NoClassDefFoundError */
        (*jEnv)->ExceptionClear(jEnv);

        /*
         * If there's no class of the given name, then we must be referring to
         * a package.  However, don't allow bogus sub-packages of pre-defined
         * system packages to be created.
         */
        if (JS_InstanceOf(cx, obj, &JavaPackage_class, NULL)) {
            JavaPackage_Private *current_package;

            current_package = JS_GetPrivate(cx, obj);
            if (current_package->flags & PKG_SYSTEM) {
                char *msg, *cp;
                msg = JS_strdup(cx, newPath);

                /* Check for OOM */
                if (msg) {
                    /* Convert package of form "java/lang" to "java.lang" */
                    for (cp = msg; *cp != '\0'; cp++)
                        if (*cp == '/')
                            *cp = '.';
                    JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                                                JSJMSG_MISSING_PACKAGE, msg);
                    free((char*)msg);
                }
                               
                ok = JS_FALSE;
                goto out;
            }
        }

        if (!define_JavaPackage(cx, obj, subPath, newPath, 0, JSPROP_READONLY)) {
            ok = JS_FALSE;
            goto out;
        }
        
#ifdef DEBUG
        /* printf("JavaPackage \'%s\' created\n", newPath); */
#endif

    }
    
out:
    free(newPath);
    jsj_ExitJava(jsj_env);
    return ok;
}
Esempio n. 14
0
JavaClass_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
    jsval idval;
    jclass java_class;
    const char *member_name;
    JavaClassDescriptor *class_descriptor;
    JavaMemberDescriptor *member_descriptor;
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;
    JSBool result;

    /* printf("In JavaClass_getProperty\n"); */
    
    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;

    if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor)) {
	jsj_ExitJava(jsj_env);
        return JS_FALSE;
    }
    if (!member_descriptor) {
        *vp = JSVAL_VOID;
	jsj_ExitJava(jsj_env);
        return JS_TRUE;
    }

    java_class = class_descriptor->java_class;

    if (member_descriptor->field) {
        if (!member_descriptor->methods) {
            result = jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, vp);
	    jsj_ExitJava(jsj_env);
	    return result;
        } else {
            JS_ASSERT(0);
        }
    } else {
        JSFunction *function;
        
        /* TODO - eliminate JSFUN_BOUND_METHOD */
        if (member_descriptor->methods->is_alias) {
            /* If this is an explicit resolution of an overloaded method,
               use the fully-qualified method name as the name of the
               resulting JS function, i.e. "myMethod(int,long)" */
            JS_IdToValue(cx, id, &idval);
            member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
        } else {
            /* Either not explicit resolution of overloaded method or
               explicit resolution was unnecessary because method was
               not overloaded. */
            member_name = member_descriptor->name;
        }
        function = JS_NewFunction(cx, jsj_JavaStaticMethodWrapper, 0,
                                  JSFUN_BOUND_METHOD, obj, member_name);
        if (!function) {
	    jsj_ExitJava(jsj_env);
            return JS_FALSE;
	}

        *vp = OBJECT_TO_JSVAL(JS_GetFunctionObject(function));
    }

    jsj_ExitJava(jsj_env);
    return JS_TRUE;
}