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

📄 javaadapter.java

📁 這是一個javascript 的 interpreter是了解 web browser的好材料
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
            // Create a string of length 1 using the character parameter.            cfw.add(ByteCode.ILOAD, paramOffset);            cfw.addInvoke(ByteCode.INVOKESTATIC, "java/lang/String",                          "valueOf", "(C)Ljava/lang/String;");        } else {            // convert all numeric values to java.lang.Double.            cfw.add(ByteCode.NEW, "java/lang/Double");            cfw.add(ByteCode.DUP);            String typeName = argType.getName();            switch (typeName.charAt(0)) {            case 'b':            case 's':            case 'i':                // load an int value, convert to double.                cfw.add(ByteCode.ILOAD, paramOffset);                cfw.add(ByteCode.I2D);                break;            case 'l':                // load a long, convert to double.                cfw.add(ByteCode.LLOAD, paramOffset);                cfw.add(ByteCode.L2D);                size = 2;                break;            case 'f':                // load a float, convert to double.                cfw.add(ByteCode.FLOAD, paramOffset);                cfw.add(ByteCode.F2D);                break;            case 'd':                cfw.add(ByteCode.DLOAD, paramOffset);                size = 2;                break;            }            cfw.addInvoke(ByteCode.INVOKESPECIAL, "java/lang/Double",                          "<init>", "(D)V");        }        return size;    }    /**     * Generates code to convert a wrapped value type to a primitive type.     * Handles unwrapping java.lang.Boolean, and java.lang.Number types.     * Generates the appropriate RETURN bytecode.     */    static void generateReturnResult(ClassFileWriter cfw, Class retType,                                     boolean callConvertResult)    {        // wrap boolean values with java.lang.Boolean, convert all other        // primitive values to java.lang.Double.        if (retType == Void.TYPE) {            cfw.add(ByteCode.POP);            cfw.add(ByteCode.RETURN);        } else if (retType == Boolean.TYPE) {            cfw.addInvoke(ByteCode.INVOKESTATIC,                          "org/mozilla/javascript/Context",                          "toBoolean", "(Ljava/lang/Object;)Z");            cfw.add(ByteCode.IRETURN);        } else if (retType == Character.TYPE) {            // characters are represented as strings in JavaScript.            // return the first character.            // first convert the value to a string if possible.            cfw.addInvoke(ByteCode.INVOKESTATIC,                          "org/mozilla/javascript/Context",                          "toString",                          "(Ljava/lang/Object;)Ljava/lang/String;");            cfw.add(ByteCode.ICONST_0);            cfw.addInvoke(ByteCode.INVOKEVIRTUAL, "java/lang/String",                          "charAt", "(I)C");            cfw.add(ByteCode.IRETURN);        } else if (retType.isPrimitive()) {            cfw.addInvoke(ByteCode.INVOKESTATIC,                          "org/mozilla/javascript/Context",                          "toNumber", "(Ljava/lang/Object;)D");            String typeName = retType.getName();            switch (typeName.charAt(0)) {            case 'b':            case 's':            case 'i':                cfw.add(ByteCode.D2I);                cfw.add(ByteCode.IRETURN);                break;            case 'l':                cfw.add(ByteCode.D2L);                cfw.add(ByteCode.LRETURN);                break;            case 'f':                cfw.add(ByteCode.D2F);                cfw.add(ByteCode.FRETURN);                break;            case 'd':                cfw.add(ByteCode.DRETURN);                break;            default:                throw new RuntimeException("Unexpected return type " +                                           retType.toString());            }        } else {            String retTypeStr = retType.getName();            if (callConvertResult) {                cfw.addLoadConstant(retTypeStr);                cfw.addInvoke(ByteCode.INVOKESTATIC,                              "java/lang/Class",                              "forName",                              "(Ljava/lang/String;)Ljava/lang/Class;");                cfw.addInvoke(ByteCode.INVOKESTATIC,                              "org/mozilla/javascript/JavaAdapter",                              "convertResult",                              "(Ljava/lang/Object;"                              +"Ljava/lang/Class;"                              +")Ljava/lang/Object;");            }            // Now cast to return type            cfw.add(ByteCode.CHECKCAST, retTypeStr);            cfw.add(ByteCode.ARETURN);        }    }    private static void generateMethod(ClassFileWriter cfw, String genName,                                       String methodName, Class[] parms,                                       Class returnType)    {        StringBuffer sb = new StringBuffer();        int paramsEnd = appendMethodSignature(parms, returnType, sb);        String methodSignature = sb.toString();        cfw.startMethod(methodName, methodSignature,                        ClassFileWriter.ACC_PUBLIC);        // Prepare stack to call method        // push factory        cfw.add(ByteCode.ALOAD_0);        cfw.add(ByteCode.GETFIELD, genName, "factory",                "Lorg/mozilla/javascript/ContextFactory;");        // push self        cfw.add(ByteCode.ALOAD_0);        cfw.add(ByteCode.GETFIELD, genName, "self",                "Lorg/mozilla/javascript/Scriptable;");        // push function        cfw.add(ByteCode.ALOAD_0);        cfw.add(ByteCode.GETFIELD, genName, "delegee",                "Lorg/mozilla/javascript/Scriptable;");        cfw.addPush(methodName);        cfw.addInvoke(ByteCode.INVOKESTATIC,                      "org/mozilla/javascript/JavaAdapter",                      "getFunction",                      "(Lorg/mozilla/javascript/Scriptable;"                      +"Ljava/lang/String;"                      +")Lorg/mozilla/javascript/Function;");        // push arguments        generatePushWrappedArgs(cfw, parms, parms.length);        // push bits to indicate which parameters should be wrapped        if (parms.length > 64) {            // If it will be an issue, then passing a static boolean array            // can be an option, but for now using simple bitmask            throw Context.reportRuntimeError0(                "JavaAdapter can not subclass methods with more then"                +" 64 arguments.");        }        long convertionMask = 0;        for (int i = 0; i != parms.length; ++i) {            if (!parms[i].isPrimitive()) {                convertionMask |= (1 << i);            }        }        cfw.addPush(convertionMask);        // go through utility method, which creates a Context to run the        // method in.        cfw.addInvoke(ByteCode.INVOKESTATIC,                      "org/mozilla/javascript/JavaAdapter",                      "callMethod",                      "(Lorg/mozilla/javascript/ContextFactory;"                      +"Lorg/mozilla/javascript/Scriptable;"                      +"Lorg/mozilla/javascript/Function;"                      +"[Ljava/lang/Object;"                      +"J"                      +")Ljava/lang/Object;");        generateReturnResult(cfw, returnType, true);        cfw.stopMethod((short)paramsEnd);    }    /**     * Generates code to push typed parameters onto the operand stack     * prior to a direct Java method call.     */    private static int generatePushParam(ClassFileWriter cfw, int paramOffset,                                         Class paramType)    {        if (!paramType.isPrimitive()) {            cfw.addALoad(paramOffset);            return 1;        }        String typeName = paramType.getName();        switch (typeName.charAt(0)) {        case 'z':        case 'b':        case 'c':        case 's':        case 'i':            // load an int value, convert to double.            cfw.addILoad(paramOffset);            return 1;        case 'l':            // load a long, convert to double.            cfw.addLLoad(paramOffset);            return 2;        case 'f':            // load a float, convert to double.            cfw.addFLoad(paramOffset);            return 1;        case 'd':            cfw.addDLoad(paramOffset);            return 2;        }        throw Kit.codeBug();    }    /**     * Generates code to return a Java type, after calling a Java method     * that returns the same type.     * Generates the appropriate RETURN bytecode.     */    private static void generatePopResult(ClassFileWriter cfw,                                          Class retType)    {        if (retType.isPrimitive()) {            String typeName = retType.getName();            switch (typeName.charAt(0)) {            case 'b':            case 'c':            case 's':            case 'i':            case 'z':                cfw.add(ByteCode.IRETURN);                break;            case 'l':                cfw.add(ByteCode.LRETURN);                break;            case 'f':                cfw.add(ByteCode.FRETURN);                break;            case 'd':                cfw.add(ByteCode.DRETURN);                break;            }        } else {            cfw.add(ByteCode.ARETURN);        }    }    /**     * Generates a method called "super$methodName()" which can be called     * from JavaScript that is equivalent to calling "super.methodName()"     * from Java. Eventually, this may be supported directly in JavaScript.     */    private static void generateSuper(ClassFileWriter cfw,                                      String genName, String superName,                                      String methodName, String methodSignature,                                      Class[] parms, Class returnType)    {        cfw.startMethod("super$" + methodName, methodSignature,                        ClassFileWriter.ACC_PUBLIC);        // push "this"        cfw.add(ByteCode.ALOAD, 0);        // push the rest of the parameters.        int paramOffset = 1;        for (int i = 0; i < parms.length; i++) {            paramOffset += generatePushParam(cfw, paramOffset, parms[i]);        }        // call the superclass implementation of the method.        cfw.addInvoke(ByteCode.INVOKESPECIAL,                      superName,                      methodName,                      methodSignature);        // now, handle the return type appropriately.        Class retType = returnType;        if (!retType.equals(Void.TYPE)) {            generatePopResult(cfw, retType);        } else {            cfw.add(ByteCode.RETURN);        }        cfw.stopMethod((short)(paramOffset + 1));    }    /**     * Returns a fully qualified method name concatenated with its signature.     */    private static String getMethodSignature(Method method, Class[] argTypes)    {        StringBuffer sb = new StringBuffer();        appendMethodSignature(argTypes, method.getReturnType(), sb);        return sb.toString();    }    static int appendMethodSignature(Class[] argTypes,                                     Class returnType,                                     StringBuffer sb)    {        sb.append('(');        int firstLocal = 1 + argTypes.length; // includes this.        for (int i = 0; i < argTypes.length; i++) {            Class type = argTypes[i];            appendTypeString(sb, type);            if (type == Long.TYPE || type == Double.TYPE) {                // adjust for duble slot                ++firstLocal;            }        }        sb.append(')');        appendTypeString(sb, returnType);        return firstLocal;    }    private static StringBuffer appendTypeString(StringBuffer sb, Class type)    {        while (type.isArray()) {            sb.append('[');            type = type.getComponentType();        }        if (type.isPrimitive()) {            char typeLetter;            if (type == Boolean.TYPE) {                typeLetter = 'Z';            } else if (type == Long.TYPE) {                typeLetter = 'J';            } else {                String typeName = type.getName();                typeLetter = Character.toUpperCase(typeName.charAt(0));            }            sb.append(typeLetter);        } else {            sb.append('L');            sb.append(type.getName().replace('.', '/'));            sb.append(';');        }        return sb;    }    static int[] getArgsToConvert(Class[] argTypes)    {        int count = 0;        for (int i = 0; i != argTypes.length; ++i) {            if (!argTypes[i].isPrimitive())                ++count;        }        if (count == 0)            return null;        int[] array = new int[count];        count = 0;        for (int i = 0; i != argTypes.length; ++i) {            if (!argTypes[i].isPrimitive())                array[count++] = i;        }        return array;    }    private static final Object FTAG = new Object();    private static final int Id_JavaAdapter = 1;}

⌨️ 快捷键说明

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