fix for bug #59686, a=asa@mozilla.org, r=rogerl, sr=shaver.
git-svn-id: svn://10.0.0.236/trunk@115821 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -97,7 +97,7 @@ jsj_InitJavaObjReflectionsTable(void)
|
||||
|
||||
#ifdef JSJ_THREADSAFE
|
||||
java_obj_reflections_monitor =
|
||||
(struct PRMonitor *) PR_NewMonitor();
|
||||
(struct PRMonitor *) PR_NewMonitor();
|
||||
if (!java_obj_reflections_monitor) {
|
||||
JSJ_HashTableDestroy(java_obj_reflections);
|
||||
return JS_FALSE;
|
||||
@@ -190,9 +190,9 @@ jsj_WrapJavaObject(JSContext *cx,
|
||||
if (he) {
|
||||
js_wrapper_obj = (JSObject *)he->value;
|
||||
if (js_wrapper_obj) {
|
||||
PR_ExitMonitor(java_obj_reflections_monitor);
|
||||
PR_ExitMonitor(java_obj_reflections_monitor);
|
||||
return js_wrapper_obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,38 +359,38 @@ JavaObject_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
|
||||
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;
|
||||
/* 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;
|
||||
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 */
|
||||
/* 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;
|
||||
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;
|
||||
/* 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;
|
||||
jsj_ExitJava(jsj_env);
|
||||
return result;
|
||||
|
||||
default:
|
||||
JS_ASSERT(0);
|
||||
@@ -427,12 +427,18 @@ inherit_props_from_JS_natives(JSContext *cx, const char *js_constructor_name,
|
||||
return JS_GetProperty(cx, prototype_obj, member_name, vp) && *vp != JSVAL_VOID;
|
||||
}
|
||||
|
||||
struct JSJPropertyInfo {
|
||||
const char* name;
|
||||
uintN attributes;
|
||||
};
|
||||
typedef struct JSJPropertyInfo JSJPropertyInfo;
|
||||
|
||||
static JSBool
|
||||
lookup_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj,
|
||||
JavaObjectWrapper **java_wrapperp,
|
||||
jsid id,
|
||||
JavaObjectWrapper **java_wrapperp, jsid id,
|
||||
JavaMemberDescriptor **member_descriptorp,
|
||||
jsval *vp)
|
||||
jsval *vp, JSObject **proto_chainp,
|
||||
JSJPropertyInfo *prop_infop)
|
||||
{
|
||||
jsval idval;
|
||||
JavaObjectWrapper *java_wrapper;
|
||||
@@ -440,7 +446,9 @@ lookup_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj,
|
||||
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);
|
||||
|
||||
@@ -516,16 +524,21 @@ lookup_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj,
|
||||
if (member_descriptor)
|
||||
goto done;
|
||||
|
||||
/* Is this lookup on behalf of a GetProperty or a LookupProperty ? */
|
||||
if (vp) {
|
||||
/* 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);
|
||||
|
||||
/* TODO: No way to tell if the property doesn't exist in proto_chain
|
||||
or if it exists, but has an undefined value. We assume the former. */
|
||||
if (proto_chain && JS_LookupProperty(cx, proto_chain, member_name, vp) &&
|
||||
(*vp != JSVAL_VOID))
|
||||
/* Use JS_GetPropertyAttributes to determine if the property actually
|
||||
exists in the prototype chain. */
|
||||
if (proto_chain &&
|
||||
JS_GetPropertyAttributes(cx, proto_chain, member_name,
|
||||
&prop_infop->attributes, &found_in_proto) &&
|
||||
found_in_proto) {
|
||||
*proto_chainp = proto_chain;
|
||||
prop_infop->name = member_name;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Report lack of Java member with the given property name */
|
||||
@@ -539,6 +552,8 @@ done:
|
||||
*java_wrapperp = java_wrapper;
|
||||
if (member_descriptorp)
|
||||
*member_descriptorp = member_descriptor;
|
||||
if (proto_chainp && !found_in_proto)
|
||||
*proto_chainp = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@@ -553,6 +568,8 @@ JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
jsval field_val, method_val;
|
||||
JSBool success;
|
||||
JSJavaThreadState *jsj_env;
|
||||
JSObject *proto_chain;
|
||||
JSJPropertyInfo prop_info;
|
||||
|
||||
/* printf("In JavaObject_getProperty\n"); */
|
||||
|
||||
@@ -562,16 +579,19 @@ JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
return JS_FALSE;
|
||||
|
||||
if (vp)
|
||||
*vp = JSVAL_VOID;
|
||||
if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member_descriptor, vp)) {
|
||||
jsj_ExitJava(jsj_env);
|
||||
*vp = JSVAL_VOID;
|
||||
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);
|
||||
jsj_ExitJava(jsj_env);
|
||||
if (proto_chain)
|
||||
return JS_GetProperty(cx, proto_chain, prop_info.name, vp);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@@ -582,9 +602,9 @@ JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
if (member_descriptor->field) {
|
||||
success = jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_obj, &field_val);
|
||||
if (!success) {
|
||||
jsj_ExitJava(jsj_env);
|
||||
jsj_ExitJava(jsj_env);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If a method member, build a wrapper around the Java method */
|
||||
@@ -593,9 +613,9 @@ JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
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);
|
||||
jsj_ExitJava(jsj_env);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
method_val = OBJECT_TO_JSVAL(funobj);
|
||||
}
|
||||
|
||||
@@ -603,7 +623,7 @@ JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
/* Always create a JavaMember object, even though it's inefficient */
|
||||
obj = jsj_CreateJavaMember(cx, method_val, field_val);
|
||||
if (!obj) {
|
||||
jsj_ExitJava(jsj_env);
|
||||
jsj_ExitJava(jsj_env);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
@@ -620,9 +640,9 @@ JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
can statically determine which is being accessed. */
|
||||
obj = jsj_CreateJavaMember(cx, method_val, field_val);
|
||||
if (!obj) {
|
||||
jsj_ExitJava(jsj_env);
|
||||
jsj_ExitJava(jsj_env);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
|
||||
@@ -648,6 +668,8 @@ JavaObject_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
jsval idval;
|
||||
JNIEnv *jEnv;
|
||||
JSJavaThreadState *jsj_env;
|
||||
JSObject *proto_chain;
|
||||
JSJPropertyInfo prop_info;
|
||||
JSBool result;
|
||||
|
||||
/* printf("In JavaObject_setProperty\n"); */
|
||||
@@ -657,27 +679,32 @@ JavaObject_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
if (!jEnv)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member_descriptor, NULL)) {
|
||||
jsj_ExitJava(jsj_env);
|
||||
if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member_descriptor, NULL,
|
||||
&proto_chain, &prop_info)) {
|
||||
jsj_ExitJava(jsj_env);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Could be assignment to magic JS __proto__ property rather than a Java field */
|
||||
if (!member_descriptor) {
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
if (!JSVAL_IS_STRING(idval))
|
||||
goto no_such_field;
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
if (strcmp(member_name, "__proto__"))
|
||||
goto no_such_field;
|
||||
if (!JSVAL_IS_OBJECT(*vp)) {
|
||||
JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL,
|
||||
JSJMSG_BAD_PROTO_ASSIGNMENT);
|
||||
jsj_ExitJava(jsj_env);
|
||||
return JS_FALSE;
|
||||
if (proto_chain && (prop_info.attributes & JSPROP_SHARED)) {
|
||||
JS_SetProperty(cx, proto_chain, prop_info.name, vp);
|
||||
} else {
|
||||
JS_IdToValue(cx, id, &idval);
|
||||
if (!JSVAL_IS_STRING(idval))
|
||||
goto no_such_field;
|
||||
member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
|
||||
if (strcmp(member_name, "__proto__"))
|
||||
goto no_such_field;
|
||||
if (!JSVAL_IS_OBJECT(*vp)) {
|
||||
JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL,
|
||||
JSJMSG_BAD_PROTO_ASSIGNMENT);
|
||||
jsj_ExitJava(jsj_env);
|
||||
return JS_FALSE;
|
||||
}
|
||||
JS_SetPrototype(cx, obj, JSVAL_TO_OBJECT(*vp));
|
||||
}
|
||||
JS_SetPrototype(cx, obj, JSVAL_TO_OBJECT(*vp));
|
||||
jsj_ExitJava(jsj_env);
|
||||
jsj_ExitJava(jsj_env);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@@ -688,7 +715,7 @@ JavaObject_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
|
||||
/* Silently fail if field value is final (immutable), as required by ECMA spec */
|
||||
if (member_descriptor->field->modifiers & ACC_FINAL) {
|
||||
jsj_ExitJava(jsj_env);
|
||||
jsj_ExitJava(jsj_env);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@@ -719,6 +746,8 @@ JavaObject_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
JNIEnv *jEnv;
|
||||
JSErrorReporter old_reporter;
|
||||
jsval dummy_val;
|
||||
JSObject *proto_chain;
|
||||
JSJPropertyInfo prop_info;
|
||||
JSJavaThreadState *jsj_env;
|
||||
|
||||
/* printf("In JavaObject_lookupProperty()\n"); */
|
||||
@@ -729,12 +758,10 @@ JavaObject_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||
return JS_FALSE;
|
||||
|
||||
old_reporter = JS_SetErrorReporter(cx, NULL);
|
||||
if (lookup_member_by_id(cx, jEnv, obj, NULL, id, NULL, &dummy_val)) {
|
||||
/* TODO - objp may not be set correctly if a property is found, not in
|
||||
obj, but somewhere in obj's proto chain. However, there is
|
||||
no exported JS API to discover which object a property is defined
|
||||
in. */
|
||||
*objp = obj;
|
||||
if (lookup_member_by_id(cx, jEnv, obj, NULL, id, NULL, &dummy_val,
|
||||
&proto_chain, &prop_info)) {
|
||||
/* signify that the property is in the prototype chain or the object itself. */
|
||||
*objp = (proto_chain ? proto_chain : obj);
|
||||
*propp = (JSProperty*)1;
|
||||
} else {
|
||||
*objp = NULL;
|
||||
@@ -762,7 +789,7 @@ JavaObject_getAttributes(JSContext *cx, JSObject *obj, jsid id,
|
||||
{
|
||||
/* We don't maintain JS property attributes for Java class members */
|
||||
*attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE;
|
||||
return JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
@@ -837,7 +864,7 @@ JavaObject_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
*statep = PRIVATE_TO_JSVAL(member_descriptor);
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(class_descriptor->num_instance_members);
|
||||
jsj_ExitJava(jsj_env);
|
||||
jsj_ExitJava(jsj_env);
|
||||
return JS_TRUE;
|
||||
|
||||
case JSENUMERATE_NEXT:
|
||||
|
||||
Reference in New Issue
Block a user