📄 jsj_method.c
字号:
return member_descriptor; /* * To speed up performance for future accesses, create a new member descriptor * with a name equal to the explicit method name, i.e. "cos(double)". */ member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor)); if (!member_descriptor) return NULL; memset(member_descriptor, 0, sizeof(JavaMemberDescriptor)); member_descriptor->id = method_name_id; member_descriptor->name = JS_strdup(cx, is_constructor ? "<init>" : JS_GetStringBytes(simple_name_jsstr)); if (!member_descriptor->name) { JS_free(cx, member_descriptor); return NULL; } member_descriptor->methods = copy_java_method_descriptor(cx, method); if (!member_descriptor->methods) { JS_free(cx, (void*)member_descriptor->name); JS_free(cx, member_descriptor); return NULL; } fun = JS_NewFunction(cx, jsj_JavaInstanceMethodWrapper, 0, JSFUN_BOUND_METHOD, NULL, method_name); member_descriptor->invoke_func_obj = JS_GetFunctionObject(fun); JS_AddNamedRoot(cx, &member_descriptor->invoke_func_obj, "&member_descriptor->invoke_func_obj"); /* THREADSAFETY */ /* Add the new aliased member to the list of all members for the class */ if (is_static) { member_descriptor->next = class_descriptor->static_members; class_descriptor->static_members = member_descriptor; } else { member_descriptor->next = class_descriptor->instance_members; class_descriptor->instance_members = member_descriptor; } return member_descriptor;}/* * Return the JavaScript types that a JavaScript method was invoked with * as a string, e.g. a JS method invoked like foo(3, 'hey', 'you', true) * would cause a return value of "(number, string, string, boolean)". * The returned string must be free'ed by the caller. * Returns NULL and reports an error if out-of-memory. */static const char *get_js_arg_types_as_string(JSContext *cx, uintN argc, jsval *argv){ uintN i; const char *arg_type, *arg_string, *tmp; if (argc == 0) return strdup("()"); arg_string = strdup("("); if (!arg_string) goto out_of_memory; for (i = 0; i < argc; i++) { arg_type = JS_GetTypeName(cx, JS_TypeOfValue(cx, argv[i])); tmp = JS_smprintf("%s%s%s%s", arg_string, i ? ", " : "", arg_type, (i == argc-1) ? ")" : ""); free((char*)arg_string); if (!tmp) goto out_of_memory; arg_string = tmp; } return arg_string;out_of_memory: JS_ReportOutOfMemory(cx); return NULL;}/* * This is an error reporting routine used when a method of the correct name * and class exists but either the number of arguments is incorrect or the * arguments are of the wrong type. */static voidreport_method_match_failure(JSContext *cx, JavaMemberDescriptor *member_descriptor, JavaClassDescriptor *class_descriptor, JSBool is_static_method, uintN argc, jsval *argv){ const char *err, *js_arg_string, *tmp, *method_str, *method_name; JSBool is_constructor; JavaMethodSpec *method; err = NULL; is_constructor = (!strcmp(member_descriptor->name, "<init>")); js_arg_string = get_js_arg_types_as_string(cx, argc, argv); if (!js_arg_string) goto out_of_memory; if (is_constructor) { err = JS_smprintf("There is no Java constructor for class %s that matches " "JavaScript argument types %s.\n", class_descriptor->name, js_arg_string); method_name = class_descriptor->name; } else { err = JS_smprintf("There is no %sJava method %s.%s that matches " "JavaScript argument types %s.\n", is_static_method ? "static ": "", class_descriptor->name, member_descriptor->name, js_arg_string); method_name = member_descriptor->name; } if (!err) goto out_of_memory; tmp = JS_smprintf("%sCandidate methods with the same name are:\n", err); if (!tmp) goto out_of_memory; err = tmp; method = member_descriptor->methods; while (method) { method_str = jsj_ConvertJavaMethodSignatureToHRString(cx, method_name, &method->signature); if (!method_str) goto out_of_memory; tmp = JS_smprintf("%s %s\n", err, method_str); free((char*)method_str); if (!tmp) goto out_of_memory; err = tmp; method = method->next; } JS_ReportError(cx, err); return;out_of_memory: if (js_arg_string) free((char*)js_arg_string); if (err) free((char*)err);}/* * This is an error reporting routine used when a method of the correct name * and class exists but more than one Java method in a set of overloaded * methods are compatible with the JavaScript argument types and none of them * match any better than all the others. */static voidreport_ambiguous_method_match(JSContext *cx, JavaMemberDescriptor *member_descriptor, JavaClassDescriptor *class_descriptor, MethodList *ambiguous_methods, JSBool is_static_method, uintN argc, jsval *argv){ const char *err, *js_arg_string, *tmp, *method_str, *method_name; JSBool is_constructor; JavaMethodSpec *method; MethodListElement *method_list_element; err = NULL; is_constructor = (!strcmp(member_descriptor->name, "<init>")); js_arg_string = get_js_arg_types_as_string(cx, argc, argv); if (!js_arg_string) goto out_of_memory; if (is_constructor) { err = JS_smprintf("The choice of Java constructor for class %s with " "JavaScript argument types %s is ambiguous.\n", class_descriptor->name, js_arg_string); method_name = class_descriptor->name; } else { err = JS_smprintf("The choice of %sJava method %s.%s matching " "JavaScript argument types %s is ambiguous.\n", is_static_method ? "static ": "", class_descriptor->name, member_descriptor->name, js_arg_string); method_name = member_descriptor->name; } if (!err) goto out_of_memory; tmp = JS_smprintf("%sCandidate methods are:\n", err); if (!tmp) goto out_of_memory; err = tmp; method_list_element = (MethodListElement*)JS_LIST_HEAD(ambiguous_methods); while ((MethodList*)method_list_element != ambiguous_methods) { method = method_list_element->method; method_str = jsj_ConvertJavaMethodSignatureToHRString(cx, method_name, &method->signature); if (!method_str) goto out_of_memory; tmp = JS_smprintf("%s %s\n", err, method_str); free((char*)method_str); if (!tmp) goto out_of_memory; err = tmp; method_list_element = (MethodListElement*)method_list_element->linkage.next; } JS_ReportError(cx, err); return;out_of_memory: if (js_arg_string) free((char*)js_arg_string); if (err) free((char*)err);}/* * Compute classification of JS types with slightly different granularity * than JSType. This is used to resolve among overloaded Java methods. */static JSJTypecompute_jsj_type(JSContext *cx, jsval v){ JSObject *js_obj; if (JSVAL_IS_OBJECT(v)) { if (JSVAL_IS_NULL(v)) return JSJTYPE_NULL; js_obj = JSVAL_TO_OBJECT(v); if (JS_InstanceOf(cx, js_obj, &JavaObject_class, 0)) return JSJTYPE_JAVAOBJECT; if (JS_InstanceOf(cx, js_obj, &JavaArray_class, 0)) return JSJTYPE_JAVAARRAY; if (JS_InstanceOf(cx, js_obj, &JavaClass_class, 0)) return JSJTYPE_JAVACLASS; if (JS_IsArrayObject(cx, js_obj)) return JSJTYPE_JSARRAY; return JSJTYPE_OBJECT; } else if (JSVAL_IS_NUMBER(v)) { return JSJTYPE_NUMBER; } else if (JSVAL_IS_STRING(v)) { return JSJTYPE_STRING; } else if (JSVAL_IS_BOOLEAN(v)) { return JSJTYPE_BOOLEAN; } else if (JSVAL_IS_VOID(v)) { return JSJTYPE_VOID; } JS_ASSERT(0); /* Unknown JS type ! */ return JSJTYPE_VOID;}/* * Ranking table used to establish preferences among Java types when converting * from JavaScript types. Each row represents a different JavaScript source * type and each column represents a different target Java type. Lower values * in the table indicate conversions that are ranked higher. The special * value 99 indicates a disallowed JS->Java conversion. The special value of * 0 indicates special handling is required to determine ranking. */static int rank_table[JSJTYPE_LIMIT][JAVA_SIGNATURE_LIMIT] = {/* boolean long | char | float java.lang.Boolean | | byte | | double | java.lang.Class | | | short | | | array | | java.lang.Double | | | | int | | | | object | | netscape.javascript.JSObject | | | | | | | | | | | | | | java.lang.Object | | | | | | | | | | | | | | | java.lang.String */ {99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 1, 1}, /* undefined */ { 1, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 99, 99, 99, 3, 4}, /* boolean */ {99, 7, 8, 6, 5, 4, 3, 1, 99, 99, 99, 99, 2, 99, 11, 9}, /* number */ {99, 3, 4, 4, 4, 4, 4, 4, 99, 99, 99, 99, 99, 99, 2, 1}, /* string */ {99, 99, 99, 99, 99, 99, 99, 99, 1, 1, 1, 1, 1, 1, 1, 1}, /* null */ {99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 1, 99, 2, 3, 4}, /* JavaClass */ {99, 7, 8, 6, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1}, /* JavaObject */ {99, 99, 99, 99, 99, 99, 99, 99, 0, 0, 99, 99, 99, 99, 0, 1}, /* JavaArray */ {99, 99, 99, 99, 99, 99, 99, 99, 2, 99, 99, 99, 99, 1, 3, 4}, /* JS Array */ {99, 9, 10, 8, 7, 6, 5, 4, 99, 99, 99, 99, 99, 1, 2, 3} /* other JS object */};/* * Returns JS_TRUE if JavaScript arguments are compatible with the specified * Java method signature. */static JSBoolmethod_signature_matches_JS_args(JSContext *cx, JNIEnv *jEnv, uintN argc, jsval *argv, JavaMethodSignature *method_signature){ uintN i; JavaClassDescriptor *descriptor; JavaObjectWrapper *java_wrapper; jclass java_class; jobject java_obj; JSObject *js_obj; JSJType js_type; jsval js_val; int rank; if (argc != (uintN)method_signature->num_args) return JS_FALSE; for (i = 0; i < argc; i++) { js_val = argv[i]; js_type = compute_jsj_type(cx, js_val); descriptor = method_signature->arg_signatures[i]; rank = rank_table[js_type][(int)descriptor->type - 2]; /* Check for disallowed JS->Java conversion */ if (rank == 99) return JS_FALSE; /* Check for special handling required by conversion from JavaObject */ if (rank == 0) { java_class = descriptor->java_class; js_obj = JSVAL_TO_OBJECT(js_val); java_wrapper = JS_GetPrivate(cx, js_obj); java_obj = java_wrapper->java_obj; if (!(*jEnv)->IsInstanceOf(jEnv, java_obj, java_class)) return JS_FALSE; } } return JS_TRUE;}#ifdef HAS_OLD_STYLE_METHOD_RESOLUTIONstatic JavaMethodSpec *resolve_overloaded_method(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor, JavaClassDescriptor *class_descriptor, JSBool is_static_method, uintN argc, jsval *argv){ int cost, lowest_cost, num_method_matches; JavaMethodSpec *best_method_match, *method; num_method_matches = 0; lowest_cost = 10000; best_method_match = NULL; for (method = member_descriptor->methods; method; method = method->next) { cost = 0; if (!method_signature_matches_JS_args(cx, jEnv, argc, argv, &method->signature, &cost)) continue; if (cost < lowest_cost) { lowest_cost = cost; best_method_match = method; num_method_matches++; } } if (!best_method_match) report_method_match_failure(cx, member_descriptor, class_descriptor, is_static_method, argc, argv);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -