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

📄 jsj_method.c

📁 caffeine-monkey java实现的js模拟引擎
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -