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

📄 jsj_javaobject.c

📁 caffeine-monkey java实现的js模拟引擎
💻 C
📖 第 1 页 / 共 3 页
字号:
JavaObject_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp){    JavaObjectWrapper *java_wrapper;    JavaClassDescriptor *class_descriptor;    jobject java_obj;    JNIEnv *jEnv;    JSJavaThreadState *jsj_env;    JSBool result;    java_wrapper = JS_GetPrivate(cx, obj);    if (!java_wrapper) {        if (type == JSTYPE_OBJECT) {            *vp = OBJECT_TO_JSVAL(obj);            return JS_TRUE;        }        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL,                             JSJMSG_BAD_OP_JOBJECT);        return JS_FALSE;    }    java_obj = java_wrapper->java_obj;    class_descriptor = java_wrapper->class_descriptor;    switch (type) {    case JSTYPE_OBJECT:        *vp = OBJECT_TO_JSVAL(obj);        return JS_TRUE;    case JSTYPE_FUNCTION:        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL,                             JSJMSG_CONVERT_TO_FUNC);        return JS_FALSE;    case JSTYPE_VOID:    case JSTYPE_STRING:        /* Get the Java per-thread environment pointer for this JSContext */        jsj_env = jsj_EnterJava(cx, &jEnv);        if (!jEnv)            return JS_FALSE;        /* Either extract a C-string from the java.lang.String object           or call the Java toString() method */        result = jsj_ConvertJavaObjectToJSString(cx, jEnv, class_descriptor, java_obj, vp);        jsj_ExitJava(jsj_env);        return result;    case JSTYPE_NUMBER:        /* Get the Java per-thread environment pointer for this JSContext */        jsj_env = jsj_EnterJava(cx, &jEnv);        if (!jEnv)            return JS_FALSE;        /* Call Java doubleValue() method, if applicable */        result = jsj_ConvertJavaObjectToJSNumber(cx, jEnv, class_descriptor, java_obj, vp);        jsj_ExitJava(jsj_env);        return result;    case JSTYPE_BOOLEAN:        /* Get the Java per-thread environment pointer for this JSContext */        jsj_env = jsj_EnterJava(cx, &jEnv);        if (!jEnv)            return JS_FALSE;        /* Call booleanValue() method, if applicable */        result = jsj_ConvertJavaObjectToJSBoolean(cx, jEnv, class_descriptor, java_obj, vp);        jsj_ExitJava(jsj_env);        return result;    default:        JS_ASSERT(0);        return JS_FALSE;    }}/* * Get a property from the prototype object of a native ECMA object, i.e. * return <js_constructor_name>.prototype.<member_name> * This is used to allow Java objects to inherit methods from Array.prototype * and String.prototype. */static JSBoolinherit_props_from_JS_natives(JSContext *cx, const char *js_constructor_name,                              const char *member_name, jsval *vp){    JSObject *global_obj, *constructor_obj, *prototype_obj;    jsval constructor_val, prototype_val;    global_obj = JS_GetGlobalObject(cx);    JS_ASSERT(global_obj);    if (!global_obj)        return JS_FALSE;    JS_GetProperty(cx, global_obj, js_constructor_name, &constructor_val);    JS_ASSERT(JSVAL_IS_OBJECT(constructor_val));    constructor_obj = JSVAL_TO_OBJECT(constructor_val);    JS_GetProperty(cx, constructor_obj, "prototype", &prototype_val);    JS_ASSERT(JSVAL_IS_OBJECT(prototype_val));    prototype_obj = JSVAL_TO_OBJECT(prototype_val);    return JS_GetProperty(cx, prototype_obj, member_name, vp) && *vp != JSVAL_VOID;}struct JSJPropertyInfo {    JSBool wantProp;            /* input param tells whether prop is returned */    const char* name;           /* output param, name of property (XXX ASCII) */    uintN attributes;           /* output param, attributes of property */    JSProperty *prop;           /* output param, if wantProp, held pointer that                                   must be released via OBJ_DROP_PROPERTY */};typedef struct JSJPropertyInfo JSJPropertyInfo;static JSBoollookup_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj,                    JavaObjectWrapper **java_wrapperp, jsid id,                    JavaMemberDescriptor **member_descriptorp,                    jsval *vp, JSObject **proto_chainp,                    JSJPropertyInfo *prop_infop){    jsval idval;    JavaObjectWrapper *java_wrapper;    JavaMemberDescriptor *member_descriptor;    const char *member_name;    JavaClassDescriptor *class_descriptor;    JSObject *proto_chain;    JSBool found_in_proto;    found_in_proto = JS_FALSE;    member_descriptor = NULL;    java_wrapper = JS_GetPrivate(cx, obj);    /* Handle accesses to prototype object */    if (!java_wrapper) {        if (JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) &&            (member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) {            if (!strcmp(member_name, "constructor"))                goto done;        }        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_BAD_OP_JOBJECT);        return JS_FALSE;    }    class_descriptor = java_wrapper->class_descriptor;    JS_ASSERT(IS_REFERENCE_TYPE(class_descriptor->type));    member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id);    if (member_descriptor)        goto done;    /* Instances can reference static methods and fields */    member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id);    if (member_descriptor)        goto done;    /* Ensure that the property we're searching for is string-valued. */    JS_IdToValue(cx, id, &idval);    if (!JSVAL_IS_STRING(idval)) {        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_BAD_JOBJECT_EXPR);        return JS_FALSE;    }    member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));    /*     * A little LC3 feature magic:     *   + Instances of java.lang.String "inherit" the standard ECMA string methods     *     of String.prototype.  All of the ECMA string methods convert the Java     *     string to a JS string before performing the string operation.  For example,     *         s = new java.lang.String("foobar");     *         return s.slice(2);     *   + Similarly, instances of Java arrays "inherit" the standard ECMA array     *     methods of Array.prototype.  (Not all of these methods work properly     *     on JavaArray objects, however, since the 'length' property is read-only.)     */    if (vp) {        if ((class_descriptor->type == JAVA_SIGNATURE_JAVA_LANG_STRING) &&            inherit_props_from_JS_natives(cx, "String", member_name, vp))            goto done;        if ((class_descriptor->type == JAVA_SIGNATURE_ARRAY) &&            inherit_props_from_JS_natives(cx, "Array", member_name, vp))            goto done;    }    /* Check for access to magic prototype chain property */    if (!strcmp(member_name, "__proto__")) {        proto_chain = JS_GetPrototype(cx, obj);        if (vp)            *vp = OBJECT_TO_JSVAL(proto_chain);        goto done;    }    /*     * See if the property looks like the explicit resolution of an     * overloaded method, e.g. "max(double,double)", first as an instance method,     * then as a static method.  If we find such a method, it will be cached     * so future accesses won't run this code.     */    member_descriptor = jsj_ResolveExplicitMethod(cx, jEnv, class_descriptor, id, JS_FALSE);    if (member_descriptor)        goto done;    member_descriptor = jsj_ResolveExplicitMethod(cx, jEnv, class_descriptor, id, JS_TRUE);    if (member_descriptor)        goto done;    /* Is the property defined in the prototype chain? */    if (proto_chainp && prop_infop) {        /* If so, follow __proto__ link to search prototype chain */        proto_chain = JS_GetPrototype(cx, obj);        /* Use OBJ_LOOKUP_PROPERTY to determine if and where the property           actually exists in the prototype chain. */        if (proto_chain) {            if (!OBJ_LOOKUP_PROPERTY(cx, proto_chain, id, proto_chainp,                                     &prop_infop->prop)) {                return JS_FALSE;            }            if (prop_infop->prop) {                if (!OBJ_GET_ATTRIBUTES(cx, *proto_chainp, id, prop_infop->prop,                                        &prop_infop->attributes)) {                    OBJ_DROP_PROPERTY(cx, *proto_chainp, prop_infop->prop);                    return JS_FALSE;                }                if (!prop_infop->wantProp) {                    OBJ_DROP_PROPERTY(cx, *proto_chainp, prop_infop->prop);                    prop_infop->prop = NULL;                }                prop_infop->name = member_name;                found_in_proto = JS_TRUE;                goto done;            }        }    }    /* Report lack of Java member with the given property name */    JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_NO_INSTANCE_NAME,                         class_descriptor->name, member_name);    return JS_FALSE;done:    /* Success.  Handle the multiple return values */    if (java_wrapperp)        *java_wrapperp = java_wrapper;    if (member_descriptorp)        *member_descriptorp = member_descriptor;    if (proto_chainp && !found_in_proto)        *proto_chainp = NULL;    return JS_TRUE;}JS_EXPORT_API(JSBool)JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp){    jobject java_obj;    JavaMemberDescriptor *member_descriptor;    JavaObjectWrapper *java_wrapper;    JNIEnv *jEnv;    JSObject *funobj;    jsval field_val, method_val;    JSBool success;    JSJavaThreadState *jsj_env;    JSObject *proto_chain;    JSJPropertyInfo prop_info;    /* printf("In JavaObject_getProperty\n"); */    /* Get the Java per-thread environment pointer for this JSContext */    jsj_env = jsj_EnterJava(cx, &jEnv);    if (!jEnv)        return JS_FALSE;    if (vp)        *vp = JSVAL_VOID;    prop_info.wantProp = JS_FALSE;    if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member_descriptor, vp,                             &proto_chain, &prop_info)) {        jsj_ExitJava(jsj_env);        return JS_FALSE;    }    /* Handle access to special, non-Java properties of JavaObjects, e.g. the       "constructor" property of the prototype object */    if (!member_descriptor) {        jsj_ExitJava(jsj_env);        if (proto_chain)            return JS_GetProperty(cx, proto_chain, prop_info.name, vp);        return JS_TRUE;    }    java_obj = java_wrapper->java_obj;    field_val = method_val = JSVAL_VOID;    if (jaApplet && (*jEnv)->IsInstanceOf(jEnv, java_obj, jaApplet)) {        jsj_JSIsCallingApplet = JS_TRUE;    }    /* If a field member, get the value of the field */    if (member_descriptor->field) {        success = jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_obj, &field_val);        if (!success) {            jsj_ExitJava(jsj_env);            return JS_FALSE;        }    }    /* If a method member, build a wrapper around the Java method */    if (member_descriptor->methods) {        /* Create a function object with this JavaObject as its parent, so that           JSFUN_BOUND_METHOD binds it as the default 'this' for the function. */        funobj = JS_CloneFunctionObject(cx, member_descriptor->invoke_func_obj, obj);        if (!funobj) {            jsj_ExitJava(jsj_env);            return JS_FALSE;        }        method_val = OBJECT_TO_JSVAL(funobj);    }#if TEST_JAVAMEMBER    /* Always create a JavaMember object, even though it's inefficient */    obj = jsj_CreateJavaMember(cx, method_val, field_val);    if (!obj) {        jsj_ExitJava(jsj_env);        return JS_FALSE;    }    *vp = OBJECT_TO_JSVAL(obj);#else   /* !TEST_JAVAMEMBER */    if (member_descriptor->field) {        if (!member_descriptor->methods) {            /* Return value of Java field */            *vp = field_val;        } else {            /* Handle special case of access to a property that could refer               to either a Java field or a method that share the same name.               In Java, such ambiguity is not possible because the compiler               can statically determine which is being accessed. */            obj = jsj_CreateJavaMember(cx, method_val, field_val);            if (!obj) {                jsj_ExitJava(jsj_env);                return JS_FALSE;            }            *vp = OBJECT_TO_JSVAL(obj);        }    } else {        /* Return wrapper around Java method */        *vp = method_val;    }#endif  /* !TEST_JAVAMEMBER */    jsj_ExitJava(jsj_env);    return JS_TRUE;}JS_STATIC_DLL_CALLBACK(JSBool)JavaObject_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp){    jobject java_obj;    const char *member_name;    JavaObjectWrapper *java_wrapper;    JavaClassDescriptor *class_descriptor;    JavaMemberDescriptor *member_descriptor;    jsval idval;    JNIEnv *jEnv;    JSJavaThreadState *jsj_env;    JSObject *proto_chain;

⌨️ 快捷键说明

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