event_capturer_route_event(JSContext *cx, JSObject *obj, uint argc, jsval *argv, jsval *rval) { JSObject *eventObj; JSEvent *event; if (argc != 1) return JS_TRUE; if (!JSVAL_IS_OBJECT(argv[0]) && !JS_ConvertValue(cx, argv[0], JSTYPE_OBJECT, &argv[0])) return JS_FALSE; eventObj = JSVAL_TO_OBJECT(argv[0]); if (!(event = JS_GetInstancePrivate (cx, eventObj, &lm_event_class, argv))) return JS_FALSE; /* Routing objects to themselves causes infinite recursion. * And that's a big no-no. */ if (event->object == obj) return JS_TRUE; if (!event->object || !event->decoder || !event->decoder->window_context) return JS_TRUE; return lm_FindEventHandler(event->decoder->window_context, event->object, eventObj, JSVAL_NULL, rval); }
MAPID valueMap::addFunction(JS::HandleValue val) { JS::RootedValue ns(g_cx); if (!JS_ConvertValue(g_cx, val, JSTYPE_FUNCTION, &ns)) return 0; return add(ns, 8); }
loc_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { const char *url_string; JSString *str; jsval val; jsint slot; JSURL *url; if (!JSVAL_IS_INT(id)) return JS_TRUE; slot = JSVAL_TO_INT(id); /* Setting these properties should not cause a FE_GetURL. */ if (slot < 0 || slot == URL_TARGET) return url_setProperty(cx, obj, id, vp); /* Make sure vp is a string. */ if (!JSVAL_IS_STRING(*vp) && !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp)) { return JS_FALSE; } /* Two cases: setting href vs. setting a component property. */ if (slot == URL_HREF || slot == URL_PROTOCOL) { /* Make sure the URL is absolute and sanity-check its protocol. */ url_string = JS_GetStringBytes(JSVAL_TO_STRING(*vp)); url_string = lm_CheckURL(cx, url_string, JS_TRUE); if (!url_string) return JS_FALSE; str = JS_NewStringCopyZ(cx, url_string); XP_FREE((char *)url_string); if (!str) return JS_FALSE; val = STRING_TO_JSVAL(str); vp = &val; } else { /* Get href from session history before setting a piece of it. */ if (!loc_getProperty(cx, obj, INT_TO_JSVAL(URL_HREF), &val)) return JS_FALSE; } /* Set slot's property. */ if (!url_setProperty(cx, obj, id, vp)) return JS_FALSE; url = JS_GetPrivate(cx, obj); if (!url) return JS_TRUE; if (url->href) url_string = JS_GetStringBytes(url->href); else url_string = ""; return url_load(cx, obj, url_string, NET_DONT_RELOAD); }
event_receiver_handle_event(JSContext *cx, JSObject *obj, uint argc, jsval *argv, jsval *rval) { JSObject *eventObj; if (argc != 1) return JS_TRUE; if (!JSVAL_IS_OBJECT(argv[0]) && !JS_ConvertValue(cx, argv[0], JSTYPE_OBJECT, &argv[0])) return JS_FALSE; eventObj = JSVAL_TO_OBJECT(argv[0]); if (!JS_InstanceOf(cx, eventObj, &lm_event_class, argv)) return JS_FALSE; return lm_HandleEvent(cx, obj, eventObj, JSVAL_NULL, rval); }
/* * 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; }
url_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { JSURL *url; const char *href, *name, *checked_href; char *new_href, *prop_name; JSBool free_href; jsval tmp; JSString *str; MWContext *context; LO_AnchorData *anchor_data; JSBool ok; jsint slot; url = JS_GetInstancePrivate(cx, obj, &lm_url_class, NULL); if (!url) { url = JS_GetInstancePrivate(cx, obj, &lm_location_class, NULL); if (!url) return JS_TRUE; } /* If the property is setting an event handler we find out now so * that we can tell the front end to send the event. */ if (JSVAL_IS_STRING(id)) { prop_name = JS_GetStringBytes(JSVAL_TO_STRING(id)); if (XP_STRCASECMP(prop_name, lm_onClick_str) == 0 || XP_STRCASECMP(prop_name, lm_onMouseDown_str) == 0 || XP_STRCASECMP(prop_name, lm_onMouseOver_str) == 0 || XP_STRCASECMP(prop_name, lm_onMouseOut_str) == 0 || XP_STRCASECMP(prop_name, lm_onMouseUp_str) == 0) { context = url->url_decoder->window_context; if (context) { anchor_data = LO_GetLinkByIndex(context, url->layer_id, url->index); if (anchor_data) anchor_data->event_handler_present = TRUE; } } return JS_TRUE; } XP_ASSERT(JSVAL_IS_INT(id)); slot = JSVAL_TO_INT(id); if (slot < 0) { /* Don't mess with user-defined or method properties. */ return JS_TRUE; } if (!JSVAL_IS_STRING(*vp) && !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp)) { return JS_FALSE; } ok = JS_TRUE; switch (slot) { case URL_HREF: url->href = JSVAL_TO_STRING(*vp); href = JS_GetStringBytes(url->href); free_href = JS_FALSE; break; case URL_PROTOCOL: case URL_HOST: case URL_HOSTNAME: case URL_PORT: case URL_PATHNAME: case URL_HASH: case URL_SEARCH: /* a component property changed -- recompute href. */ new_href = NULL; #define GET_SLOT(aslot, ptmp) { \ if (aslot == slot) { \ *(ptmp) = *vp; \ } else { \ if (!JS_GetElement(cx, obj, aslot, ptmp)) { \ if (new_href) XP_FREE(new_href); \ return JS_FALSE; \ } \ } \ } #define ADD_SLOT(aslot, separator) { \ GET_SLOT(aslot, &tmp); \ name = JS_GetStringBytes(JSVAL_TO_STRING(tmp)); \ if (*name) { \ if (separator) StrAllocCat(new_href, separator); \ StrAllocCat(new_href, name); \ } \ } GET_SLOT(URL_PROTOCOL, &tmp); StrAllocCopy(new_href, JS_GetStringBytes(JSVAL_TO_STRING(tmp))); if (slot == URL_HOST) { ADD_SLOT(URL_HOST, "//"); } else { ADD_SLOT(URL_HOSTNAME, "//"); ADD_SLOT(URL_PORT, ":"); } ADD_SLOT(URL_PATHNAME, NULL); ADD_SLOT(URL_HASH, NULL); ADD_SLOT(URL_SEARCH, NULL); if (!new_href) { JS_ReportOutOfMemory(cx); return JS_FALSE; } free_href = JS_TRUE; href = new_href; str = JS_NewStringCopyZ(cx, href); if (!str) { ok = JS_FALSE; goto out; } url->href = str; break; case URL_TARGET: url->target = JSVAL_TO_STRING(*vp); if (url->index != URL_NOT_INDEXED) { context = url->url_decoder->window_context; if (context) { anchor_data = LO_GetLinkByIndex(context, url->layer_id, url->index); if (anchor_data) { name = JS_GetStringBytes(url->target); if (!lm_CheckWindowName(cx, name)) return JS_FALSE; if (!lm_SaveParamString(cx, &anchor_data->target, name)) return JS_FALSE; } } } /* Note early return, to bypass href update and freeing. */ return JS_TRUE; default: /* Don't mess with a user-defined property. */ return ok; } if (url->index != URL_NOT_INDEXED) { context = url->url_decoder->window_context; if (context) { anchor_data = LO_GetLinkByIndex(context, url->layer_id, url->index); if (anchor_data) { checked_href = lm_CheckURL(cx, href, JS_FALSE); if (!checked_href || !lm_SaveParamString(cx, &anchor_data->anchor, checked_href)) { ok = JS_FALSE; goto out; } XP_FREE((char *)checked_href); } } } out: if (free_href && href) XP_FREE((char *)href); return ok; }