diff options
Diffstat (limited to 'trunk/infrastructure/rhino1_7R1/src')
121 files changed, 0 insertions, 64541 deletions
diff --git a/trunk/infrastructure/rhino1_7R1/src/build.xml b/trunk/infrastructure/rhino1_7R1/src/build.xml deleted file mode 100644 index a0a1e13..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/build.xml +++ /dev/null @@ -1,98 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- ***** BEGIN LICENSE BLOCK ***** - - Version: MPL 1.1/GPL 2.0 - - - - The contents of this file are subject to the Mozilla Public License Version - - 1.1 (the "License"); you may not use this file except in compliance with - - the License. You may obtain a copy of the License at - - http://www.mozilla.org/MPL/ - - - - Software distributed under the License is distributed on an "AS IS" basis, - - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - - for the specific language governing rights and limitations under the - - License. - - - - The Original Code is Rhino code, released May 6, 1999. - - - - The Initial Developer of the Original Code is - - Netscape Communications Corporation. - - Portions created by the Initial Developer are Copyright (C) 1997-1999 - - the Initial Developer. All Rights Reserved. - - - - Contributor(s): - - - - Alternatively, the contents of this file may be used under the terms of - - the GNU General Public License Version 2 or later (the "GPL"), in which - - case the provisions of the GPL are applicable instead of those above. If - - you wish to allow use of your version of this file only under the terms of - - the GPL and not to allow others to use your version of this file under the - - MPL, indicate your decision by deleting the provisions above and replacing - - them with the notice and other provisions required by the GPL. If you do - - not delete the provisions above, a recipient may use your version of this - - file under either the MPL or the GPL. - - - - ***** END LICENSE BLOCK ***** --> - - -<!-- -Build file for Rhino using Ant (see http://jakarta.apache.org/ant/index.html) -Requires Ant version 1.2 ---> -<project name="src" default="compile" basedir=".."> - - <property file="build.properties"/> - - <available property="jdk15" - classname="java.lang.reflect.ParameterizedType" /> - - <target name="compile" depends="compile-most,compile-jdk15"> - </target> - - <target name="compile-most"> - <javac srcdir="src" - destdir="${classes}" - includes="org/**/*.java" - excludes="org/**/jdk15/*.java" - deprecation="on" - debug="${debug}" - target="${target-jvm}" - source="${source-level}" - > - </javac> - <copy todir="${classes}"> - <fileset dir="src" includes="org/**/*.properties" /> - <filterset> - <filter token="IMPLEMENTATION.VERSION" - value="${implementation.version}"/> - </filterset> - </copy> - </target> - - <target name="compile-jdk15" if="jdk15"> - <javac srcdir="src" - destdir="${classes}" - includes="org/**/jdk15/*.java" - deprecation="on" - debug="${debug}" - target="${target-jvm}" - source="${source-level}" - > - </javac> - </target> - - <target name="copy-source"> - <mkdir dir="${dist.dir}/src"/> - <copy todir="${dist.dir}/src"> - <fileset dir="src" - includes="**/*.java,**/*.properties,**/*.xml,manifest"/> - </copy> - </target> - - <target name="clean"> - <delete includeEmptyDirs="true"> - <fileset dir="${classes}" - excludes="org/mozilla/javascript/tools/**"/> - </delete> - </target> - -</project> diff --git a/trunk/infrastructure/rhino1_7R1/src/manifest b/trunk/infrastructure/rhino1_7R1/src/manifest deleted file mode 100644 index b7d0c06..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/manifest +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Main-Class: org.mozilla.javascript.tools.shell.Main -Class-Path: xbean.jar diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/classfile/ByteCode.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/classfile/ByteCode.java deleted file mode 100644 index fa4713e..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/classfile/ByteCode.java +++ /dev/null @@ -1,274 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.classfile; - -/** - * This class provides opcode values expected by the JVM in Java class files. - * - * It also provides tables for internal use by the ClassFileWriter. - * - * @author Roger Lawrence - */ -public class ByteCode { - - /** - * The byte opcodes defined by the Java Virtual Machine. - */ - public static final int - NOP = 0x00, - ACONST_NULL = 0x01, - ICONST_M1 = 0x02, - ICONST_0 = 0x03, - ICONST_1 = 0x04, - ICONST_2 = 0x05, - ICONST_3 = 0x06, - ICONST_4 = 0x07, - ICONST_5 = 0x08, - LCONST_0 = 0x09, - LCONST_1 = 0x0A, - FCONST_0 = 0x0B, - FCONST_1 = 0x0C, - FCONST_2 = 0x0D, - DCONST_0 = 0x0E, - DCONST_1 = 0x0F, - BIPUSH = 0x10, - SIPUSH = 0x11, - LDC = 0x12, - LDC_W = 0x13, - LDC2_W = 0x14, - ILOAD = 0x15, - LLOAD = 0x16, - FLOAD = 0x17, - DLOAD = 0x18, - ALOAD = 0x19, - ILOAD_0 = 0x1A, - ILOAD_1 = 0x1B, - ILOAD_2 = 0x1C, - ILOAD_3 = 0x1D, - LLOAD_0 = 0x1E, - LLOAD_1 = 0x1F, - LLOAD_2 = 0x20, - LLOAD_3 = 0x21, - FLOAD_0 = 0x22, - FLOAD_1 = 0x23, - FLOAD_2 = 0x24, - FLOAD_3 = 0x25, - DLOAD_0 = 0x26, - DLOAD_1 = 0x27, - DLOAD_2 = 0x28, - DLOAD_3 = 0x29, - ALOAD_0 = 0x2A, - ALOAD_1 = 0x2B, - ALOAD_2 = 0x2C, - ALOAD_3 = 0x2D, - IALOAD = 0x2E, - LALOAD = 0x2F, - FALOAD = 0x30, - DALOAD = 0x31, - AALOAD = 0x32, - BALOAD = 0x33, - CALOAD = 0x34, - SALOAD = 0x35, - ISTORE = 0x36, - LSTORE = 0x37, - FSTORE = 0x38, - DSTORE = 0x39, - ASTORE = 0x3A, - ISTORE_0 = 0x3B, - ISTORE_1 = 0x3C, - ISTORE_2 = 0x3D, - ISTORE_3 = 0x3E, - LSTORE_0 = 0x3F, - LSTORE_1 = 0x40, - LSTORE_2 = 0x41, - LSTORE_3 = 0x42, - FSTORE_0 = 0x43, - FSTORE_1 = 0x44, - FSTORE_2 = 0x45, - FSTORE_3 = 0x46, - DSTORE_0 = 0x47, - DSTORE_1 = 0x48, - DSTORE_2 = 0x49, - DSTORE_3 = 0x4A, - ASTORE_0 = 0x4B, - ASTORE_1 = 0x4C, - ASTORE_2 = 0x4D, - ASTORE_3 = 0x4E, - IASTORE = 0x4F, - LASTORE = 0x50, - FASTORE = 0x51, - DASTORE = 0x52, - AASTORE = 0x53, - BASTORE = 0x54, - CASTORE = 0x55, - SASTORE = 0x56, - POP = 0x57, - POP2 = 0x58, - DUP = 0x59, - DUP_X1 = 0x5A, - DUP_X2 = 0x5B, - DUP2 = 0x5C, - DUP2_X1 = 0x5D, - DUP2_X2 = 0x5E, - SWAP = 0x5F, - IADD = 0x60, - LADD = 0x61, - FADD = 0x62, - DADD = 0x63, - ISUB = 0x64, - LSUB = 0x65, - FSUB = 0x66, - DSUB = 0x67, - IMUL = 0x68, - LMUL = 0x69, - FMUL = 0x6A, - DMUL = 0x6B, - IDIV = 0x6C, - LDIV = 0x6D, - FDIV = 0x6E, - DDIV = 0x6F, - IREM = 0x70, - LREM = 0x71, - FREM = 0x72, - DREM = 0x73, - INEG = 0x74, - LNEG = 0x75, - FNEG = 0x76, - DNEG = 0x77, - ISHL = 0x78, - LSHL = 0x79, - ISHR = 0x7A, - LSHR = 0x7B, - IUSHR = 0x7C, - LUSHR = 0x7D, - IAND = 0x7E, - LAND = 0x7F, - IOR = 0x80, - LOR = 0x81, - IXOR = 0x82, - LXOR = 0x83, - IINC = 0x84, - I2L = 0x85, - I2F = 0x86, - I2D = 0x87, - L2I = 0x88, - L2F = 0x89, - L2D = 0x8A, - F2I = 0x8B, - F2L = 0x8C, - F2D = 0x8D, - D2I = 0x8E, - D2L = 0x8F, - D2F = 0x90, - I2B = 0x91, - I2C = 0x92, - I2S = 0x93, - LCMP = 0x94, - FCMPL = 0x95, - FCMPG = 0x96, - DCMPL = 0x97, - DCMPG = 0x98, - IFEQ = 0x99, - IFNE = 0x9A, - IFLT = 0x9B, - IFGE = 0x9C, - IFGT = 0x9D, - IFLE = 0x9E, - IF_ICMPEQ = 0x9F, - IF_ICMPNE = 0xA0, - IF_ICMPLT = 0xA1, - IF_ICMPGE = 0xA2, - IF_ICMPGT = 0xA3, - IF_ICMPLE = 0xA4, - IF_ACMPEQ = 0xA5, - IF_ACMPNE = 0xA6, - GOTO = 0xA7, - JSR = 0xA8, - RET = 0xA9, - TABLESWITCH = 0xAA, - LOOKUPSWITCH = 0xAB, - IRETURN = 0xAC, - LRETURN = 0xAD, - FRETURN = 0xAE, - DRETURN = 0xAF, - ARETURN = 0xB0, - RETURN = 0xB1, - GETSTATIC = 0xB2, - PUTSTATIC = 0xB3, - GETFIELD = 0xB4, - PUTFIELD = 0xB5, - INVOKEVIRTUAL = 0xB6, - INVOKESPECIAL = 0xB7, - INVOKESTATIC = 0xB8, - INVOKEINTERFACE = 0xB9, - NEW = 0xBB, - NEWARRAY = 0xBC, - ANEWARRAY = 0xBD, - ARRAYLENGTH = 0xBE, - ATHROW = 0xBF, - CHECKCAST = 0xC0, - INSTANCEOF = 0xC1, - MONITORENTER = 0xC2, - MONITOREXIT = 0xC3, - WIDE = 0xC4, - MULTIANEWARRAY = 0xC5, - IFNULL = 0xC6, - IFNONNULL = 0xC7, - GOTO_W = 0xC8, - JSR_W = 0xC9, - BREAKPOINT = 0xCA, - - IMPDEP1 = 0xFE, - IMPDEP2 = 0xFF; - - /** - * Types for the NEWARRAY opcode. - */ - public static final byte - T_BOOLEAN = 4, - T_CHAR = 5, - T_FLOAT = 6, - T_DOUBLE = 7, - T_BYTE = 8, - T_SHORT = 9, - T_INT = 10, - T_LONG = 11; - - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/classfile/ClassFileWriter.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/classfile/ClassFileWriter.java deleted file mode 100644 index b9c6c96..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/classfile/ClassFileWriter.java +++ /dev/null @@ -1,3038 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.classfile; - -import org.mozilla.javascript.ObjToIntMap; -import org.mozilla.javascript.ObjArray; -import org.mozilla.javascript.UintMap; - -import java.io.*; - -/** - * ClassFileWriter - * - * A ClassFileWriter is used to write a Java class file. Methods are - * provided to create fields and methods, and within methods to write - * Java bytecodes. - * - * @author Roger Lawrence - */ -public class ClassFileWriter { - - /** - * Thrown for cases where the error in generating the class file is - * due to a program size constraints rather than a likely bug in the - * compiler. - */ - public static class ClassFileFormatException extends RuntimeException { - ClassFileFormatException(String message) { - super(message); - } - } - - /** - * Construct a ClassFileWriter for a class. - * - * @param className the name of the class to write, including - * full package qualification. - * @param superClassName the name of the superclass of the class - * to write, including full package qualification. - * @param sourceFileName the name of the source file to use for - * producing debug information, or null if debug information - * is not desired - */ - public ClassFileWriter(String className, String superClassName, - String sourceFileName) - { - generatedClassName = className; - itsConstantPool = new ConstantPool(this); - itsThisClassIndex = itsConstantPool.addClass(className); - itsSuperClassIndex = itsConstantPool.addClass(superClassName); - if (sourceFileName != null) - itsSourceFileNameIndex = itsConstantPool.addUtf8(sourceFileName); - itsFlags = ACC_PUBLIC; - } - - public final String getClassName() - { - return generatedClassName; - } - - /** - * Add an interface implemented by this class. - * - * This method may be called multiple times for classes that - * implement multiple interfaces. - * - * @param interfaceName a name of an interface implemented - * by the class being written, including full package - * qualification. - */ - public void addInterface(String interfaceName) { - short interfaceIndex = itsConstantPool.addClass(interfaceName); - itsInterfaces.add(new Short(interfaceIndex)); - } - - public static final short - ACC_PUBLIC = 0x0001, - ACC_PRIVATE = 0x0002, - ACC_PROTECTED = 0x0004, - ACC_STATIC = 0x0008, - ACC_FINAL = 0x0010, - ACC_SYNCHRONIZED = 0x0020, - ACC_VOLATILE = 0x0040, - ACC_TRANSIENT = 0x0080, - ACC_NATIVE = 0x0100, - ACC_ABSTRACT = 0x0400; - - /** - * Set the class's flags. - * - * Flags must be a set of the following flags, bitwise or'd - * together: - * ACC_PUBLIC - * ACC_PRIVATE - * ACC_PROTECTED - * ACC_FINAL - * ACC_ABSTRACT - * TODO: check that this is the appropriate set - * @param flags the set of class flags to set - */ - public void setFlags(short flags) { - itsFlags = flags; - } - - static String getSlashedForm(String name) - { - return name.replace('.', '/'); - } - - /** - * Convert Java class name in dot notation into - * "Lname-with-dots-replaced-by-slashes;" form suitable for use as - * JVM type signatures. - */ - public static String classNameToSignature(String name) - { - int nameLength = name.length(); - int colonPos = 1 + nameLength; - char[] buf = new char[colonPos + 1]; - buf[0] = 'L'; - buf[colonPos] = ';'; - name.getChars(0, nameLength, buf, 1); - for (int i = 1; i != colonPos; ++i) { - if (buf[i] == '.') { - buf[i] = '/'; - } - } - return new String(buf, 0, colonPos + 1); - } - - /** - * Add a field to the class. - * - * @param fieldName the name of the field - * @param type the type of the field using ... - * @param flags the attributes of the field, such as ACC_PUBLIC, etc. - * bitwise or'd together - */ - public void addField(String fieldName, String type, short flags) { - short fieldNameIndex = itsConstantPool.addUtf8(fieldName); - short typeIndex = itsConstantPool.addUtf8(type); - itsFields.add(new ClassFileField(fieldNameIndex, typeIndex, flags)); - } - - /** - * Add a field to the class. - * - * @param fieldName the name of the field - * @param type the type of the field using ... - * @param flags the attributes of the field, such as ACC_PUBLIC, etc. - * bitwise or'd together - * @param value an initial integral value - */ - public void addField(String fieldName, String type, short flags, - int value) - { - short fieldNameIndex = itsConstantPool.addUtf8(fieldName); - short typeIndex = itsConstantPool.addUtf8(type); - ClassFileField field = new ClassFileField(fieldNameIndex, typeIndex, - flags); - field.setAttributes(itsConstantPool.addUtf8("ConstantValue"), - (short)0, - (short)0, - itsConstantPool.addConstant(value)); - itsFields.add(field); - } - - /** - * Add a field to the class. - * - * @param fieldName the name of the field - * @param type the type of the field using ... - * @param flags the attributes of the field, such as ACC_PUBLIC, etc. - * bitwise or'd together - * @param value an initial long value - */ - public void addField(String fieldName, String type, short flags, - long value) - { - short fieldNameIndex = itsConstantPool.addUtf8(fieldName); - short typeIndex = itsConstantPool.addUtf8(type); - ClassFileField field = new ClassFileField(fieldNameIndex, typeIndex, - flags); - field.setAttributes(itsConstantPool.addUtf8("ConstantValue"), - (short)0, - (short)2, - itsConstantPool.addConstant(value)); - itsFields.add(field); - } - - /** - * Add a field to the class. - * - * @param fieldName the name of the field - * @param type the type of the field using ... - * @param flags the attributes of the field, such as ACC_PUBLIC, etc. - * bitwise or'd together - * @param value an initial double value - */ - public void addField(String fieldName, String type, short flags, - double value) - { - short fieldNameIndex = itsConstantPool.addUtf8(fieldName); - short typeIndex = itsConstantPool.addUtf8(type); - ClassFileField field = new ClassFileField(fieldNameIndex, typeIndex, - flags); - field.setAttributes(itsConstantPool.addUtf8("ConstantValue"), - (short)0, - (short)2, - itsConstantPool.addConstant(value)); - itsFields.add(field); - } - - /** - * Add Information about java variable to use when generating the local - * variable table. - * - * @param name variable name. - * @param type variable type as bytecode descriptor string. - * @param startPC the starting bytecode PC where this variable is live, - * or -1 if it does not have a Java register. - * @param register the Java register number of variable - * or -1 if it does not have a Java register. - */ - public void addVariableDescriptor(String name, String type, int startPC, int register) - { - int nameIndex = itsConstantPool.addUtf8(name); - int descriptorIndex = itsConstantPool.addUtf8(type); - int [] chunk = { nameIndex, descriptorIndex, startPC, register }; - if (itsVarDescriptors == null) { - itsVarDescriptors = new ObjArray(); - } - itsVarDescriptors.add(chunk); - } - - /** - * Add a method and begin adding code. - * - * This method must be called before other methods for adding code, - * exception tables, etc. can be invoked. - * - * @param methodName the name of the method - * @param type a string representing the type - * @param flags the attributes of the field, such as ACC_PUBLIC, etc. - * bitwise or'd together - */ - public void startMethod(String methodName, String type, short flags) { - short methodNameIndex = itsConstantPool.addUtf8(methodName); - short typeIndex = itsConstantPool.addUtf8(type); - itsCurrentMethod = new ClassFileMethod(methodNameIndex, typeIndex, - flags); - itsMethods.add(itsCurrentMethod); - } - - /** - * Complete generation of the method. - * - * After this method is called, no more code can be added to the - * method begun with <code>startMethod</code>. - * - * @param maxLocals the maximum number of local variable slots - * (a.k.a. Java registers) used by the method - */ - public void stopMethod(short maxLocals) { - if (itsCurrentMethod == null) - throw new IllegalStateException("No method to stop"); - - fixLabelGotos(); - - itsMaxLocals = maxLocals; - - int lineNumberTableLength = 0; - if (itsLineNumberTable != null) { - // 6 bytes for the attribute header - // 2 bytes for the line number count - // 4 bytes for each entry - lineNumberTableLength = 6 + 2 + (itsLineNumberTableTop * 4); - } - - int variableTableLength = 0; - if (itsVarDescriptors != null) { - // 6 bytes for the attribute header - // 2 bytes for the variable count - // 10 bytes for each entry - variableTableLength = 6 + 2 + (itsVarDescriptors.size() * 10); - } - - int attrLength = 2 + // attribute_name_index - 4 + // attribute_length - 2 + // max_stack - 2 + // max_locals - 4 + // code_length - itsCodeBufferTop + - 2 + // exception_table_length - (itsExceptionTableTop * 8) + - 2 + // attributes_count - lineNumberTableLength + - variableTableLength; - - if (attrLength > 65536) { - // See http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html, - // section 4.10, "The amount of code per non-native, non-abstract - // method is limited to 65536 bytes... - throw new ClassFileFormatException( - "generated bytecode for method exceeds 64K limit."); - } - byte[] codeAttribute = new byte[attrLength]; - int index = 0; - int codeAttrIndex = itsConstantPool.addUtf8("Code"); - index = putInt16(codeAttrIndex, codeAttribute, index); - attrLength -= 6; // discount the attribute header - index = putInt32(attrLength, codeAttribute, index); - index = putInt16(itsMaxStack, codeAttribute, index); - index = putInt16(itsMaxLocals, codeAttribute, index); - index = putInt32(itsCodeBufferTop, codeAttribute, index); - System.arraycopy(itsCodeBuffer, 0, codeAttribute, index, - itsCodeBufferTop); - index += itsCodeBufferTop; - - if (itsExceptionTableTop > 0) { - index = putInt16(itsExceptionTableTop, codeAttribute, index); - for (int i = 0; i < itsExceptionTableTop; i++) { - ExceptionTableEntry ete = itsExceptionTable[i]; - short startPC = (short)getLabelPC(ete.itsStartLabel); - short endPC = (short)getLabelPC(ete.itsEndLabel); - short handlerPC = (short)getLabelPC(ete.itsHandlerLabel); - short catchType = ete.itsCatchType; - if (startPC == -1) - throw new IllegalStateException("start label not defined"); - if (endPC == -1) - throw new IllegalStateException("end label not defined"); - if (handlerPC == -1) - throw new IllegalStateException( - "handler label not defined"); - - index = putInt16(startPC, codeAttribute, index); - index = putInt16(endPC, codeAttribute, index); - index = putInt16(handlerPC, codeAttribute, index); - index = putInt16(catchType, codeAttribute, index); - } - } - else { - // write 0 as exception table length - index = putInt16(0, codeAttribute, index); - } - - int attributeCount = 0; - if (itsLineNumberTable != null) - attributeCount++; - if (itsVarDescriptors != null) - attributeCount++; - index = putInt16(attributeCount, codeAttribute, index); - - if (itsLineNumberTable != null) { - int lineNumberTableAttrIndex - = itsConstantPool.addUtf8("LineNumberTable"); - index = putInt16(lineNumberTableAttrIndex, codeAttribute, index); - int tableAttrLength = 2 + (itsLineNumberTableTop * 4); - index = putInt32(tableAttrLength, codeAttribute, index); - index = putInt16(itsLineNumberTableTop, codeAttribute, index); - for (int i = 0; i < itsLineNumberTableTop; i++) { - index = putInt32(itsLineNumberTable[i], codeAttribute, index); - } - } - - if (itsVarDescriptors != null) { - int variableTableAttrIndex - = itsConstantPool.addUtf8("LocalVariableTable"); - index = putInt16(variableTableAttrIndex, codeAttribute, index); - int varCount = itsVarDescriptors.size(); - int tableAttrLength = 2 + (varCount * 10); - index = putInt32(tableAttrLength, codeAttribute, index); - index = putInt16(varCount, codeAttribute, index); - for (int i = 0; i < varCount; i++) { - int[] chunk = (int[])itsVarDescriptors.get(i); - int nameIndex = chunk[0]; - int descriptorIndex = chunk[1]; - int startPC = chunk[2]; - int register = chunk[3]; - int length = itsCodeBufferTop - startPC; - - index = putInt16(startPC, codeAttribute, index); - index = putInt16(length, codeAttribute, index); - index = putInt16(nameIndex, codeAttribute, index); - index = putInt16(descriptorIndex, codeAttribute, index); - index = putInt16(register, codeAttribute, index); - } - } - - itsCurrentMethod.setCodeAttribute(codeAttribute); - - itsExceptionTable = null; - itsExceptionTableTop = 0; - itsLineNumberTableTop = 0; - itsCodeBufferTop = 0; - itsCurrentMethod = null; - itsMaxStack = 0; - itsStackTop = 0; - itsLabelTableTop = 0; - itsFixupTableTop = 0; - itsVarDescriptors = null; - } - - /** - * Add the single-byte opcode to the current method. - * - * @param theOpCode the opcode of the bytecode - */ - public void add(int theOpCode) { - if (opcodeCount(theOpCode) != 0) - throw new IllegalArgumentException("Unexpected operands"); - int newStack = itsStackTop + stackChange(theOpCode); - if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); - if (DEBUGCODE) - System.out.println("Add " + bytecodeStr(theOpCode)); - addToCodeBuffer(theOpCode); - itsStackTop = (short)newStack; - if (newStack > itsMaxStack) itsMaxStack = (short)newStack; - if (DEBUGSTACK) { - System.out.println("After "+bytecodeStr(theOpCode) - +" stack = "+itsStackTop); - } - } - - /** - * Add a single-operand opcode to the current method. - * - * @param theOpCode the opcode of the bytecode - * @param theOperand the operand of the bytecode - */ - public void add(int theOpCode, int theOperand) { - if (DEBUGCODE) { - System.out.println("Add "+bytecodeStr(theOpCode) - +", "+Integer.toHexString(theOperand)); - } - int newStack = itsStackTop + stackChange(theOpCode); - if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); - - switch (theOpCode) { - case ByteCode.GOTO : - // fallthru... - case ByteCode.IFEQ : - case ByteCode.IFNE : - case ByteCode.IFLT : - case ByteCode.IFGE : - case ByteCode.IFGT : - case ByteCode.IFLE : - case ByteCode.IF_ICMPEQ : - case ByteCode.IF_ICMPNE : - case ByteCode.IF_ICMPLT : - case ByteCode.IF_ICMPGE : - case ByteCode.IF_ICMPGT : - case ByteCode.IF_ICMPLE : - case ByteCode.IF_ACMPEQ : - case ByteCode.IF_ACMPNE : - case ByteCode.JSR : - case ByteCode.IFNULL : - case ByteCode.IFNONNULL : { - if ((theOperand & 0x80000000) != 0x80000000) { - if ((theOperand < 0) || (theOperand > 65535)) - throw new IllegalArgumentException( - "Bad label for branch"); - } - int branchPC = itsCodeBufferTop; - addToCodeBuffer(theOpCode); - if ((theOperand & 0x80000000) != 0x80000000) { - // hard displacement - addToCodeInt16(theOperand); - } - else { // a label - int targetPC = getLabelPC(theOperand); - if (DEBUGLABELS) { - int theLabel = theOperand & 0x7FFFFFFF; - System.out.println("Fixing branch to " + - theLabel + " at " + targetPC + - " from " + branchPC); - } - if (targetPC != -1) { - int offset = targetPC - branchPC; - addToCodeInt16(offset); - } - else { - addLabelFixup(theOperand, branchPC + 1); - addToCodeInt16(0); - } - } - } - break; - - case ByteCode.BIPUSH : - if ((byte)theOperand != theOperand) - throw new IllegalArgumentException("out of range byte"); - addToCodeBuffer(theOpCode); - addToCodeBuffer((byte)theOperand); - break; - - case ByteCode.SIPUSH : - if ((short)theOperand != theOperand) - throw new IllegalArgumentException("out of range short"); - addToCodeBuffer(theOpCode); - addToCodeInt16(theOperand); - break; - - case ByteCode.NEWARRAY : - if (!(0 <= theOperand && theOperand < 256)) - throw new IllegalArgumentException("out of range index"); - addToCodeBuffer(theOpCode); - addToCodeBuffer(theOperand); - break; - - case ByteCode.GETFIELD : - case ByteCode.PUTFIELD : - if (!(0 <= theOperand && theOperand < 65536)) - throw new IllegalArgumentException("out of range field"); - addToCodeBuffer(theOpCode); - addToCodeInt16(theOperand); - break; - - case ByteCode.LDC : - case ByteCode.LDC_W : - case ByteCode.LDC2_W : - if (!(0 <= theOperand && theOperand < 65536)) - throw new IllegalArgumentException("out of range index"); - if (theOperand >= 256 - || theOpCode == ByteCode.LDC_W - || theOpCode == ByteCode.LDC2_W) - { - if (theOpCode == ByteCode.LDC) { - addToCodeBuffer(ByteCode.LDC_W); - } else { - addToCodeBuffer(theOpCode); - } - addToCodeInt16(theOperand); - } else { - addToCodeBuffer(theOpCode); - addToCodeBuffer(theOperand); - } - break; - - case ByteCode.RET : - case ByteCode.ILOAD : - case ByteCode.LLOAD : - case ByteCode.FLOAD : - case ByteCode.DLOAD : - case ByteCode.ALOAD : - case ByteCode.ISTORE : - case ByteCode.LSTORE : - case ByteCode.FSTORE : - case ByteCode.DSTORE : - case ByteCode.ASTORE : - if (!(0 <= theOperand && theOperand < 65536)) - throw new ClassFileFormatException("out of range variable"); - if (theOperand >= 256) { - addToCodeBuffer(ByteCode.WIDE); - addToCodeBuffer(theOpCode); - addToCodeInt16(theOperand); - } - else { - addToCodeBuffer(theOpCode); - addToCodeBuffer(theOperand); - } - break; - - default : - throw new IllegalArgumentException( - "Unexpected opcode for 1 operand"); - } - - itsStackTop = (short)newStack; - if (newStack > itsMaxStack) itsMaxStack = (short)newStack; - if (DEBUGSTACK) { - System.out.println("After "+bytecodeStr(theOpCode) - +" stack = "+itsStackTop); - } - } - - /** - * Generate the load constant bytecode for the given integer. - * - * @param k the constant - */ - public void addLoadConstant(int k) { - switch (k) { - case 0: add(ByteCode.ICONST_0); break; - case 1: add(ByteCode.ICONST_1); break; - case 2: add(ByteCode.ICONST_2); break; - case 3: add(ByteCode.ICONST_3); break; - case 4: add(ByteCode.ICONST_4); break; - case 5: add(ByteCode.ICONST_5); break; - default: - add(ByteCode.LDC, itsConstantPool.addConstant(k)); - break; - } - } - - /** - * Generate the load constant bytecode for the given long. - * - * @param k the constant - */ - public void addLoadConstant(long k) { - add(ByteCode.LDC2_W, itsConstantPool.addConstant(k)); - } - - /** - * Generate the load constant bytecode for the given float. - * - * @param k the constant - */ - public void addLoadConstant(float k) { - add(ByteCode.LDC, itsConstantPool.addConstant(k)); - } - - /** - * Generate the load constant bytecode for the given double. - * - * @param k the constant - */ - public void addLoadConstant(double k) { - add(ByteCode.LDC2_W, itsConstantPool.addConstant(k)); - } - - /** - * Generate the load constant bytecode for the given string. - * - * @param k the constant - */ - public void addLoadConstant(String k) { - add(ByteCode.LDC, itsConstantPool.addConstant(k)); - } - - /** - * Add the given two-operand bytecode to the current method. - * - * @param theOpCode the opcode of the bytecode - * @param theOperand1 the first operand of the bytecode - * @param theOperand2 the second operand of the bytecode - */ - public void add(int theOpCode, int theOperand1, int theOperand2) { - if (DEBUGCODE) { - System.out.println("Add "+bytecodeStr(theOpCode) - +", "+Integer.toHexString(theOperand1) - +", "+Integer.toHexString(theOperand2)); - } - int newStack = itsStackTop + stackChange(theOpCode); - if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); - - if (theOpCode == ByteCode.IINC) { - if (!(0 <= theOperand1 && theOperand1 < 65536)) - throw new ClassFileFormatException("out of range variable"); - if (!(0 <= theOperand2 && theOperand2 < 65536)) - throw new ClassFileFormatException("out of range increment"); - - if (theOperand1 > 255 || theOperand2 < -128 || theOperand2 > 127) { - addToCodeBuffer(ByteCode.WIDE); - addToCodeBuffer(ByteCode.IINC); - addToCodeInt16(theOperand1); - addToCodeInt16(theOperand2); - } - else { - addToCodeBuffer(ByteCode.WIDE); - addToCodeBuffer(ByteCode.IINC); - addToCodeBuffer(theOperand1); - addToCodeBuffer(theOperand2); - } - } - else if (theOpCode == ByteCode.MULTIANEWARRAY) { - if (!(0 <= theOperand1 && theOperand1 < 65536)) - throw new IllegalArgumentException("out of range index"); - if (!(0 <= theOperand2 && theOperand2 < 256)) - throw new IllegalArgumentException("out of range dimensions"); - - addToCodeBuffer(ByteCode.MULTIANEWARRAY); - addToCodeInt16(theOperand1); - addToCodeBuffer(theOperand2); - } - else { - throw new IllegalArgumentException( - "Unexpected opcode for 2 operands"); - } - itsStackTop = (short)newStack; - if (newStack > itsMaxStack) itsMaxStack = (short)newStack; - if (DEBUGSTACK) { - System.out.println("After "+bytecodeStr(theOpCode) - +" stack = "+itsStackTop); - } - - } - - public void add(int theOpCode, String className) { - if (DEBUGCODE) { - System.out.println("Add "+bytecodeStr(theOpCode) - +", "+className); - } - int newStack = itsStackTop + stackChange(theOpCode); - if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); - switch (theOpCode) { - case ByteCode.NEW : - case ByteCode.ANEWARRAY : - case ByteCode.CHECKCAST : - case ByteCode.INSTANCEOF : { - short classIndex = itsConstantPool.addClass(className); - addToCodeBuffer(theOpCode); - addToCodeInt16(classIndex); - } - break; - - default : - throw new IllegalArgumentException( - "bad opcode for class reference"); - } - itsStackTop = (short)newStack; - if (newStack > itsMaxStack) itsMaxStack = (short)newStack; - if (DEBUGSTACK) { - System.out.println("After "+bytecodeStr(theOpCode) - +" stack = "+itsStackTop); - } - } - - - public void add(int theOpCode, String className, String fieldName, - String fieldType) - { - if (DEBUGCODE) { - System.out.println("Add "+bytecodeStr(theOpCode) - +", "+className+", "+fieldName+", "+fieldType); - } - int newStack = itsStackTop + stackChange(theOpCode); - char fieldTypeChar = fieldType.charAt(0); - int fieldSize = (fieldTypeChar == 'J' || fieldTypeChar == 'D') - ? 2 : 1; - switch (theOpCode) { - case ByteCode.GETFIELD : - case ByteCode.GETSTATIC : - newStack += fieldSize; - break; - case ByteCode.PUTSTATIC : - case ByteCode.PUTFIELD : - newStack -= fieldSize; - break; - default : - throw new IllegalArgumentException( - "bad opcode for field reference"); - } - if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); - short fieldRefIndex = itsConstantPool.addFieldRef(className, - fieldName, fieldType); - addToCodeBuffer(theOpCode); - addToCodeInt16(fieldRefIndex); - - itsStackTop = (short)newStack; - if (newStack > itsMaxStack) itsMaxStack = (short)newStack; - if (DEBUGSTACK) { - System.out.println("After "+bytecodeStr(theOpCode) - +" stack = "+itsStackTop); - } - } - - public void addInvoke(int theOpCode, String className, String methodName, - String methodType) - { - if (DEBUGCODE) { - System.out.println("Add "+bytecodeStr(theOpCode) - +", "+className+", "+methodName+", " - +methodType); - } - int parameterInfo = sizeOfParameters(methodType); - int parameterCount = parameterInfo >>> 16; - int stackDiff = (short)parameterInfo; - - int newStack = itsStackTop + stackDiff; - newStack += stackChange(theOpCode); // adjusts for 'this' - if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); - - switch (theOpCode) { - case ByteCode.INVOKEVIRTUAL : - case ByteCode.INVOKESPECIAL : - case ByteCode.INVOKESTATIC : - case ByteCode.INVOKEINTERFACE : { - addToCodeBuffer(theOpCode); - if (theOpCode == ByteCode.INVOKEINTERFACE) { - short ifMethodRefIndex - = itsConstantPool.addInterfaceMethodRef( - className, methodName, - methodType); - addToCodeInt16(ifMethodRefIndex); - addToCodeBuffer(parameterCount + 1); - addToCodeBuffer(0); - } - else { - short methodRefIndex = itsConstantPool.addMethodRef( - className, methodName, - methodType); - addToCodeInt16(methodRefIndex); - } - } - break; - - default : - throw new IllegalArgumentException( - "bad opcode for method reference"); - } - itsStackTop = (short)newStack; - if (newStack > itsMaxStack) itsMaxStack = (short)newStack; - if (DEBUGSTACK) { - System.out.println("After "+bytecodeStr(theOpCode) - +" stack = "+itsStackTop); - } - } - - /** - * Generate code to load the given integer on stack. - * - * @param k the constant - */ - public void addPush(int k) - { - if ((byte)k == k) { - if (k == -1) { - add(ByteCode.ICONST_M1); - } else if (0 <= k && k <= 5) { - add((byte)(ByteCode.ICONST_0 + k)); - } else { - add(ByteCode.BIPUSH, (byte)k); - } - } else if ((short)k == k) { - add(ByteCode.SIPUSH, (short)k); - } else { - addLoadConstant(k); - } - } - - public void addPush(boolean k) - { - add(k ? ByteCode.ICONST_1 : ByteCode.ICONST_0); - } - - /** - * Generate code to load the given long on stack. - * - * @param k the constant - */ - public void addPush(long k) - { - int ik = (int)k; - if (ik == k) { - addPush(ik); - add(ByteCode.I2L); - } else { - addLoadConstant(k); - } - } - - /** - * Generate code to load the given double on stack. - * - * @param k the constant - */ - public void addPush(double k) - { - if (k == 0.0) { - // zero - add(ByteCode.DCONST_0); - if (1.0 / k < 0) { - // Negative zero - add(ByteCode.DNEG); - } - } else if (k == 1.0 || k == -1.0) { - add(ByteCode.DCONST_1); - if (k < 0) { - add(ByteCode.DNEG); - } - } else { - addLoadConstant(k); - } - } - - /** - * Generate the code to leave on stack the given string even if the - * string encoding exeeds the class file limit for single string constant - * - * @param k the constant - */ - public void addPush(String k) { - int length = k.length(); - int limit = itsConstantPool.getUtfEncodingLimit(k, 0, length); - if (limit == length) { - addLoadConstant(k); - return; - } - // Split string into picies fitting the UTF limit and generate code for - // StringBuffer sb = new StringBuffer(length); - // sb.append(loadConstant(piece_1)); - // ... - // sb.append(loadConstant(piece_N)); - // sb.toString(); - final String SB = "java/lang/StringBuffer"; - add(ByteCode.NEW, SB); - add(ByteCode.DUP); - addPush(length); - addInvoke(ByteCode.INVOKESPECIAL, SB, "<init>", "(I)V"); - int cursor = 0; - for (;;) { - add(ByteCode.DUP); - String s = k.substring(cursor, limit); - addLoadConstant(s); - addInvoke(ByteCode.INVOKEVIRTUAL, SB, "append", - "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); - add(ByteCode.POP); - if (limit == length) { - break; - } - cursor = limit; - limit = itsConstantPool.getUtfEncodingLimit(k, limit, length); - } - addInvoke(ByteCode.INVOKEVIRTUAL, SB, "toString", - "()Ljava/lang/String;"); - } - - /** - * Check if k fits limit on string constant size imposed by class file - * format. - * - * @param k the string constant - */ - public boolean isUnderStringSizeLimit(String k) - { - return itsConstantPool.isUnderUtfEncodingLimit(k); - } - - /** - * Store integer from stack top into the given local. - * - * @param local number of local register - */ - public void addIStore(int local) - { - xop(ByteCode.ISTORE_0, ByteCode.ISTORE, local); - } - - /** - * Store long from stack top into the given local. - * - * @param local number of local register - */ - public void addLStore(int local) - { - xop(ByteCode.LSTORE_0, ByteCode.LSTORE, local); - } - - /** - * Store float from stack top into the given local. - * - * @param local number of local register - */ - public void addFStore(int local) - { - xop(ByteCode.FSTORE_0, ByteCode.FSTORE, local); - } - - /** - * Store double from stack top into the given local. - * - * @param local number of local register - */ - public void addDStore(int local) - { - xop(ByteCode.DSTORE_0, ByteCode.DSTORE, local); - } - - /** - * Store object from stack top into the given local. - * - * @param local number of local register - */ - public void addAStore(int local) - { - xop(ByteCode.ASTORE_0, ByteCode.ASTORE, local); - } - - /** - * Load integer from the given local into stack. - * - * @param local number of local register - */ - public void addILoad(int local) - { - xop(ByteCode.ILOAD_0, ByteCode.ILOAD, local); - } - - /** - * Load long from the given local into stack. - * - * @param local number of local register - */ - public void addLLoad(int local) - { - xop(ByteCode.LLOAD_0, ByteCode.LLOAD, local); - } - - /** - * Load float from the given local into stack. - * - * @param local number of local register - */ - public void addFLoad(int local) - { - xop(ByteCode.FLOAD_0, ByteCode.FLOAD, local); - } - - /** - * Load double from the given local into stack. - * - * @param local number of local register - */ - public void addDLoad(int local) - { - xop(ByteCode.DLOAD_0, ByteCode.DLOAD, local); - } - - /** - * Load object from the given local into stack. - * - * @param local number of local register - */ - public void addALoad(int local) - { - xop(ByteCode.ALOAD_0, ByteCode.ALOAD, local); - } - - /** - * Load "this" into stack. - */ - public void addLoadThis() - { - add(ByteCode.ALOAD_0); - } - - private void xop(int shortOp, int op, int local) - { - switch (local) { - case 0: - add(shortOp); - break; - case 1: - add(shortOp + 1); - break; - case 2: - add(shortOp + 2); - break; - case 3: - add(shortOp + 3); - break; - default: - add(op, local); - } - } - - public int addTableSwitch(int low, int high) - { - if (DEBUGCODE) { - System.out.println("Add "+bytecodeStr(ByteCode.TABLESWITCH) - +" "+low+" "+high); - } - if (low > high) - throw new ClassFileFormatException("Bad bounds: "+low+' '+ high); - - int newStack = itsStackTop + stackChange(ByteCode.TABLESWITCH); - if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); - - int entryCount = high - low + 1; - int padSize = 3 & ~itsCodeBufferTop; // == 3 - itsCodeBufferTop % 4 - - int N = addReservedCodeSpace(1 + padSize + 4 * (1 + 2 + entryCount)); - int switchStart = N; - itsCodeBuffer[N++] = (byte)ByteCode.TABLESWITCH; - while (padSize != 0) { - itsCodeBuffer[N++] = 0; - --padSize; - } - N += 4; // skip default offset - N = putInt32(low, itsCodeBuffer, N); - putInt32(high, itsCodeBuffer, N); - - itsStackTop = (short)newStack; - if (newStack > itsMaxStack) itsMaxStack = (short)newStack; - if (DEBUGSTACK) { - System.out.println("After "+bytecodeStr(ByteCode.TABLESWITCH) - +" stack = "+itsStackTop); - } - - return switchStart; - } - - public final void markTableSwitchDefault(int switchStart) - { - setTableSwitchJump(switchStart, -1, itsCodeBufferTop); - } - - public final void markTableSwitchCase(int switchStart, int caseIndex) - { - setTableSwitchJump(switchStart, caseIndex, itsCodeBufferTop); - } - - public final void markTableSwitchCase(int switchStart, int caseIndex, - int stackTop) - { - if (!(0 <= stackTop && stackTop <= itsMaxStack)) - throw new IllegalArgumentException("Bad stack index: "+stackTop); - itsStackTop = (short)stackTop; - setTableSwitchJump(switchStart, caseIndex, itsCodeBufferTop); - } - - public void setTableSwitchJump(int switchStart, int caseIndex, - int jumpTarget) - { - if (!(0 <= jumpTarget && jumpTarget <= itsCodeBufferTop)) - throw new IllegalArgumentException("Bad jump target: "+jumpTarget); - if (!(caseIndex >= -1)) - throw new IllegalArgumentException("Bad case index: "+caseIndex); - - int padSize = 3 & ~switchStart; // == 3 - switchStart % 4 - int caseOffset; - if (caseIndex < 0) { - // default label - caseOffset = switchStart + 1 + padSize; - } else { - caseOffset = switchStart + 1 + padSize + 4 * (3 + caseIndex); - } - if (!(0 <= switchStart - && switchStart <= itsCodeBufferTop - 4 * 4 - padSize - 1)) - { - throw new IllegalArgumentException( - switchStart+" is outside a possible range of tableswitch" - +" in already generated code"); - } - if ((0xFF & itsCodeBuffer[switchStart]) != ByteCode.TABLESWITCH) { - throw new IllegalArgumentException( - switchStart+" is not offset of tableswitch statement"); - } - if (!(0 <= caseOffset && caseOffset + 4 <= itsCodeBufferTop)) { - // caseIndex >= -1 does not guarantee that caseOffset >= 0 due - // to a possible overflow. - throw new ClassFileFormatException( - "Too big case index: "+caseIndex); - } - // ALERT: perhaps check against case bounds? - putInt32(jumpTarget - switchStart, itsCodeBuffer, caseOffset); - } - - public int acquireLabel() - { - int top = itsLabelTableTop; - if (itsLabelTable == null || top == itsLabelTable.length) { - if (itsLabelTable == null) { - itsLabelTable = new int[MIN_LABEL_TABLE_SIZE]; - }else { - int[] tmp = new int[itsLabelTable.length * 2]; - System.arraycopy(itsLabelTable, 0, tmp, 0, top); - itsLabelTable = tmp; - } - } - itsLabelTableTop = top + 1; - itsLabelTable[top] = -1; - return top | 0x80000000; - } - - public void markLabel(int label) - { - if (!(label < 0)) - throw new IllegalArgumentException("Bad label, no biscuit"); - - label &= 0x7FFFFFFF; - if (label > itsLabelTableTop) - throw new IllegalArgumentException("Bad label"); - - if (itsLabelTable[label] != -1) { - throw new IllegalStateException("Can only mark label once"); - } - - itsLabelTable[label] = itsCodeBufferTop; - } - - public void markLabel(int label, short stackTop) - { - markLabel(label); - itsStackTop = stackTop; - } - - public void markHandler(int theLabel) { - itsStackTop = 1; - markLabel(theLabel); - } - - private int getLabelPC(int label) - { - if (!(label < 0)) - throw new IllegalArgumentException("Bad label, no biscuit"); - label &= 0x7FFFFFFF; - if (!(label < itsLabelTableTop)) - throw new IllegalArgumentException("Bad label"); - return itsLabelTable[label]; - } - - private void addLabelFixup(int label, int fixupSite) - { - if (!(label < 0)) - throw new IllegalArgumentException("Bad label, no biscuit"); - label &= 0x7FFFFFFF; - if (!(label < itsLabelTableTop)) - throw new IllegalArgumentException("Bad label"); - int top = itsFixupTableTop; - if (itsFixupTable == null || top == itsFixupTable.length) { - if (itsFixupTable == null) { - itsFixupTable = new long[MIN_FIXUP_TABLE_SIZE]; - }else { - long[] tmp = new long[itsFixupTable.length * 2]; - System.arraycopy(itsFixupTable, 0, tmp, 0, top); - itsFixupTable = tmp; - } - } - itsFixupTableTop = top + 1; - itsFixupTable[top] = ((long)label << 32) | fixupSite; - } - - private void fixLabelGotos() - { - byte[] codeBuffer = itsCodeBuffer; - for (int i = 0; i < itsFixupTableTop; i++) { - long fixup = itsFixupTable[i]; - int label = (int)(fixup >> 32); - int fixupSite = (int)fixup; - int pc = itsLabelTable[label]; - if (pc == -1) { - // Unlocated label - throw new RuntimeException(); - } - // -1 to get delta from instruction start - int offset = pc - (fixupSite - 1); - if ((short)offset != offset) { - throw new ClassFileFormatException - ("Program too complex: too big jump offset"); - } - codeBuffer[fixupSite] = (byte)(offset >> 8); - codeBuffer[fixupSite + 1] = (byte)offset; - } - itsFixupTableTop = 0; - } - - /** - * Get the current offset into the code of the current method. - * - * @return an integer representing the offset - */ - public int getCurrentCodeOffset() { - return itsCodeBufferTop; - } - - public short getStackTop() { - return itsStackTop; - } - - public void setStackTop(short n) { - itsStackTop = n; - } - - public void adjustStackTop(int delta) { - int newStack = itsStackTop + delta; - if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); - itsStackTop = (short)newStack; - if (newStack > itsMaxStack) itsMaxStack = (short)newStack; - if (DEBUGSTACK) { - System.out.println("After "+"adjustStackTop("+delta+")" - +" stack = "+itsStackTop); - } - } - - private void addToCodeBuffer(int b) - { - int N = addReservedCodeSpace(1); - itsCodeBuffer[N] = (byte)b; - } - - private void addToCodeInt16(int value) - { - int N = addReservedCodeSpace(2); - putInt16(value, itsCodeBuffer, N); - } - - private int addReservedCodeSpace(int size) - { - if (itsCurrentMethod == null) - throw new IllegalArgumentException("No method to add to"); - int oldTop = itsCodeBufferTop; - int newTop = oldTop + size; - if (newTop > itsCodeBuffer.length) { - int newSize = itsCodeBuffer.length * 2; - if (newTop > newSize) { newSize = newTop; } - byte[] tmp = new byte[newSize]; - System.arraycopy(itsCodeBuffer, 0, tmp, 0, oldTop); - itsCodeBuffer = tmp; - } - itsCodeBufferTop = newTop; - return oldTop; - } - - public void addExceptionHandler(int startLabel, int endLabel, - int handlerLabel, String catchClassName) - { - if ((startLabel & 0x80000000) != 0x80000000) - throw new IllegalArgumentException("Bad startLabel"); - if ((endLabel & 0x80000000) != 0x80000000) - throw new IllegalArgumentException("Bad endLabel"); - if ((handlerLabel & 0x80000000) != 0x80000000) - throw new IllegalArgumentException("Bad handlerLabel"); - - /* - * If catchClassName is null, use 0 for the catch_type_index; which - * means catch everything. (Even when the verifier has let you throw - * something other than a Throwable.) - */ - short catch_type_index = (catchClassName == null) - ? 0 - : itsConstantPool.addClass(catchClassName); - ExceptionTableEntry newEntry = new ExceptionTableEntry( - startLabel, - endLabel, - handlerLabel, - catch_type_index); - int N = itsExceptionTableTop; - if (N == 0) { - itsExceptionTable = new ExceptionTableEntry[ExceptionTableSize]; - } else if (N == itsExceptionTable.length) { - ExceptionTableEntry[] tmp = new ExceptionTableEntry[N * 2]; - System.arraycopy(itsExceptionTable, 0, tmp, 0, N); - itsExceptionTable = tmp; - } - itsExceptionTable[N] = newEntry; - itsExceptionTableTop = N + 1; - - } - - public void addLineNumberEntry(short lineNumber) { - if (itsCurrentMethod == null) - throw new IllegalArgumentException("No method to stop"); - int N = itsLineNumberTableTop; - if (N == 0) { - itsLineNumberTable = new int[LineNumberTableSize]; - } else if (N == itsLineNumberTable.length) { - int[] tmp = new int[N * 2]; - System.arraycopy(itsLineNumberTable, 0, tmp, 0, N); - itsLineNumberTable = tmp; - } - itsLineNumberTable[N] = (itsCodeBufferTop << 16) + lineNumber; - itsLineNumberTableTop = N + 1; - } - - /** - * Write the class file to the OutputStream. - * - * @param oStream the stream to write to - * @throws IOException if writing to the stream produces an exception - */ - public void write(OutputStream oStream) - throws IOException - { - byte[] array = toByteArray(); - oStream.write(array); - } - - private int getWriteSize() - { - int size = 0; - - if (itsSourceFileNameIndex != 0) { - itsConstantPool.addUtf8("SourceFile"); - } - - size += 8; //writeLong(FileHeaderConstant); - size += itsConstantPool.getWriteSize(); - size += 2; //writeShort(itsFlags); - size += 2; //writeShort(itsThisClassIndex); - size += 2; //writeShort(itsSuperClassIndex); - size += 2; //writeShort(itsInterfaces.size()); - size += 2 * itsInterfaces.size(); - - size += 2; //writeShort(itsFields.size()); - for (int i = 0; i < itsFields.size(); i++) { - size += ((ClassFileField)(itsFields.get(i))).getWriteSize(); - } - - size += 2; //writeShort(itsMethods.size()); - for (int i = 0; i < itsMethods.size(); i++) { - size += ((ClassFileMethod)(itsMethods.get(i))).getWriteSize(); - } - - if (itsSourceFileNameIndex != 0) { - size += 2; //writeShort(1); attributes count - size += 2; //writeShort(sourceFileAttributeNameIndex); - size += 4; //writeInt(2); - size += 2; //writeShort(itsSourceFileNameIndex); - }else { - size += 2; //out.writeShort(0); no attributes - } - - return size; - } - - /** - * Get the class file as array of bytesto the OutputStream. - */ - public byte[] toByteArray() - { - int dataSize = getWriteSize(); - byte[] data = new byte[dataSize]; - int offset = 0; - - short sourceFileAttributeNameIndex = 0; - if (itsSourceFileNameIndex != 0) { - sourceFileAttributeNameIndex = itsConstantPool.addUtf8( - "SourceFile"); - } - - offset = putInt64(FileHeaderConstant, data, offset); - offset = itsConstantPool.write(data, offset); - offset = putInt16(itsFlags, data, offset); - offset = putInt16(itsThisClassIndex, data, offset); - offset = putInt16(itsSuperClassIndex, data, offset); - offset = putInt16(itsInterfaces.size(), data, offset); - for (int i = 0; i < itsInterfaces.size(); i++) { - int interfaceIndex = ((Short)(itsInterfaces.get(i))).shortValue(); - offset = putInt16(interfaceIndex, data, offset); - } - offset = putInt16(itsFields.size(), data, offset); - for (int i = 0; i < itsFields.size(); i++) { - ClassFileField field = (ClassFileField)itsFields.get(i); - offset = field.write(data, offset); - } - offset = putInt16(itsMethods.size(), data, offset); - for (int i = 0; i < itsMethods.size(); i++) { - ClassFileMethod method = (ClassFileMethod)itsMethods.get(i); - offset = method.write(data, offset); - } - if (itsSourceFileNameIndex != 0) { - offset = putInt16(1, data, offset); // attributes count - offset = putInt16(sourceFileAttributeNameIndex, data, offset); - offset = putInt32(2, data, offset); - offset = putInt16(itsSourceFileNameIndex, data, offset); - } else { - offset = putInt16(0, data, offset); // no attributes - } - - if (offset != dataSize) { - // Check getWriteSize is consistent with write! - throw new RuntimeException(); - } - - return data; - } - - static int putInt64(long value, byte[] array, int offset) - { - offset = putInt32((int)(value >>> 32), array, offset); - return putInt32((int)value, array, offset); - } - - private static void badStack(int value) - { - String s; - if (value < 0) { s = "Stack underflow: "+value; } - else { s = "Too big stack: "+value; } - throw new IllegalStateException(s); - } - - /* - Really weird. Returns an int with # parameters in hi 16 bits, and - stack difference removal of parameters from stack and pushing the - result (it does not take into account removal of this in case of - non-static methods). - If Java really supported references we wouldn't have to be this - perverted. - */ - private static int sizeOfParameters(String pString) - { - int length = pString.length(); - int rightParenthesis = pString.lastIndexOf(')'); - if (3 <= length /* minimal signature takes at least 3 chars: ()V */ - && pString.charAt(0) == '(' - && 1 <= rightParenthesis && rightParenthesis + 1 < length) - { - boolean ok = true; - int index = 1; - int stackDiff = 0; - int count = 0; - stringLoop: - while (index != rightParenthesis) { - switch (pString.charAt(index)) { - default: - ok = false; - break stringLoop; - case 'J' : - case 'D' : - --stackDiff; - // fall thru - case 'B' : - case 'S' : - case 'C' : - case 'I' : - case 'Z' : - case 'F' : - --stackDiff; - ++count; - ++index; - continue; - case '[' : - ++index; - int c = pString.charAt(index); - while (c == '[') { - ++index; - c = pString.charAt(index); - } - switch (c) { - default: - ok = false; - break stringLoop; - case 'J' : - case 'D' : - case 'B' : - case 'S' : - case 'C' : - case 'I' : - case 'Z' : - case 'F' : - --stackDiff; - ++count; - ++index; - continue; - case 'L': - // fall thru - } - // fall thru - case 'L' : { - --stackDiff; - ++count; - ++index; - int semicolon = pString.indexOf(';', index); - if (!(index + 1 <= semicolon - && semicolon < rightParenthesis)) - { - ok = false; - break stringLoop; - } - index = semicolon + 1; - continue; - } - } - } - if (ok) { - switch (pString.charAt(rightParenthesis + 1)) { - default: - ok = false; - break; - case 'J' : - case 'D' : - ++stackDiff; - // fall thru - case 'B' : - case 'S' : - case 'C' : - case 'I' : - case 'Z' : - case 'F' : - case 'L' : - case '[' : - ++stackDiff; - // fall thru - case 'V' : - break; - } - if (ok) { - return ((count << 16) | (0xFFFF & stackDiff)); - } - } - } - throw new IllegalArgumentException( - "Bad parameter signature: "+pString); - } - - static int putInt16(int value, byte[] array, int offset) - { - array[offset + 0] = (byte)(value >>> 8); - array[offset + 1] = (byte)value; - return offset + 2; - } - - static int putInt32(int value, byte[] array, int offset) - { - array[offset + 0] = (byte)(value >>> 24); - array[offset + 1] = (byte)(value >>> 16); - array[offset + 2] = (byte)(value >>> 8); - array[offset + 3] = (byte)value; - return offset + 4; - } - - /** - * Number of operands accompanying the opcode. - */ - static int opcodeCount(int opcode) - { - switch (opcode) { - case ByteCode.AALOAD: - case ByteCode.AASTORE: - case ByteCode.ACONST_NULL: - case ByteCode.ALOAD_0: - case ByteCode.ALOAD_1: - case ByteCode.ALOAD_2: - case ByteCode.ALOAD_3: - case ByteCode.ARETURN: - case ByteCode.ARRAYLENGTH: - case ByteCode.ASTORE_0: - case ByteCode.ASTORE_1: - case ByteCode.ASTORE_2: - case ByteCode.ASTORE_3: - case ByteCode.ATHROW: - case ByteCode.BALOAD: - case ByteCode.BASTORE: - case ByteCode.BREAKPOINT: - case ByteCode.CALOAD: - case ByteCode.CASTORE: - case ByteCode.D2F: - case ByteCode.D2I: - case ByteCode.D2L: - case ByteCode.DADD: - case ByteCode.DALOAD: - case ByteCode.DASTORE: - case ByteCode.DCMPG: - case ByteCode.DCMPL: - case ByteCode.DCONST_0: - case ByteCode.DCONST_1: - case ByteCode.DDIV: - case ByteCode.DLOAD_0: - case ByteCode.DLOAD_1: - case ByteCode.DLOAD_2: - case ByteCode.DLOAD_3: - case ByteCode.DMUL: - case ByteCode.DNEG: - case ByteCode.DREM: - case ByteCode.DRETURN: - case ByteCode.DSTORE_0: - case ByteCode.DSTORE_1: - case ByteCode.DSTORE_2: - case ByteCode.DSTORE_3: - case ByteCode.DSUB: - case ByteCode.DUP: - case ByteCode.DUP2: - case ByteCode.DUP2_X1: - case ByteCode.DUP2_X2: - case ByteCode.DUP_X1: - case ByteCode.DUP_X2: - case ByteCode.F2D: - case ByteCode.F2I: - case ByteCode.F2L: - case ByteCode.FADD: - case ByteCode.FALOAD: - case ByteCode.FASTORE: - case ByteCode.FCMPG: - case ByteCode.FCMPL: - case ByteCode.FCONST_0: - case ByteCode.FCONST_1: - case ByteCode.FCONST_2: - case ByteCode.FDIV: - case ByteCode.FLOAD_0: - case ByteCode.FLOAD_1: - case ByteCode.FLOAD_2: - case ByteCode.FLOAD_3: - case ByteCode.FMUL: - case ByteCode.FNEG: - case ByteCode.FREM: - case ByteCode.FRETURN: - case ByteCode.FSTORE_0: - case ByteCode.FSTORE_1: - case ByteCode.FSTORE_2: - case ByteCode.FSTORE_3: - case ByteCode.FSUB: - case ByteCode.I2B: - case ByteCode.I2C: - case ByteCode.I2D: - case ByteCode.I2F: - case ByteCode.I2L: - case ByteCode.I2S: - case ByteCode.IADD: - case ByteCode.IALOAD: - case ByteCode.IAND: - case ByteCode.IASTORE: - case ByteCode.ICONST_0: - case ByteCode.ICONST_1: - case ByteCode.ICONST_2: - case ByteCode.ICONST_3: - case ByteCode.ICONST_4: - case ByteCode.ICONST_5: - case ByteCode.ICONST_M1: - case ByteCode.IDIV: - case ByteCode.ILOAD_0: - case ByteCode.ILOAD_1: - case ByteCode.ILOAD_2: - case ByteCode.ILOAD_3: - case ByteCode.IMPDEP1: - case ByteCode.IMPDEP2: - case ByteCode.IMUL: - case ByteCode.INEG: - case ByteCode.IOR: - case ByteCode.IREM: - case ByteCode.IRETURN: - case ByteCode.ISHL: - case ByteCode.ISHR: - case ByteCode.ISTORE_0: - case ByteCode.ISTORE_1: - case ByteCode.ISTORE_2: - case ByteCode.ISTORE_3: - case ByteCode.ISUB: - case ByteCode.IUSHR: - case ByteCode.IXOR: - case ByteCode.L2D: - case ByteCode.L2F: - case ByteCode.L2I: - case ByteCode.LADD: - case ByteCode.LALOAD: - case ByteCode.LAND: - case ByteCode.LASTORE: - case ByteCode.LCMP: - case ByteCode.LCONST_0: - case ByteCode.LCONST_1: - case ByteCode.LDIV: - case ByteCode.LLOAD_0: - case ByteCode.LLOAD_1: - case ByteCode.LLOAD_2: - case ByteCode.LLOAD_3: - case ByteCode.LMUL: - case ByteCode.LNEG: - case ByteCode.LOR: - case ByteCode.LREM: - case ByteCode.LRETURN: - case ByteCode.LSHL: - case ByteCode.LSHR: - case ByteCode.LSTORE_0: - case ByteCode.LSTORE_1: - case ByteCode.LSTORE_2: - case ByteCode.LSTORE_3: - case ByteCode.LSUB: - case ByteCode.LUSHR: - case ByteCode.LXOR: - case ByteCode.MONITORENTER: - case ByteCode.MONITOREXIT: - case ByteCode.NOP: - case ByteCode.POP: - case ByteCode.POP2: - case ByteCode.RETURN: - case ByteCode.SALOAD: - case ByteCode.SASTORE: - case ByteCode.SWAP: - case ByteCode.WIDE: - return 0; - case ByteCode.ALOAD: - case ByteCode.ANEWARRAY: - case ByteCode.ASTORE: - case ByteCode.BIPUSH: - case ByteCode.CHECKCAST: - case ByteCode.DLOAD: - case ByteCode.DSTORE: - case ByteCode.FLOAD: - case ByteCode.FSTORE: - case ByteCode.GETFIELD: - case ByteCode.GETSTATIC: - case ByteCode.GOTO: - case ByteCode.GOTO_W: - case ByteCode.IFEQ: - case ByteCode.IFGE: - case ByteCode.IFGT: - case ByteCode.IFLE: - case ByteCode.IFLT: - case ByteCode.IFNE: - case ByteCode.IFNONNULL: - case ByteCode.IFNULL: - case ByteCode.IF_ACMPEQ: - case ByteCode.IF_ACMPNE: - case ByteCode.IF_ICMPEQ: - case ByteCode.IF_ICMPGE: - case ByteCode.IF_ICMPGT: - case ByteCode.IF_ICMPLE: - case ByteCode.IF_ICMPLT: - case ByteCode.IF_ICMPNE: - case ByteCode.ILOAD: - case ByteCode.INSTANCEOF: - case ByteCode.INVOKEINTERFACE: - case ByteCode.INVOKESPECIAL: - case ByteCode.INVOKESTATIC: - case ByteCode.INVOKEVIRTUAL: - case ByteCode.ISTORE: - case ByteCode.JSR: - case ByteCode.JSR_W: - case ByteCode.LDC: - case ByteCode.LDC2_W: - case ByteCode.LDC_W: - case ByteCode.LLOAD: - case ByteCode.LSTORE: - case ByteCode.NEW: - case ByteCode.NEWARRAY: - case ByteCode.PUTFIELD: - case ByteCode.PUTSTATIC: - case ByteCode.RET: - case ByteCode.SIPUSH: - return 1; - - case ByteCode.IINC: - case ByteCode.MULTIANEWARRAY: - return 2; - - case ByteCode.LOOKUPSWITCH: - case ByteCode.TABLESWITCH: - return -1; - } - throw new IllegalArgumentException("Bad opcode: "+opcode); - } - - /** - * The effect on the operand stack of a given opcode. - */ - static int stackChange(int opcode) - { - // For INVOKE... accounts only for popping this (unless static), - // ignoring parameters and return type - switch (opcode) { - case ByteCode.DASTORE: - case ByteCode.LASTORE: - return -4; - - case ByteCode.AASTORE: - case ByteCode.BASTORE: - case ByteCode.CASTORE: - case ByteCode.DCMPG: - case ByteCode.DCMPL: - case ByteCode.FASTORE: - case ByteCode.IASTORE: - case ByteCode.LCMP: - case ByteCode.SASTORE: - return -3; - - case ByteCode.DADD: - case ByteCode.DDIV: - case ByteCode.DMUL: - case ByteCode.DREM: - case ByteCode.DRETURN: - case ByteCode.DSTORE: - case ByteCode.DSTORE_0: - case ByteCode.DSTORE_1: - case ByteCode.DSTORE_2: - case ByteCode.DSTORE_3: - case ByteCode.DSUB: - case ByteCode.IF_ACMPEQ: - case ByteCode.IF_ACMPNE: - case ByteCode.IF_ICMPEQ: - case ByteCode.IF_ICMPGE: - case ByteCode.IF_ICMPGT: - case ByteCode.IF_ICMPLE: - case ByteCode.IF_ICMPLT: - case ByteCode.IF_ICMPNE: - case ByteCode.LADD: - case ByteCode.LAND: - case ByteCode.LDIV: - case ByteCode.LMUL: - case ByteCode.LOR: - case ByteCode.LREM: - case ByteCode.LRETURN: - case ByteCode.LSTORE: - case ByteCode.LSTORE_0: - case ByteCode.LSTORE_1: - case ByteCode.LSTORE_2: - case ByteCode.LSTORE_3: - case ByteCode.LSUB: - case ByteCode.LXOR: - case ByteCode.POP2: - return -2; - - case ByteCode.AALOAD: - case ByteCode.ARETURN: - case ByteCode.ASTORE: - case ByteCode.ASTORE_0: - case ByteCode.ASTORE_1: - case ByteCode.ASTORE_2: - case ByteCode.ASTORE_3: - case ByteCode.ATHROW: - case ByteCode.BALOAD: - case ByteCode.CALOAD: - case ByteCode.D2F: - case ByteCode.D2I: - case ByteCode.FADD: - case ByteCode.FALOAD: - case ByteCode.FCMPG: - case ByteCode.FCMPL: - case ByteCode.FDIV: - case ByteCode.FMUL: - case ByteCode.FREM: - case ByteCode.FRETURN: - case ByteCode.FSTORE: - case ByteCode.FSTORE_0: - case ByteCode.FSTORE_1: - case ByteCode.FSTORE_2: - case ByteCode.FSTORE_3: - case ByteCode.FSUB: - case ByteCode.GETFIELD: - case ByteCode.IADD: - case ByteCode.IALOAD: - case ByteCode.IAND: - case ByteCode.IDIV: - case ByteCode.IFEQ: - case ByteCode.IFGE: - case ByteCode.IFGT: - case ByteCode.IFLE: - case ByteCode.IFLT: - case ByteCode.IFNE: - case ByteCode.IFNONNULL: - case ByteCode.IFNULL: - case ByteCode.IMUL: - case ByteCode.INVOKEINTERFACE: // - case ByteCode.INVOKESPECIAL: // but needs to account for - case ByteCode.INVOKEVIRTUAL: // pops 'this' (unless static) - case ByteCode.IOR: - case ByteCode.IREM: - case ByteCode.IRETURN: - case ByteCode.ISHL: - case ByteCode.ISHR: - case ByteCode.ISTORE: - case ByteCode.ISTORE_0: - case ByteCode.ISTORE_1: - case ByteCode.ISTORE_2: - case ByteCode.ISTORE_3: - case ByteCode.ISUB: - case ByteCode.IUSHR: - case ByteCode.IXOR: - case ByteCode.L2F: - case ByteCode.L2I: - case ByteCode.LOOKUPSWITCH: - case ByteCode.LSHL: - case ByteCode.LSHR: - case ByteCode.LUSHR: - case ByteCode.MONITORENTER: - case ByteCode.MONITOREXIT: - case ByteCode.POP: - case ByteCode.PUTFIELD: - case ByteCode.SALOAD: - case ByteCode.TABLESWITCH: - return -1; - - case ByteCode.ANEWARRAY: - case ByteCode.ARRAYLENGTH: - case ByteCode.BREAKPOINT: - case ByteCode.CHECKCAST: - case ByteCode.D2L: - case ByteCode.DALOAD: - case ByteCode.DNEG: - case ByteCode.F2I: - case ByteCode.FNEG: - case ByteCode.GETSTATIC: - case ByteCode.GOTO: - case ByteCode.GOTO_W: - case ByteCode.I2B: - case ByteCode.I2C: - case ByteCode.I2F: - case ByteCode.I2S: - case ByteCode.IINC: - case ByteCode.IMPDEP1: - case ByteCode.IMPDEP2: - case ByteCode.INEG: - case ByteCode.INSTANCEOF: - case ByteCode.INVOKESTATIC: - case ByteCode.L2D: - case ByteCode.LALOAD: - case ByteCode.LNEG: - case ByteCode.NEWARRAY: - case ByteCode.NOP: - case ByteCode.PUTSTATIC: - case ByteCode.RET: - case ByteCode.RETURN: - case ByteCode.SWAP: - case ByteCode.WIDE: - return 0; - - case ByteCode.ACONST_NULL: - case ByteCode.ALOAD: - case ByteCode.ALOAD_0: - case ByteCode.ALOAD_1: - case ByteCode.ALOAD_2: - case ByteCode.ALOAD_3: - case ByteCode.BIPUSH: - case ByteCode.DUP: - case ByteCode.DUP_X1: - case ByteCode.DUP_X2: - case ByteCode.F2D: - case ByteCode.F2L: - case ByteCode.FCONST_0: - case ByteCode.FCONST_1: - case ByteCode.FCONST_2: - case ByteCode.FLOAD: - case ByteCode.FLOAD_0: - case ByteCode.FLOAD_1: - case ByteCode.FLOAD_2: - case ByteCode.FLOAD_3: - case ByteCode.I2D: - case ByteCode.I2L: - case ByteCode.ICONST_0: - case ByteCode.ICONST_1: - case ByteCode.ICONST_2: - case ByteCode.ICONST_3: - case ByteCode.ICONST_4: - case ByteCode.ICONST_5: - case ByteCode.ICONST_M1: - case ByteCode.ILOAD: - case ByteCode.ILOAD_0: - case ByteCode.ILOAD_1: - case ByteCode.ILOAD_2: - case ByteCode.ILOAD_3: - case ByteCode.JSR: - case ByteCode.JSR_W: - case ByteCode.LDC: - case ByteCode.LDC_W: - case ByteCode.MULTIANEWARRAY: - case ByteCode.NEW: - case ByteCode.SIPUSH: - return 1; - - case ByteCode.DCONST_0: - case ByteCode.DCONST_1: - case ByteCode.DLOAD: - case ByteCode.DLOAD_0: - case ByteCode.DLOAD_1: - case ByteCode.DLOAD_2: - case ByteCode.DLOAD_3: - case ByteCode.DUP2: - case ByteCode.DUP2_X1: - case ByteCode.DUP2_X2: - case ByteCode.LCONST_0: - case ByteCode.LCONST_1: - case ByteCode.LDC2_W: - case ByteCode.LLOAD: - case ByteCode.LLOAD_0: - case ByteCode.LLOAD_1: - case ByteCode.LLOAD_2: - case ByteCode.LLOAD_3: - return 2; - } - throw new IllegalArgumentException("Bad opcode: "+opcode); - } - - /* - * Number of bytes of operands generated after the opcode. - * Not in use currently. - */ -/* - int extra(int opcode) - { - switch (opcode) { - case ByteCode.AALOAD: - case ByteCode.AASTORE: - case ByteCode.ACONST_NULL: - case ByteCode.ALOAD_0: - case ByteCode.ALOAD_1: - case ByteCode.ALOAD_2: - case ByteCode.ALOAD_3: - case ByteCode.ARETURN: - case ByteCode.ARRAYLENGTH: - case ByteCode.ASTORE_0: - case ByteCode.ASTORE_1: - case ByteCode.ASTORE_2: - case ByteCode.ASTORE_3: - case ByteCode.ATHROW: - case ByteCode.BALOAD: - case ByteCode.BASTORE: - case ByteCode.BREAKPOINT: - case ByteCode.CALOAD: - case ByteCode.CASTORE: - case ByteCode.D2F: - case ByteCode.D2I: - case ByteCode.D2L: - case ByteCode.DADD: - case ByteCode.DALOAD: - case ByteCode.DASTORE: - case ByteCode.DCMPG: - case ByteCode.DCMPL: - case ByteCode.DCONST_0: - case ByteCode.DCONST_1: - case ByteCode.DDIV: - case ByteCode.DLOAD_0: - case ByteCode.DLOAD_1: - case ByteCode.DLOAD_2: - case ByteCode.DLOAD_3: - case ByteCode.DMUL: - case ByteCode.DNEG: - case ByteCode.DREM: - case ByteCode.DRETURN: - case ByteCode.DSTORE_0: - case ByteCode.DSTORE_1: - case ByteCode.DSTORE_2: - case ByteCode.DSTORE_3: - case ByteCode.DSUB: - case ByteCode.DUP2: - case ByteCode.DUP2_X1: - case ByteCode.DUP2_X2: - case ByteCode.DUP: - case ByteCode.DUP_X1: - case ByteCode.DUP_X2: - case ByteCode.F2D: - case ByteCode.F2I: - case ByteCode.F2L: - case ByteCode.FADD: - case ByteCode.FALOAD: - case ByteCode.FASTORE: - case ByteCode.FCMPG: - case ByteCode.FCMPL: - case ByteCode.FCONST_0: - case ByteCode.FCONST_1: - case ByteCode.FCONST_2: - case ByteCode.FDIV: - case ByteCode.FLOAD_0: - case ByteCode.FLOAD_1: - case ByteCode.FLOAD_2: - case ByteCode.FLOAD_3: - case ByteCode.FMUL: - case ByteCode.FNEG: - case ByteCode.FREM: - case ByteCode.FRETURN: - case ByteCode.FSTORE_0: - case ByteCode.FSTORE_1: - case ByteCode.FSTORE_2: - case ByteCode.FSTORE_3: - case ByteCode.FSUB: - case ByteCode.I2B: - case ByteCode.I2C: - case ByteCode.I2D: - case ByteCode.I2F: - case ByteCode.I2L: - case ByteCode.I2S: - case ByteCode.IADD: - case ByteCode.IALOAD: - case ByteCode.IAND: - case ByteCode.IASTORE: - case ByteCode.ICONST_0: - case ByteCode.ICONST_1: - case ByteCode.ICONST_2: - case ByteCode.ICONST_3: - case ByteCode.ICONST_4: - case ByteCode.ICONST_5: - case ByteCode.ICONST_M1: - case ByteCode.IDIV: - case ByteCode.ILOAD_0: - case ByteCode.ILOAD_1: - case ByteCode.ILOAD_2: - case ByteCode.ILOAD_3: - case ByteCode.IMPDEP1: - case ByteCode.IMPDEP2: - case ByteCode.IMUL: - case ByteCode.INEG: - case ByteCode.IOR: - case ByteCode.IREM: - case ByteCode.IRETURN: - case ByteCode.ISHL: - case ByteCode.ISHR: - case ByteCode.ISTORE_0: - case ByteCode.ISTORE_1: - case ByteCode.ISTORE_2: - case ByteCode.ISTORE_3: - case ByteCode.ISUB: - case ByteCode.IUSHR: - case ByteCode.IXOR: - case ByteCode.L2D: - case ByteCode.L2F: - case ByteCode.L2I: - case ByteCode.LADD: - case ByteCode.LALOAD: - case ByteCode.LAND: - case ByteCode.LASTORE: - case ByteCode.LCMP: - case ByteCode.LCONST_0: - case ByteCode.LCONST_1: - case ByteCode.LDIV: - case ByteCode.LLOAD_0: - case ByteCode.LLOAD_1: - case ByteCode.LLOAD_2: - case ByteCode.LLOAD_3: - case ByteCode.LMUL: - case ByteCode.LNEG: - case ByteCode.LOR: - case ByteCode.LREM: - case ByteCode.LRETURN: - case ByteCode.LSHL: - case ByteCode.LSHR: - case ByteCode.LSTORE_0: - case ByteCode.LSTORE_1: - case ByteCode.LSTORE_2: - case ByteCode.LSTORE_3: - case ByteCode.LSUB: - case ByteCode.LUSHR: - case ByteCode.LXOR: - case ByteCode.MONITORENTER: - case ByteCode.MONITOREXIT: - case ByteCode.NOP: - case ByteCode.POP2: - case ByteCode.POP: - case ByteCode.RETURN: - case ByteCode.SALOAD: - case ByteCode.SASTORE: - case ByteCode.SWAP: - case ByteCode.WIDE: - return 0; - - case ByteCode.ALOAD: - case ByteCode.ASTORE: - case ByteCode.BIPUSH: - case ByteCode.DLOAD: - case ByteCode.DSTORE: - case ByteCode.FLOAD: - case ByteCode.FSTORE: - case ByteCode.ILOAD: - case ByteCode.ISTORE: - case ByteCode.LDC: - case ByteCode.LLOAD: - case ByteCode.LSTORE: - case ByteCode.NEWARRAY: - case ByteCode.RET: - return 1; - - case ByteCode.ANEWARRAY: - case ByteCode.CHECKCAST: - case ByteCode.GETFIELD: - case ByteCode.GETSTATIC: - case ByteCode.GOTO: - case ByteCode.IFEQ: - case ByteCode.IFGE: - case ByteCode.IFGT: - case ByteCode.IFLE: - case ByteCode.IFLT: - case ByteCode.IFNE: - case ByteCode.IFNONNULL: - case ByteCode.IFNULL: - case ByteCode.IF_ACMPEQ: - case ByteCode.IF_ACMPNE: - case ByteCode.IF_ICMPEQ: - case ByteCode.IF_ICMPGE: - case ByteCode.IF_ICMPGT: - case ByteCode.IF_ICMPLE: - case ByteCode.IF_ICMPLT: - case ByteCode.IF_ICMPNE: - case ByteCode.IINC: - case ByteCode.INSTANCEOF: - case ByteCode.INVOKEINTERFACE: - case ByteCode.INVOKESPECIAL: - case ByteCode.INVOKESTATIC: - case ByteCode.INVOKEVIRTUAL: - case ByteCode.JSR: - case ByteCode.LDC2_W: - case ByteCode.LDC_W: - case ByteCode.NEW: - case ByteCode.PUTFIELD: - case ByteCode.PUTSTATIC: - case ByteCode.SIPUSH: - return 2; - - case ByteCode.MULTIANEWARRAY: - return 3; - - case ByteCode.GOTO_W: - case ByteCode.JSR_W: - return 4; - - case ByteCode.LOOKUPSWITCH: // depends on alignment - case ByteCode.TABLESWITCH: // depends on alignment - return -1; - } - throw new IllegalArgumentException("Bad opcode: "+opcode); - } -*/ - private static String bytecodeStr(int code) - { - if (DEBUGSTACK || DEBUGCODE) { - switch (code) { - case ByteCode.NOP: return "nop"; - case ByteCode.ACONST_NULL: return "aconst_null"; - case ByteCode.ICONST_M1: return "iconst_m1"; - case ByteCode.ICONST_0: return "iconst_0"; - case ByteCode.ICONST_1: return "iconst_1"; - case ByteCode.ICONST_2: return "iconst_2"; - case ByteCode.ICONST_3: return "iconst_3"; - case ByteCode.ICONST_4: return "iconst_4"; - case ByteCode.ICONST_5: return "iconst_5"; - case ByteCode.LCONST_0: return "lconst_0"; - case ByteCode.LCONST_1: return "lconst_1"; - case ByteCode.FCONST_0: return "fconst_0"; - case ByteCode.FCONST_1: return "fconst_1"; - case ByteCode.FCONST_2: return "fconst_2"; - case ByteCode.DCONST_0: return "dconst_0"; - case ByteCode.DCONST_1: return "dconst_1"; - case ByteCode.BIPUSH: return "bipush"; - case ByteCode.SIPUSH: return "sipush"; - case ByteCode.LDC: return "ldc"; - case ByteCode.LDC_W: return "ldc_w"; - case ByteCode.LDC2_W: return "ldc2_w"; - case ByteCode.ILOAD: return "iload"; - case ByteCode.LLOAD: return "lload"; - case ByteCode.FLOAD: return "fload"; - case ByteCode.DLOAD: return "dload"; - case ByteCode.ALOAD: return "aload"; - case ByteCode.ILOAD_0: return "iload_0"; - case ByteCode.ILOAD_1: return "iload_1"; - case ByteCode.ILOAD_2: return "iload_2"; - case ByteCode.ILOAD_3: return "iload_3"; - case ByteCode.LLOAD_0: return "lload_0"; - case ByteCode.LLOAD_1: return "lload_1"; - case ByteCode.LLOAD_2: return "lload_2"; - case ByteCode.LLOAD_3: return "lload_3"; - case ByteCode.FLOAD_0: return "fload_0"; - case ByteCode.FLOAD_1: return "fload_1"; - case ByteCode.FLOAD_2: return "fload_2"; - case ByteCode.FLOAD_3: return "fload_3"; - case ByteCode.DLOAD_0: return "dload_0"; - case ByteCode.DLOAD_1: return "dload_1"; - case ByteCode.DLOAD_2: return "dload_2"; - case ByteCode.DLOAD_3: return "dload_3"; - case ByteCode.ALOAD_0: return "aload_0"; - case ByteCode.ALOAD_1: return "aload_1"; - case ByteCode.ALOAD_2: return "aload_2"; - case ByteCode.ALOAD_3: return "aload_3"; - case ByteCode.IALOAD: return "iaload"; - case ByteCode.LALOAD: return "laload"; - case ByteCode.FALOAD: return "faload"; - case ByteCode.DALOAD: return "daload"; - case ByteCode.AALOAD: return "aaload"; - case ByteCode.BALOAD: return "baload"; - case ByteCode.CALOAD: return "caload"; - case ByteCode.SALOAD: return "saload"; - case ByteCode.ISTORE: return "istore"; - case ByteCode.LSTORE: return "lstore"; - case ByteCode.FSTORE: return "fstore"; - case ByteCode.DSTORE: return "dstore"; - case ByteCode.ASTORE: return "astore"; - case ByteCode.ISTORE_0: return "istore_0"; - case ByteCode.ISTORE_1: return "istore_1"; - case ByteCode.ISTORE_2: return "istore_2"; - case ByteCode.ISTORE_3: return "istore_3"; - case ByteCode.LSTORE_0: return "lstore_0"; - case ByteCode.LSTORE_1: return "lstore_1"; - case ByteCode.LSTORE_2: return "lstore_2"; - case ByteCode.LSTORE_3: return "lstore_3"; - case ByteCode.FSTORE_0: return "fstore_0"; - case ByteCode.FSTORE_1: return "fstore_1"; - case ByteCode.FSTORE_2: return "fstore_2"; - case ByteCode.FSTORE_3: return "fstore_3"; - case ByteCode.DSTORE_0: return "dstore_0"; - case ByteCode.DSTORE_1: return "dstore_1"; - case ByteCode.DSTORE_2: return "dstore_2"; - case ByteCode.DSTORE_3: return "dstore_3"; - case ByteCode.ASTORE_0: return "astore_0"; - case ByteCode.ASTORE_1: return "astore_1"; - case ByteCode.ASTORE_2: return "astore_2"; - case ByteCode.ASTORE_3: return "astore_3"; - case ByteCode.IASTORE: return "iastore"; - case ByteCode.LASTORE: return "lastore"; - case ByteCode.FASTORE: return "fastore"; - case ByteCode.DASTORE: return "dastore"; - case ByteCode.AASTORE: return "aastore"; - case ByteCode.BASTORE: return "bastore"; - case ByteCode.CASTORE: return "castore"; - case ByteCode.SASTORE: return "sastore"; - case ByteCode.POP: return "pop"; - case ByteCode.POP2: return "pop2"; - case ByteCode.DUP: return "dup"; - case ByteCode.DUP_X1: return "dup_x1"; - case ByteCode.DUP_X2: return "dup_x2"; - case ByteCode.DUP2: return "dup2"; - case ByteCode.DUP2_X1: return "dup2_x1"; - case ByteCode.DUP2_X2: return "dup2_x2"; - case ByteCode.SWAP: return "swap"; - case ByteCode.IADD: return "iadd"; - case ByteCode.LADD: return "ladd"; - case ByteCode.FADD: return "fadd"; - case ByteCode.DADD: return "dadd"; - case ByteCode.ISUB: return "isub"; - case ByteCode.LSUB: return "lsub"; - case ByteCode.FSUB: return "fsub"; - case ByteCode.DSUB: return "dsub"; - case ByteCode.IMUL: return "imul"; - case ByteCode.LMUL: return "lmul"; - case ByteCode.FMUL: return "fmul"; - case ByteCode.DMUL: return "dmul"; - case ByteCode.IDIV: return "idiv"; - case ByteCode.LDIV: return "ldiv"; - case ByteCode.FDIV: return "fdiv"; - case ByteCode.DDIV: return "ddiv"; - case ByteCode.IREM: return "irem"; - case ByteCode.LREM: return "lrem"; - case ByteCode.FREM: return "frem"; - case ByteCode.DREM: return "drem"; - case ByteCode.INEG: return "ineg"; - case ByteCode.LNEG: return "lneg"; - case ByteCode.FNEG: return "fneg"; - case ByteCode.DNEG: return "dneg"; - case ByteCode.ISHL: return "ishl"; - case ByteCode.LSHL: return "lshl"; - case ByteCode.ISHR: return "ishr"; - case ByteCode.LSHR: return "lshr"; - case ByteCode.IUSHR: return "iushr"; - case ByteCode.LUSHR: return "lushr"; - case ByteCode.IAND: return "iand"; - case ByteCode.LAND: return "land"; - case ByteCode.IOR: return "ior"; - case ByteCode.LOR: return "lor"; - case ByteCode.IXOR: return "ixor"; - case ByteCode.LXOR: return "lxor"; - case ByteCode.IINC: return "iinc"; - case ByteCode.I2L: return "i2l"; - case ByteCode.I2F: return "i2f"; - case ByteCode.I2D: return "i2d"; - case ByteCode.L2I: return "l2i"; - case ByteCode.L2F: return "l2f"; - case ByteCode.L2D: return "l2d"; - case ByteCode.F2I: return "f2i"; - case ByteCode.F2L: return "f2l"; - case ByteCode.F2D: return "f2d"; - case ByteCode.D2I: return "d2i"; - case ByteCode.D2L: return "d2l"; - case ByteCode.D2F: return "d2f"; - case ByteCode.I2B: return "i2b"; - case ByteCode.I2C: return "i2c"; - case ByteCode.I2S: return "i2s"; - case ByteCode.LCMP: return "lcmp"; - case ByteCode.FCMPL: return "fcmpl"; - case ByteCode.FCMPG: return "fcmpg"; - case ByteCode.DCMPL: return "dcmpl"; - case ByteCode.DCMPG: return "dcmpg"; - case ByteCode.IFEQ: return "ifeq"; - case ByteCode.IFNE: return "ifne"; - case ByteCode.IFLT: return "iflt"; - case ByteCode.IFGE: return "ifge"; - case ByteCode.IFGT: return "ifgt"; - case ByteCode.IFLE: return "ifle"; - case ByteCode.IF_ICMPEQ: return "if_icmpeq"; - case ByteCode.IF_ICMPNE: return "if_icmpne"; - case ByteCode.IF_ICMPLT: return "if_icmplt"; - case ByteCode.IF_ICMPGE: return "if_icmpge"; - case ByteCode.IF_ICMPGT: return "if_icmpgt"; - case ByteCode.IF_ICMPLE: return "if_icmple"; - case ByteCode.IF_ACMPEQ: return "if_acmpeq"; - case ByteCode.IF_ACMPNE: return "if_acmpne"; - case ByteCode.GOTO: return "goto"; - case ByteCode.JSR: return "jsr"; - case ByteCode.RET: return "ret"; - case ByteCode.TABLESWITCH: return "tableswitch"; - case ByteCode.LOOKUPSWITCH: return "lookupswitch"; - case ByteCode.IRETURN: return "ireturn"; - case ByteCode.LRETURN: return "lreturn"; - case ByteCode.FRETURN: return "freturn"; - case ByteCode.DRETURN: return "dreturn"; - case ByteCode.ARETURN: return "areturn"; - case ByteCode.RETURN: return "return"; - case ByteCode.GETSTATIC: return "getstatic"; - case ByteCode.PUTSTATIC: return "putstatic"; - case ByteCode.GETFIELD: return "getfield"; - case ByteCode.PUTFIELD: return "putfield"; - case ByteCode.INVOKEVIRTUAL: return "invokevirtual"; - case ByteCode.INVOKESPECIAL: return "invokespecial"; - case ByteCode.INVOKESTATIC: return "invokestatic"; - case ByteCode.INVOKEINTERFACE: return "invokeinterface"; - case ByteCode.NEW: return "new"; - case ByteCode.NEWARRAY: return "newarray"; - case ByteCode.ANEWARRAY: return "anewarray"; - case ByteCode.ARRAYLENGTH: return "arraylength"; - case ByteCode.ATHROW: return "athrow"; - case ByteCode.CHECKCAST: return "checkcast"; - case ByteCode.INSTANCEOF: return "instanceof"; - case ByteCode.MONITORENTER: return "monitorenter"; - case ByteCode.MONITOREXIT: return "monitorexit"; - case ByteCode.WIDE: return "wide"; - case ByteCode.MULTIANEWARRAY: return "multianewarray"; - case ByteCode.IFNULL: return "ifnull"; - case ByteCode.IFNONNULL: return "ifnonnull"; - case ByteCode.GOTO_W: return "goto_w"; - case ByteCode.JSR_W: return "jsr_w"; - case ByteCode.BREAKPOINT: return "breakpoint"; - - case ByteCode.IMPDEP1: return "impdep1"; - case ByteCode.IMPDEP2: return "impdep2"; - } - } - return ""; - } - - final char[] getCharBuffer(int minimalSize) - { - if (minimalSize > tmpCharBuffer.length) { - int newSize = tmpCharBuffer.length * 2; - if (minimalSize > newSize) { newSize = minimalSize; } - tmpCharBuffer = new char[newSize]; - } - return tmpCharBuffer; - } - - private static final int LineNumberTableSize = 16; - private static final int ExceptionTableSize = 4; - - private final static long FileHeaderConstant = 0xCAFEBABE0003002DL; - // Set DEBUG flags to true to get better checking and progress info. - private static final boolean DEBUGSTACK = false; - private static final boolean DEBUGLABELS = false; - private static final boolean DEBUGCODE = false; - - private String generatedClassName; - - private ExceptionTableEntry itsExceptionTable[]; - private int itsExceptionTableTop; - - private int itsLineNumberTable[]; // pack start_pc & line_number together - private int itsLineNumberTableTop; - - private byte[] itsCodeBuffer = new byte[256]; - private int itsCodeBufferTop; - - private ConstantPool itsConstantPool; - - private ClassFileMethod itsCurrentMethod; - private short itsStackTop; - - private short itsMaxStack; - private short itsMaxLocals; - - private ObjArray itsMethods = new ObjArray(); - private ObjArray itsFields = new ObjArray(); - private ObjArray itsInterfaces = new ObjArray(); - - private short itsFlags; - private short itsThisClassIndex; - private short itsSuperClassIndex; - private short itsSourceFileNameIndex; - - private static final int MIN_LABEL_TABLE_SIZE = 32; - private int[] itsLabelTable; - private int itsLabelTableTop; - -// itsFixupTable[i] = (label_index << 32) | fixup_site - private static final int MIN_FIXUP_TABLE_SIZE = 40; - private long[] itsFixupTable; - private int itsFixupTableTop; - private ObjArray itsVarDescriptors; - - private char[] tmpCharBuffer = new char[64]; -} - -final class ExceptionTableEntry -{ - - ExceptionTableEntry(int startLabel, int endLabel, - int handlerLabel, short catchType) - { - itsStartLabel = startLabel; - itsEndLabel = endLabel; - itsHandlerLabel = handlerLabel; - itsCatchType = catchType; - } - - int itsStartLabel; - int itsEndLabel; - int itsHandlerLabel; - short itsCatchType; -} - -final class ClassFileField -{ - - ClassFileField(short nameIndex, short typeIndex, short flags) - { - itsNameIndex = nameIndex; - itsTypeIndex = typeIndex; - itsFlags = flags; - itsHasAttributes = false; - } - - void setAttributes(short attr1, short attr2, short attr3, int index) - { - itsHasAttributes = true; - itsAttr1 = attr1; - itsAttr2 = attr2; - itsAttr3 = attr3; - itsIndex = index; - } - - int write(byte[] data, int offset) - { - offset = ClassFileWriter.putInt16(itsFlags, data, offset); - offset = ClassFileWriter.putInt16(itsNameIndex, data, offset); - offset = ClassFileWriter.putInt16(itsTypeIndex, data, offset); - if (!itsHasAttributes) { - // write 0 attributes - offset = ClassFileWriter.putInt16(0, data, offset); - } else { - offset = ClassFileWriter.putInt16(1, data, offset); - offset = ClassFileWriter.putInt16(itsAttr1, data, offset); - offset = ClassFileWriter.putInt16(itsAttr2, data, offset); - offset = ClassFileWriter.putInt16(itsAttr3, data, offset); - offset = ClassFileWriter.putInt16(itsIndex, data, offset); - } - return offset; - } - - int getWriteSize() - { - int size = 2 * 3; - if (!itsHasAttributes) { - size += 2; - } else { - size += 2 + 2 * 4; - } - return size; - } - - private short itsNameIndex; - private short itsTypeIndex; - private short itsFlags; - private boolean itsHasAttributes; - private short itsAttr1, itsAttr2, itsAttr3; - private int itsIndex; -} - -final class ClassFileMethod -{ - - ClassFileMethod(short nameIndex, short typeIndex, short flags) - { - itsNameIndex = nameIndex; - itsTypeIndex = typeIndex; - itsFlags = flags; - } - - void setCodeAttribute(byte codeAttribute[]) - { - itsCodeAttribute = codeAttribute; - } - - int write(byte[] data, int offset) - { - offset = ClassFileWriter.putInt16(itsFlags, data, offset); - offset = ClassFileWriter.putInt16(itsNameIndex, data, offset); - offset = ClassFileWriter.putInt16(itsTypeIndex, data, offset); - // Code attribute only - offset = ClassFileWriter.putInt16(1, data, offset); - System.arraycopy(itsCodeAttribute, 0, data, offset, - itsCodeAttribute.length); - offset += itsCodeAttribute.length; - return offset; - } - - int getWriteSize() - { - return 2 * 4 + itsCodeAttribute.length; - } - - private short itsNameIndex; - private short itsTypeIndex; - private short itsFlags; - private byte[] itsCodeAttribute; - -} - -final class ConstantPool -{ - - ConstantPool(ClassFileWriter cfw) - { - this.cfw = cfw; - itsTopIndex = 1; // the zero'th entry is reserved - itsPool = new byte[ConstantPoolSize]; - itsTop = 0; - } - - private static final int ConstantPoolSize = 256; - private static final byte - CONSTANT_Class = 7, - CONSTANT_Fieldref = 9, - CONSTANT_Methodref = 10, - CONSTANT_InterfaceMethodref = 11, - CONSTANT_String = 8, - CONSTANT_Integer = 3, - CONSTANT_Float = 4, - CONSTANT_Long = 5, - CONSTANT_Double = 6, - CONSTANT_NameAndType = 12, - CONSTANT_Utf8 = 1; - - int write(byte[] data, int offset) - { - offset = ClassFileWriter.putInt16((short)itsTopIndex, data, offset); - System.arraycopy(itsPool, 0, data, offset, itsTop); - offset += itsTop; - return offset; - } - - int getWriteSize() - { - return 2 + itsTop; - } - - int addConstant(int k) - { - ensure(5); - itsPool[itsTop++] = CONSTANT_Integer; - itsTop = ClassFileWriter.putInt32(k, itsPool, itsTop); - return (short)(itsTopIndex++); - } - - int addConstant(long k) - { - ensure(9); - itsPool[itsTop++] = CONSTANT_Long; - itsTop = ClassFileWriter.putInt64(k, itsPool, itsTop); - int index = itsTopIndex; - itsTopIndex += 2; - return index; - } - - int addConstant(float k) - { - ensure(5); - itsPool[itsTop++] = CONSTANT_Float; - int bits = Float.floatToIntBits(k); - itsTop = ClassFileWriter.putInt32(bits, itsPool, itsTop); - return itsTopIndex++; - } - - int addConstant(double k) - { - ensure(9); - itsPool[itsTop++] = CONSTANT_Double; - long bits = Double.doubleToLongBits(k); - itsTop = ClassFileWriter.putInt64(bits, itsPool, itsTop); - int index = itsTopIndex; - itsTopIndex += 2; - return index; - } - - int addConstant(String k) - { - int utf8Index = 0xFFFF & addUtf8(k); - int theIndex = itsStringConstHash.getInt(utf8Index, -1); - if (theIndex == -1) { - theIndex = itsTopIndex++; - ensure(3); - itsPool[itsTop++] = CONSTANT_String; - itsTop = ClassFileWriter.putInt16(utf8Index, itsPool, itsTop); - itsStringConstHash.put(utf8Index, theIndex); - } - return theIndex; - } - - boolean isUnderUtfEncodingLimit(String s) - { - int strLen = s.length(); - if (strLen * 3 <= MAX_UTF_ENCODING_SIZE) { - return true; - } else if (strLen > MAX_UTF_ENCODING_SIZE) { - return false; - } - return strLen == getUtfEncodingLimit(s, 0, strLen); - } - - /** - * Get maximum i such that <tt>start <= i <= end</tt> and - * <tt>s.substring(start, i)</tt> fits JVM UTF string encoding limit. - */ - int getUtfEncodingLimit(String s, int start, int end) - { - if ((end - start) * 3 <= MAX_UTF_ENCODING_SIZE) { - return end; - } - int limit = MAX_UTF_ENCODING_SIZE; - for (int i = start; i != end; i++) { - int c = s.charAt(i); - if (0 != c && c <= 0x7F) { - --limit; - } else if (c < 0x7FF) { - limit -= 2; - } else { - limit -= 3; - } - if (limit < 0) { - return i; - } - } - return end; - } - - short addUtf8(String k) - { - int theIndex = itsUtf8Hash.get(k, -1); - if (theIndex == -1) { - int strLen = k.length(); - boolean tooBigString; - if (strLen > MAX_UTF_ENCODING_SIZE) { - tooBigString = true; - } else { - tooBigString = false; - // Ask for worst case scenario buffer when each char takes 3 - // bytes - ensure(1 + 2 + strLen * 3); - int top = itsTop; - - itsPool[top++] = CONSTANT_Utf8; - top += 2; // skip length - - char[] chars = cfw.getCharBuffer(strLen); - k.getChars(0, strLen, chars, 0); - - for (int i = 0; i != strLen; i++) { - int c = chars[i]; - if (c != 0 && c <= 0x7F) { - itsPool[top++] = (byte)c; - } else if (c > 0x7FF) { - itsPool[top++] = (byte)(0xE0 | (c >> 12)); - itsPool[top++] = (byte)(0x80 | ((c >> 6) & 0x3F)); - itsPool[top++] = (byte)(0x80 | (c & 0x3F)); - } else { - itsPool[top++] = (byte)(0xC0 | (c >> 6)); - itsPool[top++] = (byte)(0x80 | (c & 0x3F)); - } - } - - int utfLen = top - (itsTop + 1 + 2); - if (utfLen > MAX_UTF_ENCODING_SIZE) { - tooBigString = true; - } else { - // Write back length - itsPool[itsTop + 1] = (byte)(utfLen >>> 8); - itsPool[itsTop + 2] = (byte)utfLen; - - itsTop = top; - theIndex = itsTopIndex++; - itsUtf8Hash.put(k, theIndex); - } - } - if (tooBigString) { - throw new IllegalArgumentException("Too big string"); - } - } - return (short)theIndex; - } - - private short addNameAndType(String name, String type) - { - short nameIndex = addUtf8(name); - short typeIndex = addUtf8(type); - ensure(5); - itsPool[itsTop++] = CONSTANT_NameAndType; - itsTop = ClassFileWriter.putInt16(nameIndex, itsPool, itsTop); - itsTop = ClassFileWriter.putInt16(typeIndex, itsPool, itsTop); - return (short)(itsTopIndex++); - } - - short addClass(String className) - { - int theIndex = itsClassHash.get(className, -1); - if (theIndex == -1) { - String slashed = className; - if (className.indexOf('.') > 0) { - slashed = ClassFileWriter.getSlashedForm(className); - theIndex = itsClassHash.get(slashed, -1); - if (theIndex != -1) { - itsClassHash.put(className, theIndex); - } - } - if (theIndex == -1) { - int utf8Index = addUtf8(slashed); - ensure(3); - itsPool[itsTop++] = CONSTANT_Class; - itsTop = ClassFileWriter.putInt16(utf8Index, itsPool, itsTop); - theIndex = itsTopIndex++; - itsClassHash.put(slashed, theIndex); - if (className != slashed) { - itsClassHash.put(className, theIndex); - } - } - } - return (short)theIndex; - } - - short addFieldRef(String className, String fieldName, String fieldType) - { - FieldOrMethodRef ref = new FieldOrMethodRef(className, fieldName, - fieldType); - - int theIndex = itsFieldRefHash.get(ref, -1); - if (theIndex == -1) { - short ntIndex = addNameAndType(fieldName, fieldType); - short classIndex = addClass(className); - ensure(5); - itsPool[itsTop++] = CONSTANT_Fieldref; - itsTop = ClassFileWriter.putInt16(classIndex, itsPool, itsTop); - itsTop = ClassFileWriter.putInt16(ntIndex, itsPool, itsTop); - theIndex = itsTopIndex++; - itsFieldRefHash.put(ref, theIndex); - } - return (short)theIndex; - } - - short addMethodRef(String className, String methodName, - String methodType) - { - FieldOrMethodRef ref = new FieldOrMethodRef(className, methodName, - methodType); - - int theIndex = itsMethodRefHash.get(ref, -1); - if (theIndex == -1) { - short ntIndex = addNameAndType(methodName, methodType); - short classIndex = addClass(className); - ensure(5); - itsPool[itsTop++] = CONSTANT_Methodref; - itsTop = ClassFileWriter.putInt16(classIndex, itsPool, itsTop); - itsTop = ClassFileWriter.putInt16(ntIndex, itsPool, itsTop); - theIndex = itsTopIndex++; - itsMethodRefHash.put(ref, theIndex); - } - return (short)theIndex; - } - - short addInterfaceMethodRef(String className, - String methodName, String methodType) - { - short ntIndex = addNameAndType(methodName, methodType); - short classIndex = addClass(className); - ensure(5); - itsPool[itsTop++] = CONSTANT_InterfaceMethodref; - itsTop = ClassFileWriter.putInt16(classIndex, itsPool, itsTop); - itsTop = ClassFileWriter.putInt16(ntIndex, itsPool, itsTop); - return (short)(itsTopIndex++); - } - - void ensure(int howMuch) - { - if (itsTop + howMuch > itsPool.length) { - int newCapacity = itsPool.length * 2; - if (itsTop + howMuch > newCapacity) { - newCapacity = itsTop + howMuch; - } - byte[] tmp = new byte[newCapacity]; - System.arraycopy(itsPool, 0, tmp, 0, itsTop); - itsPool = tmp; - } - } - - private ClassFileWriter cfw; - - private static final int MAX_UTF_ENCODING_SIZE = 65535; - - private UintMap itsStringConstHash = new UintMap(); - private ObjToIntMap itsUtf8Hash = new ObjToIntMap(); - private ObjToIntMap itsFieldRefHash = new ObjToIntMap(); - private ObjToIntMap itsMethodRefHash = new ObjToIntMap(); - private ObjToIntMap itsClassHash = new ObjToIntMap(); - - private int itsTop; - private int itsTopIndex; - private byte itsPool[]; -} - -final class FieldOrMethodRef -{ - FieldOrMethodRef(String className, String name, String type) - { - this.className = className; - this.name = name; - this.type = type; - } - - public boolean equals(Object obj) - { - if (!(obj instanceof FieldOrMethodRef)) { return false; } - FieldOrMethodRef x = (FieldOrMethodRef)obj; - return className.equals(x.className) - && name.equals(x.name) - && type.equals(x.type); - } - - public int hashCode() - { - if (hashCode == -1) { - int h1 = className.hashCode(); - int h2 = name.hashCode(); - int h3 = type.hashCode(); - hashCode = h1 ^ h2 ^ h3; - } - return hashCode; - } - - private String className; - private String name; - private String type; - private int hashCode = -1; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Arguments.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Arguments.java deleted file mode 100644 index 954b078..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Arguments.java +++ /dev/null @@ -1,311 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class implements the "arguments" object. - * - * See ECMA 10.1.8 - * - * @see org.mozilla.javascript.NativeCall - * @author Norris Boyd - */ -final class Arguments extends IdScriptableObject -{ - static final long serialVersionUID = 4275508002492040609L; - - public Arguments(NativeCall activation) - { - this.activation = activation; - - Scriptable parent = activation.getParentScope(); - setParentScope(parent); - setPrototype(ScriptableObject.getObjectPrototype(parent)); - - args = activation.originalArgs; - lengthObj = new Integer(args.length); - - NativeFunction f = activation.function; - calleeObj = f; - - int version = f.getLanguageVersion(); - if (version <= Context.VERSION_1_3 - && version != Context.VERSION_DEFAULT) - { - callerObj = null; - } else { - callerObj = NOT_FOUND; - } - } - - public String getClassName() - { - return "Object"; - } - - public boolean has(int index, Scriptable start) - { - if (0 <= index && index < args.length) { - if (args[index] != NOT_FOUND) { - return true; - } - } - return super.has(index, start); - } - - public Object get(int index, Scriptable start) - { - if (0 <= index && index < args.length) { - Object value = args[index]; - if (value != NOT_FOUND) { - if (sharedWithActivation(index)) { - NativeFunction f = activation.function; - String argName = f.getParamOrVarName(index); - value = activation.get(argName, activation); - if (value == NOT_FOUND) Kit.codeBug(); - } - return value; - } - } - return super.get(index, start); - } - - private boolean sharedWithActivation(int index) - { - NativeFunction f = activation.function; - int definedCount = f.getParamCount(); - if (index < definedCount) { - // Check if argument is not hidden by later argument with the same - // name as hidden arguments are not shared with activation - if (index < definedCount - 1) { - String argName = f.getParamOrVarName(index); - for (int i = index + 1; i < definedCount; i++) { - if (argName.equals(f.getParamOrVarName(i))) { - return false; - } - } - } - return true; - } - return false; - } - - public void put(int index, Scriptable start, Object value) - { - if (0 <= index && index < args.length) { - if (args[index] != NOT_FOUND) { - if (sharedWithActivation(index)) { - String argName; - argName = activation.function.getParamOrVarName(index); - activation.put(argName, activation, value); - return; - } - synchronized (this) { - if (args[index] != NOT_FOUND) { - if (args == activation.originalArgs) { - args = args.clone(); - } - args[index] = value; - return; - } - } - } - } - super.put(index, start, value); - } - - public void delete(int index) - { - if (0 <= index && index < args.length) { - synchronized (this) { - if (args[index] != NOT_FOUND) { - if (args == activation.originalArgs) { - args = args.clone(); - } - args[index] = NOT_FOUND; - return; - } - } - } - super.delete(index); - } - -// #string_id_map# - - private static final int - Id_callee = 1, - Id_length = 2, - Id_caller = 3, - - MAX_INSTANCE_ID = 3; - - protected int getMaxInstanceId() - { - return MAX_INSTANCE_ID; - } - - protected int findInstanceIdInfo(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:15:04 EDT - L0: { id = 0; String X = null; int c; - if (s.length()==6) { - c=s.charAt(5); - if (c=='e') { X="callee";id=Id_callee; } - else if (c=='h') { X="length";id=Id_length; } - else if (c=='r') { X="caller";id=Id_caller; } - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - - if (id == 0) return super.findInstanceIdInfo(s); - - int attr; - switch (id) { - case Id_callee: - case Id_caller: - case Id_length: - attr = DONTENUM; - break; - default: throw new IllegalStateException(); - } - return instanceIdInfo(attr, id); - } - -// #/string_id_map# - - protected String getInstanceIdName(int id) - { - switch (id) { - case Id_callee: return "callee"; - case Id_length: return "length"; - case Id_caller: return "caller"; - } - return null; - } - - protected Object getInstanceIdValue(int id) - { - switch (id) { - case Id_callee: return calleeObj; - case Id_length: return lengthObj; - case Id_caller: { - Object value = callerObj; - if (value == UniqueTag.NULL_VALUE) { value = null; } - else if (value == null) { - NativeCall caller = activation.parentActivationCall; - if (caller != null) { - value = caller.get("arguments", caller); - } - } - return value; - } - } - return super.getInstanceIdValue(id); - } - - protected void setInstanceIdValue(int id, Object value) - { - switch (id) { - case Id_callee: calleeObj = value; return; - case Id_length: lengthObj = value; return; - case Id_caller: - callerObj = (value != null) ? value : UniqueTag.NULL_VALUE; - return; - } - super.setInstanceIdValue(id, value); - } - - Object[] getIds(boolean getAll) - { - Object[] ids = super.getIds(getAll); - if (getAll && args.length != 0) { - boolean[] present = null; - int extraCount = args.length; - for (int i = 0; i != ids.length; ++i) { - Object id = ids[i]; - if (id instanceof Integer) { - int index = ((Integer)id).intValue(); - if (0 <= index && index < args.length) { - if (present == null) { - present = new boolean[args.length]; - } - if (!present[index]) { - present[index] = true; - extraCount--; - } - } - } - } - if (extraCount != 0) { - Object[] tmp = new Object[extraCount + ids.length]; - System.arraycopy(ids, 0, tmp, extraCount, ids.length); - ids = tmp; - int offset = 0; - for (int i = 0; i != args.length; ++i) { - if (present == null || !present[i]) { - ids[offset] = new Integer(i); - ++offset; - } - } - if (offset != extraCount) Kit.codeBug(); - } - } - return ids; - } - -// Fields to hold caller, callee and length properties, -// where NOT_FOUND value tags deleted properties. -// In addition if callerObj == NULL_VALUE, it tags null for scripts, as -// initial callerObj == null means access to caller arguments available -// only in JS <= 1.3 scripts - private Object callerObj; - private Object calleeObj; - private Object lengthObj; - - private NativeCall activation; - -// Initially args holds activation.getOriginalArgs(), but any modification -// of its elements triggers creation of a copy. If its element holds NOT_FOUND, -// it indicates deleted index, in which case super class is queried. - private Object[] args; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/BaseFunction.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/BaseFunction.java deleted file mode 100644 index d7d8992..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/BaseFunction.java +++ /dev/null @@ -1,553 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Roger Lawrence - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * The base class for Function objects - * See ECMA 15.3. - * @author Norris Boyd - */ -public class BaseFunction extends IdScriptableObject implements Function -{ - - static final long serialVersionUID = 5311394446546053859L; - - private static final Object FUNCTION_TAG = new Object(); - - static void init(Scriptable scope, boolean sealed) - { - BaseFunction obj = new BaseFunction(); - // Function.prototype attributes: see ECMA 15.3.3.1 - obj.prototypePropertyAttributes = DONTENUM | READONLY | PERMANENT; - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - public BaseFunction() - { - } - - public BaseFunction(Scriptable scope, Scriptable prototype) - { - super(scope, prototype); - } - - public String getClassName() { - return "Function"; - } - - /** - * Implements the instanceof operator for JavaScript Function objects. - * <p> - * <code> - * foo = new Foo();<br> - * foo instanceof Foo; // true<br> - * </code> - * - * @param instance The value that appeared on the LHS of the instanceof - * operator - * @return true if the "prototype" property of "this" appears in - * value's prototype chain - * - */ - public boolean hasInstance(Scriptable instance) - { - Object protoProp = ScriptableObject.getProperty(this, "prototype"); - if (protoProp instanceof Scriptable) { - return ScriptRuntime.jsDelegatesTo(instance, (Scriptable)protoProp); - } - throw ScriptRuntime.typeError1("msg.instanceof.bad.prototype", - getFunctionName()); - } - -// #string_id_map# - - private static final int - Id_length = 1, - Id_arity = 2, - Id_name = 3, - Id_prototype = 4, - Id_arguments = 5, - - MAX_INSTANCE_ID = 5; - - protected int getMaxInstanceId() - { - return MAX_INSTANCE_ID; - } - - protected int findInstanceIdInfo(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:15:15 EDT - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 4: X="name";id=Id_name; break L; - case 5: X="arity";id=Id_arity; break L; - case 6: X="length";id=Id_length; break L; - case 9: c=s.charAt(0); - if (c=='a') { X="arguments";id=Id_arguments; } - else if (c=='p') { X="prototype";id=Id_prototype; } - break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# -// #/string_id_map# - - if (id == 0) return super.findInstanceIdInfo(s); - - int attr; - switch (id) { - case Id_length: - case Id_arity: - case Id_name: - attr = DONTENUM | READONLY | PERMANENT; - break; - case Id_prototype: - attr = prototypePropertyAttributes; - break; - case Id_arguments: - attr = DONTENUM | PERMANENT; - break; - default: throw new IllegalStateException(); - } - return instanceIdInfo(attr, id); - } - - protected String getInstanceIdName(int id) - { - switch (id) { - case Id_length: return "length"; - case Id_arity: return "arity"; - case Id_name: return "name"; - case Id_prototype: return "prototype"; - case Id_arguments: return "arguments"; - } - return super.getInstanceIdName(id); - } - - protected Object getInstanceIdValue(int id) - { - switch (id) { - case Id_length: return ScriptRuntime.wrapInt(getLength()); - case Id_arity: return ScriptRuntime.wrapInt(getArity()); - case Id_name: return getFunctionName(); - case Id_prototype: return getPrototypeProperty(); - case Id_arguments: return getArguments(); - } - return super.getInstanceIdValue(id); - } - - protected void setInstanceIdValue(int id, Object value) - { - if (id == Id_prototype) { - if ((prototypePropertyAttributes & READONLY) == 0) { - prototypeProperty = (value != null) - ? value : UniqueTag.NULL_VALUE; - } - return; - } else if (id == Id_arguments) { - if (value == NOT_FOUND) { - // This should not be called since "arguments" is PERMANENT - Kit.codeBug(); - } - defaultPut("arguments", value); - } - super.setInstanceIdValue(id, value); - } - - protected void fillConstructorProperties(IdFunctionObject ctor) - { - // Fix up bootstrapping problem: getPrototype of the IdFunctionObject - // can not return Function.prototype because Function object is not - // yet defined. - ctor.setPrototype(this); - super.fillConstructorProperties(ctor); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=1; s="constructor"; break; - case Id_toString: arity=1; s="toString"; break; - case Id_toSource: arity=1; s="toSource"; break; - case Id_apply: arity=2; s="apply"; break; - case Id_call: arity=1; s="call"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(FUNCTION_TAG, id, s, arity); - } - - static boolean isApply(IdFunctionObject f) { - return f.hasTag(FUNCTION_TAG) && f.methodId() == Id_apply; - } - - static boolean isApplyOrCall(IdFunctionObject f) { - if(f.hasTag(FUNCTION_TAG)) { - switch(f.methodId()) { - case Id_apply: - case Id_call: - return true; - } - } - return false; - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(FUNCTION_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case Id_constructor: - return jsConstructor(cx, scope, args); - - case Id_toString: { - BaseFunction realf = realFunction(thisObj, f); - int indent = ScriptRuntime.toInt32(args, 0); - return realf.decompile(indent, 0); - } - - case Id_toSource: { - BaseFunction realf = realFunction(thisObj, f); - int indent = 0; - int flags = Decompiler.TO_SOURCE_FLAG; - if (args.length != 0) { - indent = ScriptRuntime.toInt32(args[0]); - if (indent >= 0) { - flags = 0; - } else { - indent = 0; - } - } - return realf.decompile(indent, flags); - } - - case Id_apply: - case Id_call: - return ScriptRuntime.applyOrCall(id == Id_apply, - cx, scope, thisObj, args); - } - throw new IllegalArgumentException(String.valueOf(id)); - } - - private BaseFunction realFunction(Scriptable thisObj, IdFunctionObject f) - { - Object x = thisObj.getDefaultValue(ScriptRuntime.FunctionClass); - if (x instanceof BaseFunction) { - return (BaseFunction)x; - } - throw ScriptRuntime.typeError1("msg.incompat.call", - f.getFunctionName()); - } - - /** - * Make value as DontEnum, DontDelete, ReadOnly - * prototype property of this Function object - */ - public void setImmunePrototypeProperty(Object value) - { - if ((prototypePropertyAttributes & READONLY) != 0) { - throw new IllegalStateException(); - } - prototypeProperty = (value != null) ? value : UniqueTag.NULL_VALUE; - prototypePropertyAttributes = DONTENUM | PERMANENT | READONLY; - } - - protected Scriptable getClassPrototype() - { - Object protoVal = getPrototypeProperty(); - if (protoVal instanceof Scriptable) { - return (Scriptable) protoVal; - } - return getClassPrototype(this, "Object"); - } - - /** - * Should be overridden. - */ - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - return Undefined.instance; - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) - { - Scriptable result = createObject(cx, scope); - if (result != null) { - Object val = call(cx, scope, result, args); - if (val instanceof Scriptable) { - result = (Scriptable)val; - } - } else { - Object val = call(cx, scope, null, args); - if (!(val instanceof Scriptable)) { - // It is program error not to return Scriptable from - // the call method if createObject returns null. - throw new IllegalStateException( - "Bad implementaion of call as constructor, name=" - +getFunctionName()+" in "+getClass().getName()); - } - result = (Scriptable)val; - if (result.getPrototype() == null) { - result.setPrototype(getClassPrototype()); - } - if (result.getParentScope() == null) { - Scriptable parent = getParentScope(); - if (result != parent) { - result.setParentScope(parent); - } - } - } - return result; - } - - /** - * Creates new script object. - * The default implementation of {@link #construct} uses the method to - * to get the value for <tt>thisObj</tt> argument when invoking - * {@link #call}. - * The methos is allowed to return <tt>null</tt> to indicate that - * {@link #call} will create a new object itself. In this case - * {@link #construct} will set scope and prototype on the result - * {@link #call} unless they are already set. - */ - public Scriptable createObject(Context cx, Scriptable scope) - { - Scriptable newInstance = new NativeObject(); - newInstance.setPrototype(getClassPrototype()); - newInstance.setParentScope(getParentScope()); - return newInstance; - } - - /** - * Decompile the source information associated with this js - * function/script back into a string. - * - * @param indent How much to indent the decompiled result. - * - * @param flags Flags specifying format of decompilation output. - */ - String decompile(int indent, int flags) - { - StringBuffer sb = new StringBuffer(); - boolean justbody = (0 != (flags & Decompiler.ONLY_BODY_FLAG)); - if (!justbody) { - sb.append("function "); - sb.append(getFunctionName()); - sb.append("() {\n\t"); - } - sb.append("[native code, arity="); - sb.append(getArity()); - sb.append("]\n"); - if (!justbody) { - sb.append("}\n"); - } - return sb.toString(); - } - - public int getArity() { return 0; } - - public int getLength() { return 0; } - - public String getFunctionName() - { - return ""; - } - - final Object getPrototypeProperty() { - Object result = prototypeProperty; - if (result == null) { - synchronized (this) { - result = prototypeProperty; - if (result == null) { - setupDefaultPrototype(); - result = prototypeProperty; - } - } - } - else if (result == UniqueTag.NULL_VALUE) { result = null; } - return result; - } - - private void setupDefaultPrototype() - { - NativeObject obj = new NativeObject(); - final int attr = ScriptableObject.DONTENUM; - obj.defineProperty("constructor", this, attr); - // put the prototype property into the object now, then in the - // wacky case of a user defining a function Object(), we don't - // get an infinite loop trying to find the prototype. - prototypeProperty = obj; - Scriptable proto = getObjectPrototype(this); - if (proto != obj) { - // not the one we just made, it must remain grounded - obj.setPrototype(proto); - } - } - - private Object getArguments() - { - // <Function name>.arguments is deprecated, so we use a slow - // way of getting it that doesn't add to the invocation cost. - // TODO: add warning, error based on version - Object value = defaultGet("arguments"); - if (value != NOT_FOUND) { - // Should after changing <Function name>.arguments its - // activation still be available during Function call? - // This code assumes it should not: - // defaultGet("arguments") != NOT_FOUND - // means assigned arguments - return value; - } - Context cx = Context.getContext(); - NativeCall activation = ScriptRuntime.findFunctionActivation(cx, this); - return (activation == null) - ? null - : activation.get("arguments", activation); - } - - private static Object jsConstructor(Context cx, Scriptable scope, - Object[] args) - { - int arglen = args.length; - StringBuffer sourceBuf = new StringBuffer(); - - sourceBuf.append("function "); - /* version != 1.2 Function constructor behavior - - * print 'anonymous' as the function name if the - * version (under which the function was compiled) is - * less than 1.2... or if it's greater than 1.2, because - * we need to be closer to ECMA. - */ - if (cx.getLanguageVersion() != Context.VERSION_1_2) { - sourceBuf.append("anonymous"); - } - sourceBuf.append('('); - - // Append arguments as coma separated strings - for (int i = 0; i < arglen - 1; i++) { - if (i > 0) { - sourceBuf.append(','); - } - sourceBuf.append(ScriptRuntime.toString(args[i])); - } - sourceBuf.append(") {"); - if (arglen != 0) { - // append function body - String funBody = ScriptRuntime.toString(args[arglen - 1]); - sourceBuf.append(funBody); - } - sourceBuf.append('}'); - String source = sourceBuf.toString(); - - int[] linep = new int[1]; - String filename = Context.getSourcePositionFromStack(linep); - if (filename == null) { - filename = "<eval'ed string>"; - linep[0] = 1; - } - - String sourceURI = ScriptRuntime. - makeUrlForGeneratedScript(false, filename, linep[0]); - - Scriptable global = ScriptableObject.getTopLevelScope(scope); - - ErrorReporter reporter; - reporter = DefaultErrorReporter.forEval(cx.getErrorReporter()); - - Evaluator evaluator = Context.createInterpreter(); - if (evaluator == null) { - throw new JavaScriptException("Interpreter not present", - filename, linep[0]); - } - - // Compile with explicit interpreter instance to force interpreter - // mode. - return cx.compileFunction(global, source, evaluator, reporter, - sourceURI, 1, null); - } - - protected int findPrototypeId(String s) - { - int id; -// #string_id_map# -// #generated# Last update: 2007-05-09 08:15:15 EDT - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 4: X="call";id=Id_call; break L; - case 5: X="apply";id=Id_apply; break L; - case 8: c=s.charAt(3); - if (c=='o') { X="toSource";id=Id_toSource; } - else if (c=='t') { X="toString";id=Id_toString; } - break L; - case 11: X="constructor";id=Id_constructor; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_constructor = 1, - Id_toString = 2, - Id_toSource = 3, - Id_apply = 4, - Id_call = 5, - - MAX_PROTOTYPE_ID = 5; - -// #/string_id_map# - - private Object prototypeProperty; - // For function object instances, attribute is PERMANENT; see ECMA 15.3.5.2 - private int prototypePropertyAttributes = PERMANENT; -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Callable.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Callable.java deleted file mode 100644 index 03e0fce..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Callable.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov, igor@fastmail.fm - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * Generic notion of callable object that can execute some script-related code - * upon request with specified values for script scope and this objects. - */ -public interface Callable -{ - /** - * Perform the call. - * - * @param cx the current Context for this thread - * @param scope the scope to use to resolve properties. - * @param thisObj the JavaScript <code>this</code> object - * @param args the array of arguments - * @return the result of the call - */ - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args); -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ClassCache.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ClassCache.java deleted file mode 100644 index 9047278..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ClassCache.java +++ /dev/null @@ -1,220 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov, igor@fastmail.fm - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.util.Map; -import java.util.HashMap; - -/** - * Cache of generated classes and data structures to access Java runtime - * from JavaScript. - * - * @author Igor Bukanov - * - * @since Rhino 1.5 Release 5 - */ -public class ClassCache -{ - private static final Object AKEY = new Object(); - private volatile boolean cachingIsEnabled = true; - private HashMap<Class<?>,JavaMembers> classTable - = new HashMap<Class<?>,JavaMembers>(); - private HashMap<Class<?>,JavaMembers> javaAdapterGeneratedClasses - = new HashMap<Class<?>,JavaMembers>(); - private HashMap<JavaAdapter.JavaAdapterSignature,Class<?>> classAdapterCache - = new HashMap<JavaAdapter.JavaAdapterSignature,Class<?>>(); - private HashMap<Class<?>,Object> interfaceAdapterCache; - private int generatedClassSerial; - - /** - * Search for ClassCache object in the given scope. - * The method first calls - * {@link ScriptableObject#getTopLevelScope(Scriptable scope)} - * to get the top most scope and then tries to locate associated - * ClassCache object in the prototype chain of the top scope. - * - * @param scope scope to search for ClassCache object. - * @return previously associated ClassCache object or a new instance of - * ClassCache if no ClassCache object was found. - * - * @see #associate(ScriptableObject topScope) - */ - public static ClassCache get(Scriptable scope) - { - ClassCache cache = (ClassCache) - ScriptableObject.getTopScopeValue(scope, AKEY); - if (cache == null) { - throw new RuntimeException("Can't find top level scope for " + - "ClassCache.get"); - } - return cache; - } - - /** - * Associate ClassCache object with the given top-level scope. - * The ClassCache object can only be associated with the given scope once. - * - * @param topScope scope to associate this ClassCache object with. - * @return true if no previous ClassCache objects were embedded into - * the scope and this ClassCache were successfully associated - * or false otherwise. - * - * @see #get(Scriptable scope) - */ - public boolean associate(ScriptableObject topScope) - { - if (topScope.getParentScope() != null) { - // Can only associate cache with top level scope - throw new IllegalArgumentException(); - } - if (this == topScope.associateValue(AKEY, this)) { - return true; - } - return false; - } - - /** - * Empty caches of generated Java classes and Java reflection information. - */ - public synchronized void clearCaches() - { - classTable.clear(); - javaAdapterGeneratedClasses.clear(); - classAdapterCache.clear(); - interfaceAdapterCache = null; - } - - /** - * Check if generated Java classes and Java reflection information - * is cached. - */ - public final boolean isCachingEnabled() - { - return cachingIsEnabled; - } - - /** - * Set whether to cache some values. - * <p> - * By default, the engine will cache the results of - * <tt>Class.getMethods()</tt> and similar calls. - * This can speed execution dramatically, but increases the memory - * footprint. Also, with caching enabled, references may be held to - * objects past the lifetime of any real usage. - * <p> - * If caching is enabled and this method is called with a - * <code>false</code> argument, the caches will be emptied. - * <p> - * Caching is enabled by default. - * - * @param enabled if true, caching is enabled - * - * @see #clearCaches() - */ - public synchronized void setCachingEnabled(boolean enabled) - { - if (enabled == cachingIsEnabled) - return; - if (!enabled) - clearCaches(); - cachingIsEnabled = enabled; - } - - /** - * @return a map from classes to associated JavaMembers objects - */ - Map<Class<?>,JavaMembers> getClassCacheMap() { - return classTable; - } - - Map<JavaAdapter.JavaAdapterSignature,Class<?>> getInterfaceAdapterCacheMap() - { - return classAdapterCache; - } - - /** - * @deprecated - * The method always returns false. - * @see #setInvokerOptimizationEnabled(boolean enabled) - */ - public boolean isInvokerOptimizationEnabled() - { - return false; - } - - /** - * @deprecated - * The method does nothing. - * Invoker optimization is no longer used by Rhino. - * On modern JDK like 1.4 or 1.5 the disadvantages of the optimization - * like increased memory usage or longer initialization time overweight - * small speed increase that can be gained using generated proxy class - * to replace reflection. - */ - public synchronized void setInvokerOptimizationEnabled(boolean enabled) - { - } - - /** - * Internal engine method to return serial number for generated classes - * to ensure name uniqueness. - */ - public final synchronized int newClassSerialNumber() - { - return ++generatedClassSerial; - } - - Object getInterfaceAdapter(Class<?> cl) - { - return interfaceAdapterCache == null - ? null - : interfaceAdapterCache.get(cl); - } - - synchronized void cacheInterfaceAdapter(Class<?> cl, Object iadapter) - { - if (cachingIsEnabled) { - if (interfaceAdapterCache == null) { - interfaceAdapterCache = new HashMap<Class<?>,Object>(); - } - interfaceAdapterCache.put(cl, iadapter); - } - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ClassShutter.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ClassShutter.java deleted file mode 100644 index d5f4cd6..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ClassShutter.java +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** -Embeddings that wish to filter Java classes that are visible to scripts -through the LiveConnect, should implement this interface. - -@see Context#setClassShutter(ClassShutter) -@since 1.5 Release 4 -@author Norris Boyd -*/ - - public interface ClassShutter { - - /** - * Return true iff the Java class with the given name should be exposed - * to scripts. - * <p> - * An embedding may filter which Java classes are exposed through - * LiveConnect to JavaScript scripts. - * <p> - * Due to the fact that there is no package reflection in Java, - * this method will also be called with package names. There - * is no way for Rhino to tell if "Packages.a.b" is a package name - * or a class that doesn't exist. What Rhino does is attempt - * to load each segment of "Packages.a.b.c": It first attempts to - * load class "a", then attempts to load class "a.b", then - * finally attempts to load class "a.b.c". On a Rhino installation - * without any ClassShutter set, and without any of the - * above classes, the expression "Packages.a.b.c" will result in - * a [JavaPackage a.b.c] and not an error. - * <p> - * With ClassShutter supplied, Rhino will first call - * visibleToScripts before attempting to look up the class name. If - * visibleToScripts returns false, the class name lookup is not - * performed and subsequent Rhino execution assumes the class is - * not present. So for "java.lang.System.out.println" the lookup - * of "java.lang.System" is skipped and thus Rhino assumes that - * "java.lang.System" doesn't exist. So then for "java.lang.System.out", - * Rhino attempts to load the class "java.lang.System.out" because - * it assumes that "java.lang.System" is a package name. - * <p> - * @param fullClassName the full name of the class (including the package - * name, with '.' as a delimiter). For example the - * standard string class is "java.lang.String" - * @return whether or not to reveal this class to scripts - */ - public boolean visibleToScripts(String fullClassName); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/CompilerEnvirons.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/CompilerEnvirons.java deleted file mode 100644 index 645d098..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/CompilerEnvirons.java +++ /dev/null @@ -1,233 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov, igor@fastmail.fm - * Bob Jervis - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.util.Hashtable; - -public class CompilerEnvirons -{ - public CompilerEnvirons() - { - errorReporter = DefaultErrorReporter.instance; - languageVersion = Context.VERSION_DEFAULT; - generateDebugInfo = true; - useDynamicScope = false; - reservedKeywordAsIdentifier = false; - allowMemberExprAsFunctionName = false; - xmlAvailable = true; - optimizationLevel = 0; - generatingSource = true; - strictMode = false; - warningAsError = false; - generateObserverCount = false; - } - - public void initFromContext(Context cx) - { - setErrorReporter(cx.getErrorReporter()); - this.languageVersion = cx.getLanguageVersion(); - useDynamicScope = cx.compileFunctionsWithDynamicScopeFlag; - generateDebugInfo = (!cx.isGeneratingDebugChanged() - || cx.isGeneratingDebug()); - reservedKeywordAsIdentifier - = cx.hasFeature(Context.FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER); - allowMemberExprAsFunctionName - = cx.hasFeature(Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME); - strictMode - = cx.hasFeature(Context.FEATURE_STRICT_MODE); - warningAsError = cx.hasFeature(Context.FEATURE_WARNING_AS_ERROR); - xmlAvailable - = cx.hasFeature(Context.FEATURE_E4X); - - optimizationLevel = cx.getOptimizationLevel(); - - generatingSource = cx.isGeneratingSource(); - activationNames = cx.activationNames; - - // Observer code generation in compiled code : - generateObserverCount = cx.generateObserverCount; - } - - public final ErrorReporter getErrorReporter() - { - return errorReporter; - } - - public void setErrorReporter(ErrorReporter errorReporter) - { - if (errorReporter == null) throw new IllegalArgumentException(); - this.errorReporter = errorReporter; - } - - public final int getLanguageVersion() - { - return languageVersion; - } - - public void setLanguageVersion(int languageVersion) - { - Context.checkLanguageVersion(languageVersion); - this.languageVersion = languageVersion; - } - - public final boolean isGenerateDebugInfo() - { - return generateDebugInfo; - } - - public void setGenerateDebugInfo(boolean flag) - { - this.generateDebugInfo = flag; - } - - public final boolean isUseDynamicScope() - { - return useDynamicScope; - } - - public final boolean isReservedKeywordAsIdentifier() - { - return reservedKeywordAsIdentifier; - } - - public void setReservedKeywordAsIdentifier(boolean flag) - { - reservedKeywordAsIdentifier = flag; - } - - public final boolean isAllowMemberExprAsFunctionName() - { - return allowMemberExprAsFunctionName; - } - - public void setAllowMemberExprAsFunctionName(boolean flag) - { - allowMemberExprAsFunctionName = flag; - } - - public final boolean isXmlAvailable() - { - return xmlAvailable; - } - - public void setXmlAvailable(boolean flag) - { - xmlAvailable = flag; - } - - public final int getOptimizationLevel() - { - return optimizationLevel; - } - - public void setOptimizationLevel(int level) - { - Context.checkOptimizationLevel(level); - this.optimizationLevel = level; - } - - public final boolean isGeneratingSource() - { - return generatingSource; - } - - public final boolean isStrictMode() - { - return strictMode; - } - - public final boolean reportWarningAsError() - { - return warningAsError; - } - - /** - * Specify whether or not source information should be generated. - * <p> - * Without source information, evaluating the "toString" method - * on JavaScript functions produces only "[native code]" for - * the body of the function. - * Note that code generated without source is not fully ECMA - * conformant. - */ - public void setGeneratingSource(boolean generatingSource) - { - this.generatingSource = generatingSource; - } - - /** - * @return true iff code will be generated with callbacks to enable - * instruction thresholds - */ - public boolean isGenerateObserverCount() { - return generateObserverCount; - } - - /** - * Turn on or off generation of code with callbacks to - * track the count of executed instructions. - * Currently only affects JVM byte code generation: this slows down the - * generated code, but code generated without the callbacks will not - * be counted toward instruction thresholds. Rhino's interpretive - * mode does instruction counting without inserting callbacks, so - * there is no requirement to compile code differently. - * @param generateObserverCount if true, generated code will contain - * calls to accumulate an estimate of the instructions executed. - */ - public void setGenerateObserverCount(boolean generateObserverCount) { - this.generateObserverCount = generateObserverCount; - } - - private ErrorReporter errorReporter; - - private int languageVersion; - private boolean generateDebugInfo; - private boolean useDynamicScope; - private boolean reservedKeywordAsIdentifier; - private boolean allowMemberExprAsFunctionName; - private boolean xmlAvailable; - private int optimizationLevel; - private boolean generatingSource; - private boolean strictMode; - private boolean warningAsError; - private boolean generateObserverCount; - Hashtable activationNames; -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ConstProperties.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ConstProperties.java deleted file mode 100644 index 860db79..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ConstProperties.java +++ /dev/null @@ -1,109 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Bob Jervis - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -public interface ConstProperties { - /** - * Sets a named const property in this object. - * <p> - * The property is specified by a string name - * as defined for <code>Scriptable.get</code>. - * <p> - * The possible values that may be passed in are as defined for - * <code>Scriptable.get</code>. A class that implements this method may choose - * to ignore calls to set certain properties, in which case those - * properties are effectively read-only.<p> - * For properties defined in a prototype chain, - * use <code>putProperty</code> in ScriptableObject. <p> - * Note that if a property <i>a</i> is defined in the prototype <i>p</i> - * of an object <i>o</i>, then evaluating <code>o.a = 23</code> will cause - * <code>set</code> to be called on the prototype <i>p</i> with - * <i>o</i> as the <i>start</i> parameter. - * To preserve JavaScript semantics, it is the Scriptable - * object's responsibility to modify <i>o</i>. <p> - * This design allows properties to be defined in prototypes and implemented - * in terms of getters and setters of Java values without consuming slots - * in each instance.<p> - * <p> - * The values that may be set are limited to the following: - * <UL> - * <LI>java.lang.Boolean objects</LI> - * <LI>java.lang.String objects</LI> - * <LI>java.lang.Number objects</LI> - * <LI>org.mozilla.javascript.Scriptable objects</LI> - * <LI>null</LI> - * <LI>The value returned by Context.getUndefinedValue()</LI> - * </UL><p> - * Arbitrary Java objects may be wrapped in a Scriptable by first calling - * <code>Context.toObject</code>. This allows the property of a JavaScript - * object to contain an arbitrary Java object as a value.<p> - * Note that <code>has</code> will be called by the runtime first before - * <code>set</code> is called to determine in which object the - * property is defined. - * Note that this method is not expected to traverse the prototype chain, - * which is different from the ECMA [[Put]] operation. - * @param name the name of the property - * @param start the object whose property is being set - * @param value value to set the property to - * @see org.mozilla.javascript.Scriptable#has(String, Scriptable) - * @see org.mozilla.javascript.Scriptable#get(String, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#putProperty(Scriptable, String, Object) - * @see org.mozilla.javascript.Context#toObject(Object, Scriptable) - */ - public void putConst(String name, Scriptable start, Object value); - - /** - * Reserves a definition spot for a const. This will set up a definition - * of the const property, but set its value to undefined. The semantics of - * the start parameter is the same as for putConst. - * @param name The name of the property. - * @param start The object whose property is being reserved. - */ - public void defineConst(String name, Scriptable start); - - /** - * Returns true if the named property is defined as a const on this object. - * @param name - * @return true if the named property is defined as a const, false - * otherwise. - */ - public boolean isConst(String name); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Context.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Context.java deleted file mode 100644 index 0833883..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Context.java +++ /dev/null @@ -1,2526 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Bob Jervis - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.CharArrayWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Hashtable; -import java.util.Locale; - -import org.mozilla.javascript.debug.DebuggableScript; -import org.mozilla.javascript.debug.Debugger; -import org.mozilla.javascript.xml.XMLLib; - -/** - * This class represents the runtime context of an executing script. - * - * Before executing a script, an instance of Context must be created - * and associated with the thread that will be executing the script. - * The Context will be used to store information about the executing - * of the script such as the call stack. Contexts are associated with - * the current thread using the {@link #call(ContextAction)} - * or {@link #enter()} methods.<p> - * - * Different forms of script execution are supported. Scripts may be - * evaluated from the source directly, or first compiled and then later - * executed. Interactive execution is also supported.<p> - * - * Some aspects of script execution, such as type conversions and - * object creation, may be accessed directly through methods of - * Context. - * - * @see Scriptable - * @author Norris Boyd - * @author Brendan Eich - */ - -public class Context -{ - /** - * Language versions. - * - * All integral values are reserved for future version numbers. - */ - - /** - * The unknown version. - */ - public static final int VERSION_UNKNOWN = -1; - - /** - * The default version. - */ - public static final int VERSION_DEFAULT = 0; - - /** - * JavaScript 1.0 - */ - public static final int VERSION_1_0 = 100; - - /** - * JavaScript 1.1 - */ - public static final int VERSION_1_1 = 110; - - /** - * JavaScript 1.2 - */ - public static final int VERSION_1_2 = 120; - - /** - * JavaScript 1.3 - */ - public static final int VERSION_1_3 = 130; - - /** - * JavaScript 1.4 - */ - public static final int VERSION_1_4 = 140; - - /** - * JavaScript 1.5 - */ - public static final int VERSION_1_5 = 150; - - /** - * JavaScript 1.6 - */ - public static final int VERSION_1_6 = 160; - - /** - * JavaScript 1.7 - */ - public static final int VERSION_1_7 = 170; - - /** - * Controls behaviour of <tt>Date.prototype.getYear()</tt>. - * If <tt>hasFeature(FEATURE_NON_ECMA_GET_YEAR)</tt> returns true, - * Date.prototype.getYear subtructs 1900 only if 1900 <= date < 2000. - * The default behavior of {@link #hasFeature(int)} is always to subtruct - * 1900 as rquired by ECMAScript B.2.4. - */ - public static final int FEATURE_NON_ECMA_GET_YEAR = 1; - - /** - * Control if member expression as function name extension is available. - * If <tt>hasFeature(FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)</tt> returns - * true, allow <tt>function memberExpression(args) { body }</tt> to be - * syntax sugar for <tt>memberExpression = function(args) { body }</tt>, - * when memberExpression is not a simple identifier. - * See ECMAScript-262, section 11.2 for definition of memberExpression. - * By default {@link #hasFeature(int)} returns false. - */ - public static final int FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME = 2; - - /** - * Control if reserved keywords are treated as identifiers. - * If <tt>hasFeature(RESERVED_KEYWORD_AS_IDENTIFIER)</tt> returns true, - * treat future reserved keyword (see Ecma-262, section 7.5.3) as ordinary - * identifiers but warn about this usage. - * - * By default {@link #hasFeature(int)} returns false. - */ - public static final int FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER = 3; - - /** - * Control if <tt>toString()</tt> should returns the same result - * as <tt>toSource()</tt> when applied to objects and arrays. - * If <tt>hasFeature(FEATURE_TO_STRING_AS_SOURCE)</tt> returns true, - * calling <tt>toString()</tt> on JS objects gives the same result as - * calling <tt>toSource()</tt>. That is it returns JS source with code - * to create an object with all enumeratable fields of the original object - * instead of printing <tt>[object <i>result of - * {@link Scriptable#getClassName()}</i>]</tt>. - * <p> - * By default {@link #hasFeature(int)} returns true only if - * the current JS version is set to {@link #VERSION_1_2}. - */ - public static final int FEATURE_TO_STRING_AS_SOURCE = 4; - - /** - * Control if properties <tt>__proto__</tt> and <tt>__parent__</tt> - * are treated specially. - * If <tt>hasFeature(FEATURE_PARENT_PROTO_PROPERTIES)</tt> returns true, - * treat <tt>__parent__</tt> and <tt>__proto__</tt> as special properties. - * <p> - * The properties allow to query and set scope and prototype chains for the - * objects. The special meaning of the properties is available - * only when they are used as the right hand side of the dot operator. - * For example, while <tt>x.__proto__ = y</tt> changes the prototype - * chain of the object <tt>x</tt> to point to <tt>y</tt>, - * <tt>x["__proto__"] = y</tt> simply assigns a new value to the property - * <tt>__proto__</tt> in <tt>x</tt> even when the feature is on. - * - * By default {@link #hasFeature(int)} returns true. - */ - public static final int FEATURE_PARENT_PROTO_PROPERTIES = 5; - - /** - * @deprecated In previous releases, this name was given to - * FEATURE_PARENT_PROTO_PROPERTIES. - */ - public static final int FEATURE_PARENT_PROTO_PROPRTIES = 5; - - /** - * Control if support for E4X(ECMAScript for XML) extension is available. - * If hasFeature(FEATURE_E4X) returns true, the XML syntax is available. - * <p> - * By default {@link #hasFeature(int)} returns true if - * the current JS version is set to {@link #VERSION_DEFAULT} - * or is at least {@link #VERSION_1_6}. - * @since 1.6 Release 1 - */ - public static final int FEATURE_E4X = 6; - - /** - * Control if dynamic scope should be used for name access. - * If hasFeature(FEATURE_DYNAMIC_SCOPE) returns true, then the name lookup - * during name resolution will use the top scope of the script or function - * which is at the top of JS execution stack instead of the top scope of the - * script or function from the current stack frame if the top scope of - * the top stack frame contains the top scope of the current stack frame - * on its prototype chain. - * <p> - * This is useful to define shared scope containing functions that can - * be called from scripts and functions using private scopes. - * <p> - * By default {@link #hasFeature(int)} returns false. - * @since 1.6 Release 1 - */ - public static final int FEATURE_DYNAMIC_SCOPE = 7; - - /** - * Control if strict variable mode is enabled. - * When the feature is on Rhino reports runtime errors if assignment - * to a global variable that does not exist is executed. When the feature - * is off such assignments creates new variable in the global scope as - * required by ECMA 262. - * <p> - * By default {@link #hasFeature(int)} returns false. - * @since 1.6 Release 1 - */ - public static final int FEATURE_STRICT_VARS = 8; - - /** - * Control if strict eval mode is enabled. - * When the feature is on Rhino reports runtime errors if non-string - * argument is passed to the eval function. When the feature is off - * eval simply return non-string argument as is without performing any - * evaluation as required by ECMA 262. - * <p> - * By default {@link #hasFeature(int)} returns false. - * @since 1.6 Release 1 - */ - public static final int FEATURE_STRICT_EVAL = 9; - - /** - * When the feature is on Rhino will add a "fileName" and "lineNumber" - * properties to Error objects automatically. When the feature is off, you - * have to explicitly pass them as the second and third argument to the - * Error constructor. Note that neither behaviour is fully ECMA 262 - * compliant (as 262 doesn't specify a three-arg constructor), but keeping - * the feature off results in Error objects that don't have - * additional non-ECMA properties when constructed using the ECMA-defined - * single-arg constructor and is thus desirable if a stricter ECMA - * compliance is desired, specifically adherence to the point 15.11.5. of - * the standard. - * <p> - * By default {@link #hasFeature(int)} returns false. - * @since 1.6 Release 6 - */ - public static final int FEATURE_LOCATION_INFORMATION_IN_ERROR = 10; - - /** - * Controls whether JS 1.5 'strict mode' is enabled. - * When the feature is on, Rhino reports more than a dozen different - * warnings. When the feature is off, these warnings are not generated. - * FEATURE_STRICT_MODE implies FEATURE_STRICT_VARS and FEATURE_STRICT_EVAL. - * <p> - * By default {@link #hasFeature(int)} returns false. - * @since 1.6 Release 6 - */ - public static final int FEATURE_STRICT_MODE = 11; - - /** - * Controls whether a warning should be treated as an error. - * @since 1.6 Release 6 - */ - public static final int FEATURE_WARNING_AS_ERROR = 12; - - /** - * Enables enhanced access to Java. - * Specifically, controls whether private and protected members can be - * accessed, and whether scripts can catch all Java exceptions. - * <p> - * Note that this feature should only be enabled for trusted scripts. - * <p> - * By default {@link #hasFeature(int)} returns false. - * @since 1.7 Release 1 - */ - public static final int FEATURE_ENHANCED_JAVA_ACCESS = 13; - - - public static final String languageVersionProperty = "language version"; - public static final String errorReporterProperty = "error reporter"; - - /** - * Convenient value to use as zero-length array of objects. - */ - public static final Object[] emptyArgs = ScriptRuntime.emptyArgs; - - /** - * Create a new Context. - * - * Note that the Context must be associated with a thread before - * it can be used to execute a script. - * @deprecated use {@link ContextFactory#enter()} or - * {@link ContextFactory#call(ContextAction)} instead. - */ - public Context() - { - this(ContextFactory.getGlobal()); - } - - Context(ContextFactory factory) - { - assert factory != null; - this.factory = factory; - setLanguageVersion(VERSION_DEFAULT); - optimizationLevel = codegenClass != null ? 0 : -1; - maximumInterpreterStackDepth = Integer.MAX_VALUE; - } - - /** - * Get the current Context. - * - * The current Context is per-thread; this method looks up - * the Context associated with the current thread. <p> - * - * @return the Context associated with the current thread, or - * null if no context is associated with the current - * thread. - * @see ContextFactory#enterContext() - * @see ContextFactory#call(ContextAction) - */ - public static Context getCurrentContext() - { - Object helper = VMBridge.instance.getThreadContextHelper(); - return VMBridge.instance.getContext(helper); - } - - /** - * Same as calling {@link ContextFactory#enterContext()} on the global - * ContextFactory instance. - * @deprecated use {@link ContextFactory#enter()} or - * {@link ContextFactory#call(ContextAction)} instead as this method relies - * on usage of a static singleton "global" ContextFactory. - * @return a Context associated with the current thread - * @see #getCurrentContext() - * @see #exit() - * @see #call(ContextAction) - */ - public static Context enter() - { - return enter(null); - } - - /** - * Get a Context associated with the current thread, using - * the given Context if need be. - * <p> - * The same as <code>enter()</code> except that <code>cx</code> - * is associated with the current thread and returned if - * the current thread has no associated context and <code>cx</code> - * is not associated with any other thread. - * @param cx a Context to associate with the thread if possible - * @return a Context associated with the current thread - * @deprecated use {@link ContextFactory#enterContext(Context)} instead as - * this method relies on usage of a static singleton "global" ContextFactory. - * @see ContextFactory#enterContext(Context) - * @see ContextFactory#call(ContextAction) - */ - public static Context enter(Context cx) - { - return enter(cx, ContextFactory.getGlobal()); - } - - static final Context enter(Context cx, ContextFactory factory) - { - Object helper = VMBridge.instance.getThreadContextHelper(); - Context old = VMBridge.instance.getContext(helper); - if (old != null) { - cx = old; - } else { - if (cx == null) { - cx = factory.makeContext(); - if (cx.enterCount != 0) { - throw new IllegalStateException("factory.makeContext() returned Context instance already associated with some thread"); - } - factory.onContextCreated(cx); - if (factory.isSealed() && !cx.isSealed()) { - cx.seal(null); - } - } else { - if (cx.enterCount != 0) { - throw new IllegalStateException("can not use Context instance already associated with some thread"); - } - } - VMBridge.instance.setContext(helper, cx); - } - ++cx.enterCount; - return cx; - } - - /** - * Exit a block of code requiring a Context. - * - * Calling <code>exit()</code> will remove the association between - * the current thread and a Context if the prior call to - * {@link ContextFactory#enterContext()} on this thread newly associated a - * Context with this thread. Once the current thread no longer has an - * associated Context, it cannot be used to execute JavaScript until it is - * again associated with a Context. - * @see ContextFactory#enterContext() - */ - public static void exit() - { - Object helper = VMBridge.instance.getThreadContextHelper(); - Context cx = VMBridge.instance.getContext(helper); - if (cx == null) { - throw new IllegalStateException( - "Calling Context.exit without previous Context.enter"); - } - if (cx.enterCount < 1) Kit.codeBug(); - if (--cx.enterCount == 0) { - VMBridge.instance.setContext(helper, null); - cx.factory.onContextReleased(cx); - } - } - - /** - * Call {@link ContextAction#run(Context cx)} - * using the Context instance associated with the current thread. - * If no Context is associated with the thread, then - * <tt>ContextFactory.getGlobal().makeContext()</tt> will be called to - * construct new Context instance. The instance will be temporary - * associated with the thread during call to - * {@link ContextAction#run(Context)}. - * @deprecated use {@link ContextFactory#call(ContextAction)} instead as - * this method relies on usage of a static singleton "global" - * ContextFactory. - * @return The result of {@link ContextAction#run(Context)}. - */ - public static Object call(ContextAction action) - { - return call(ContextFactory.getGlobal(), action); - } - - /** - * Call {@link - * Callable#call(Context cx, Scriptable scope, Scriptable thisObj, - * Object[] args)} - * using the Context instance associated with the current thread. - * If no Context is associated with the thread, then - * {@link ContextFactory#makeContext()} will be called to construct - * new Context instance. The instance will be temporary associated - * with the thread during call to {@link ContextAction#run(Context)}. - * <p> - * It is allowed but not advisable to use null for <tt>factory</tt> - * argument in which case the global static singleton ContextFactory - * instance will be used to create new context instances. - * @see ContextFactory#call(ContextAction) - */ - public static Object call(ContextFactory factory, final Callable callable, - final Scriptable scope, final Scriptable thisObj, - final Object[] args) - { - if(factory == null) { - factory = ContextFactory.getGlobal(); - } - return call(factory, new ContextAction() { - public Object run(Context cx) { - return callable.call(cx, scope, thisObj, args); - } - }); - } - - /** - * The method implements {@links ContextFactory#call(ContextAction)} logic. - */ - static Object call(ContextFactory factory, ContextAction action) { - Context cx = enter(null, factory); - try { - return action.run(cx); - } - finally { - exit(); - } - } - - /** - * @deprecated - * @see ContextFactory#addListener(ContextFactory.Listener) - * @see ContextFactory#getGlobal() - */ - public static void addContextListener(ContextListener listener) - { - // Special workaround for the debugger - String DBG = "org.mozilla.javascript.tools.debugger.Main"; - if (DBG.equals(listener.getClass().getName())) { - Class cl = listener.getClass(); - Class factoryClass = Kit.classOrNull( - "org.mozilla.javascript.ContextFactory"); - Class[] sig = { factoryClass }; - Object[] args = { ContextFactory.getGlobal() }; - try { - Method m = cl.getMethod("attachTo", sig); - m.invoke(listener, args); - } catch (Exception ex) { - RuntimeException rex = new RuntimeException(); - Kit.initCause(rex, ex); - throw rex; - } - return; - } - - ContextFactory.getGlobal().addListener(listener); - } - - /** - * @deprecated - * @see ContextFactory#removeListener(ContextFactory.Listener) - * @see ContextFactory#getGlobal() - */ - public static void removeContextListener(ContextListener listener) - { - ContextFactory.getGlobal().addListener(listener); - } - - /** - * Return {@link ContextFactory} instance used to create this Context. - */ - public final ContextFactory getFactory() - { - return factory; - } - - /** - * Checks if this is a sealed Context. A sealed Context instance does not - * allow to modify any of its properties and will throw an exception - * on any such attempt. - * @see #seal(Object sealKey) - */ - public final boolean isSealed() - { - return sealed; - } - - /** - * Seal this Context object so any attempt to modify any of its properties - * including calling {@link #enter()} and {@link #exit()} methods will - * throw an exception. - * <p> - * If <tt>sealKey</tt> is not null, calling - * {@link #unseal(Object sealKey)} with the same key unseals - * the object. If <tt>sealKey</tt> is null, unsealing is no longer possible. - * - * @see #isSealed() - * @see #unseal(Object) - */ - public final void seal(Object sealKey) - { - if (sealed) onSealedMutation(); - sealed = true; - this.sealKey = sealKey; - } - - /** - * Unseal previously sealed Context object. - * The <tt>sealKey</tt> argument should not be null and should match - * <tt>sealKey</tt> suplied with the last call to - * {@link #seal(Object)} or an exception will be thrown. - * - * @see #isSealed() - * @see #seal(Object sealKey) - */ - public final void unseal(Object sealKey) - { - if (sealKey == null) throw new IllegalArgumentException(); - if (this.sealKey != sealKey) throw new IllegalArgumentException(); - if (!sealed) throw new IllegalStateException(); - sealed = false; - this.sealKey = null; - } - - static void onSealedMutation() - { - throw new IllegalStateException(); - } - - /** - * Get the current language version. - * <p> - * The language version number affects JavaScript semantics as detailed - * in the overview documentation. - * - * @return an integer that is one of VERSION_1_0, VERSION_1_1, etc. - */ - public final int getLanguageVersion() - { - return version; - } - - /** - * Set the language version. - * - * <p> - * Setting the language version will affect functions and scripts compiled - * subsequently. See the overview documentation for version-specific - * behavior. - * - * @param version the version as specified by VERSION_1_0, VERSION_1_1, etc. - */ - public void setLanguageVersion(int version) - { - if (sealed) onSealedMutation(); - checkLanguageVersion(version); - Object listeners = propertyListeners; - if (listeners != null && version != this.version) { - firePropertyChangeImpl(listeners, languageVersionProperty, - new Integer(this.version), - new Integer(version)); - } - this.version = version; - } - - public static boolean isValidLanguageVersion(int version) - { - switch (version) { - case VERSION_DEFAULT: - case VERSION_1_0: - case VERSION_1_1: - case VERSION_1_2: - case VERSION_1_3: - case VERSION_1_4: - case VERSION_1_5: - case VERSION_1_6: - case VERSION_1_7: - return true; - } - return false; - } - - public static void checkLanguageVersion(int version) - { - if (isValidLanguageVersion(version)) { - return; - } - throw new IllegalArgumentException("Bad language version: "+version); - } - - /** - * Get the implementation version. - * - * <p> - * The implementation version is of the form - * <pre> - * "<i>name langVer</i> <code>release</code> <i>relNum date</i>" - * </pre> - * where <i>name</i> is the name of the product, <i>langVer</i> is - * the language version, <i>relNum</i> is the release number, and - * <i>date</i> is the release date for that specific - * release in the form "yyyy mm dd". - * - * @return a string that encodes the product, language version, release - * number, and date. - */ - public final String getImplementationVersion() - { - // XXX Probably it would be better to embed this directly into source - // with special build preprocessing but that would require some ant - // tweaking and then replacing token in resource files was simpler - if (implementationVersion == null) { - implementationVersion - = ScriptRuntime.getMessage0("implementation.version"); - } - return implementationVersion; - } - - /** - * Get the current error reporter. - * - * @see org.mozilla.javascript.ErrorReporter - */ - public final ErrorReporter getErrorReporter() - { - if (errorReporter == null) { - return DefaultErrorReporter.instance; - } - return errorReporter; - } - - /** - * Change the current error reporter. - * - * @return the previous error reporter - * @see org.mozilla.javascript.ErrorReporter - */ - public final ErrorReporter setErrorReporter(ErrorReporter reporter) - { - if (sealed) onSealedMutation(); - if (reporter == null) throw new IllegalArgumentException(); - ErrorReporter old = getErrorReporter(); - if (reporter == old) { - return old; - } - Object listeners = propertyListeners; - if (listeners != null) { - firePropertyChangeImpl(listeners, errorReporterProperty, - old, reporter); - } - this.errorReporter = reporter; - return old; - } - - /** - * Get the current locale. Returns the default locale if none has - * been set. - * - * @see java.util.Locale - */ - - public final Locale getLocale() - { - if (locale == null) - locale = Locale.getDefault(); - return locale; - } - - /** - * Set the current locale. - * - * @see java.util.Locale - */ - public final Locale setLocale(Locale loc) - { - if (sealed) onSealedMutation(); - Locale result = locale; - locale = loc; - return result; - } - - /** - * Register an object to receive notifications when a bound property - * has changed - * @see java.beans.PropertyChangeEvent - * @see #removePropertyChangeListener(java.beans.PropertyChangeListener) - * @param l the listener - */ - public final void addPropertyChangeListener(PropertyChangeListener l) - { - if (sealed) onSealedMutation(); - propertyListeners = Kit.addListener(propertyListeners, l); - } - - /** - * Remove an object from the list of objects registered to receive - * notification of changes to a bounded property - * @see java.beans.PropertyChangeEvent - * @see #addPropertyChangeListener(java.beans.PropertyChangeListener) - * @param l the listener - */ - public final void removePropertyChangeListener(PropertyChangeListener l) - { - if (sealed) onSealedMutation(); - propertyListeners = Kit.removeListener(propertyListeners, l); - } - - /** - * Notify any registered listeners that a bounded property has changed - * @see #addPropertyChangeListener(java.beans.PropertyChangeListener) - * @see #removePropertyChangeListener(java.beans.PropertyChangeListener) - * @see java.beans.PropertyChangeListener - * @see java.beans.PropertyChangeEvent - * @param property the bound property - * @param oldValue the old value - * @param newValue the new value - */ - final void firePropertyChange(String property, Object oldValue, - Object newValue) - { - Object listeners = propertyListeners; - if (listeners != null) { - firePropertyChangeImpl(listeners, property, oldValue, newValue); - } - } - - private void firePropertyChangeImpl(Object listeners, String property, - Object oldValue, Object newValue) - { - for (int i = 0; ; ++i) { - Object l = Kit.getListener(listeners, i); - if (l == null) - break; - if (l instanceof PropertyChangeListener) { - PropertyChangeListener pcl = (PropertyChangeListener)l; - pcl.propertyChange(new PropertyChangeEvent( - this, property, oldValue, newValue)); - } - } - } - - /** - * Report a warning using the error reporter for the current thread. - * - * @param message the warning message to report - * @param sourceName a string describing the source, such as a filename - * @param lineno the starting line number - * @param lineSource the text of the line (may be null) - * @param lineOffset the offset into lineSource where problem was detected - * @see org.mozilla.javascript.ErrorReporter - */ - public static void reportWarning(String message, String sourceName, - int lineno, String lineSource, - int lineOffset) - { - Context cx = Context.getContext(); - if (cx.hasFeature(FEATURE_WARNING_AS_ERROR)) - reportError(message, sourceName, lineno, lineSource, lineOffset); - else - cx.getErrorReporter().warning(message, sourceName, lineno, - lineSource, lineOffset); - } - - /** - * Report a warning using the error reporter for the current thread. - * - * @param message the warning message to report - * @see org.mozilla.javascript.ErrorReporter - */ - public static void reportWarning(String message) - { - int[] linep = { 0 }; - String filename = getSourcePositionFromStack(linep); - Context.reportWarning(message, filename, linep[0], null, 0); - } - - public static void reportWarning(String message, Throwable t) - { - int[] linep = { 0 }; - String filename = getSourcePositionFromStack(linep); - Writer sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - pw.println(message); - t.printStackTrace(pw); - pw.flush(); - Context.reportWarning(sw.toString(), filename, linep[0], null, 0); - } - - /** - * Report an error using the error reporter for the current thread. - * - * @param message the error message to report - * @param sourceName a string describing the source, such as a filename - * @param lineno the starting line number - * @param lineSource the text of the line (may be null) - * @param lineOffset the offset into lineSource where problem was detected - * @see org.mozilla.javascript.ErrorReporter - */ - public static void reportError(String message, String sourceName, - int lineno, String lineSource, - int lineOffset) - { - Context cx = getCurrentContext(); - if (cx != null) { - cx.getErrorReporter().error(message, sourceName, lineno, - lineSource, lineOffset); - } else { - throw new EvaluatorException(message, sourceName, lineno, - lineSource, lineOffset); - } - } - - /** - * Report an error using the error reporter for the current thread. - * - * @param message the error message to report - * @see org.mozilla.javascript.ErrorReporter - */ - public static void reportError(String message) - { - int[] linep = { 0 }; - String filename = getSourcePositionFromStack(linep); - Context.reportError(message, filename, linep[0], null, 0); - } - - /** - * Report a runtime error using the error reporter for the current thread. - * - * @param message the error message to report - * @param sourceName a string describing the source, such as a filename - * @param lineno the starting line number - * @param lineSource the text of the line (may be null) - * @param lineOffset the offset into lineSource where problem was detected - * @return a runtime exception that will be thrown to terminate the - * execution of the script - * @see org.mozilla.javascript.ErrorReporter - */ - public static EvaluatorException reportRuntimeError(String message, - String sourceName, - int lineno, - String lineSource, - int lineOffset) - { - Context cx = getCurrentContext(); - if (cx != null) { - return cx.getErrorReporter(). - runtimeError(message, sourceName, lineno, - lineSource, lineOffset); - } else { - throw new EvaluatorException(message, sourceName, lineno, - lineSource, lineOffset); - } - } - - static EvaluatorException reportRuntimeError0(String messageId) - { - String msg = ScriptRuntime.getMessage0(messageId); - return reportRuntimeError(msg); - } - - static EvaluatorException reportRuntimeError1(String messageId, - Object arg1) - { - String msg = ScriptRuntime.getMessage1(messageId, arg1); - return reportRuntimeError(msg); - } - - static EvaluatorException reportRuntimeError2(String messageId, - Object arg1, Object arg2) - { - String msg = ScriptRuntime.getMessage2(messageId, arg1, arg2); - return reportRuntimeError(msg); - } - - static EvaluatorException reportRuntimeError3(String messageId, - Object arg1, Object arg2, - Object arg3) - { - String msg = ScriptRuntime.getMessage3(messageId, arg1, arg2, arg3); - return reportRuntimeError(msg); - } - - static EvaluatorException reportRuntimeError4(String messageId, - Object arg1, Object arg2, - Object arg3, Object arg4) - { - String msg - = ScriptRuntime.getMessage4(messageId, arg1, arg2, arg3, arg4); - return reportRuntimeError(msg); - } - - /** - * Report a runtime error using the error reporter for the current thread. - * - * @param message the error message to report - * @see org.mozilla.javascript.ErrorReporter - */ - public static EvaluatorException reportRuntimeError(String message) - { - int[] linep = { 0 }; - String filename = getSourcePositionFromStack(linep); - return Context.reportRuntimeError(message, filename, linep[0], null, 0); - } - - /** - * Initialize the standard objects. - * - * Creates instances of the standard objects and their constructors - * (Object, String, Number, Date, etc.), setting up 'scope' to act - * as a global object as in ECMA 15.1.<p> - * - * This method must be called to initialize a scope before scripts - * can be evaluated in that scope.<p> - * - * This method does not affect the Context it is called upon. - * - * @return the initialized scope - */ - public final ScriptableObject initStandardObjects() - { - return initStandardObjects(null, false); - } - - /** - * Initialize the standard objects. - * - * Creates instances of the standard objects and their constructors - * (Object, String, Number, Date, etc.), setting up 'scope' to act - * as a global object as in ECMA 15.1.<p> - * - * This method must be called to initialize a scope before scripts - * can be evaluated in that scope.<p> - * - * This method does not affect the Context it is called upon. - * - * @param scope the scope to initialize, or null, in which case a new - * object will be created to serve as the scope - * @return the initialized scope. The method returns the value of the scope - * argument if it is not null or newly allocated scope object which - * is an instance {@link ScriptableObject}. - */ - public final Scriptable initStandardObjects(ScriptableObject scope) - { - return initStandardObjects(scope, false); - } - - /** - * Initialize the standard objects. - * - * Creates instances of the standard objects and their constructors - * (Object, String, Number, Date, etc.), setting up 'scope' to act - * as a global object as in ECMA 15.1.<p> - * - * This method must be called to initialize a scope before scripts - * can be evaluated in that scope.<p> - * - * This method does not affect the Context it is called upon.<p> - * - * This form of the method also allows for creating "sealed" standard - * objects. An object that is sealed cannot have properties added, changed, - * or removed. This is useful to create a "superglobal" that can be shared - * among several top-level objects. Note that sealing is not allowed in - * the current ECMA/ISO language specification, but is likely for - * the next version. - * - * @param scope the scope to initialize, or null, in which case a new - * object will be created to serve as the scope - * @param sealed whether or not to create sealed standard objects that - * cannot be modified. - * @return the initialized scope. The method returns the value of the scope - * argument if it is not null or newly allocated scope object. - * @since 1.4R3 - */ - public ScriptableObject initStandardObjects(ScriptableObject scope, - boolean sealed) - { - return ScriptRuntime.initStandardObjects(this, scope, sealed); - } - - /** - * Get the singleton object that represents the JavaScript Undefined value. - */ - public static Object getUndefinedValue() - { - return Undefined.instance; - } - - /** - * Evaluate a JavaScript source string. - * - * The provided source name and line number are used for error messages - * and for producing debug information. - * - * @param scope the scope to execute in - * @param source the JavaScript source - * @param sourceName a string describing the source, such as a filename - * @param lineno the starting line number - * @param securityDomain an arbitrary object that specifies security - * information about the origin or owner of the script. For - * implementations that don't care about security, this value - * may be null. - * @return the result of evaluating the string - * @see org.mozilla.javascript.SecurityController - */ - public final Object evaluateString(Scriptable scope, String source, - String sourceName, int lineno, - Object securityDomain) - { - Script script = compileString(source, sourceName, lineno, - securityDomain); - if (script != null) { - return script.exec(this, scope); - } else { - return null; - } - } - - /** - * Evaluate a reader as JavaScript source. - * - * All characters of the reader are consumed. - * - * @param scope the scope to execute in - * @param in the Reader to get JavaScript source from - * @param sourceName a string describing the source, such as a filename - * @param lineno the starting line number - * @param securityDomain an arbitrary object that specifies security - * information about the origin or owner of the script. For - * implementations that don't care about security, this value - * may be null. - * @return the result of evaluating the source - * - * @exception IOException if an IOException was generated by the Reader - */ - public final Object evaluateReader(Scriptable scope, Reader in, - String sourceName, int lineno, - Object securityDomain) - throws IOException - { - Script script = compileReader(scope, in, sourceName, lineno, - securityDomain); - if (script != null) { - return script.exec(this, scope); - } else { - return null; - } - } - - /** - * Check whether a string is ready to be compiled. - * <p> - * stringIsCompilableUnit is intended to support interactive compilation of - * javascript. If compiling the string would result in an error - * that might be fixed by appending more source, this method - * returns false. In every other case, it returns true. - * <p> - * Interactive shells may accumulate source lines, using this - * method after each new line is appended to check whether the - * statement being entered is complete. - * - * @param source the source buffer to check - * @return whether the source is ready for compilation - * @since 1.4 Release 2 - */ - public final boolean stringIsCompilableUnit(String source) - { - boolean errorseen = false; - CompilerEnvirons compilerEnv = new CompilerEnvirons(); - compilerEnv.initFromContext(this); - // no source name or source text manager, because we're just - // going to throw away the result. - compilerEnv.setGeneratingSource(false); - /*APPJET*/ - Parser p = InformativeParser.makeParser(compilerEnv, - DefaultErrorReporter.instance); - try { - p.parse(source, null, 1); - } catch (EvaluatorException ee) { - errorseen = true; - } - // Return false only if an error occurred as a result of reading past - // the end of the file, i.e. if the source could be fixed by - // appending more source. - if (errorseen && p.eof()) - return false; - else - return true; - } - - /** - * @deprecated - * @see #compileReader(Reader in, String sourceName, int lineno, - * Object securityDomain) - */ - public final Script compileReader(Scriptable scope, Reader in, - String sourceName, int lineno, - Object securityDomain) - throws IOException - { - return compileReader(in, sourceName, lineno, securityDomain); - } - - /** - * Compiles the source in the given reader. - * <p> - * Returns a script that may later be executed. - * Will consume all the source in the reader. - * - * @param in the input reader - * @param sourceName a string describing the source, such as a filename - * @param lineno the starting line number for reporting errors - * @param securityDomain an arbitrary object that specifies security - * information about the origin or owner of the script. For - * implementations that don't care about security, this value - * may be null. - * @return a script that may later be executed - * @exception IOException if an IOException was generated by the Reader - * @see org.mozilla.javascript.Script - */ - public final Script compileReader(Reader in, String sourceName, - int lineno, Object securityDomain) - throws IOException - { - if (lineno < 0) { - // For compatibility IllegalArgumentException can not be thrown here - lineno = 0; - } - return (Script) compileImpl(null, in, null, sourceName, lineno, - securityDomain, false, null, null); - } - - /** - * Compiles the source in the given string. - * <p> - * Returns a script that may later be executed. - * - * @param source the source string - * @param sourceName a string describing the source, such as a filename - * @param lineno the starting line number for reporting errors - * @param securityDomain an arbitrary object that specifies security - * information about the origin or owner of the script. For - * implementations that don't care about security, this value - * may be null. - * @return a script that may later be executed - * @see org.mozilla.javascript.Script - */ - public final Script compileString(String source, - String sourceName, int lineno, - Object securityDomain) - { - if (lineno < 0) { - // For compatibility IllegalArgumentException can not be thrown here - lineno = 0; - } - return compileString(source, null, null, sourceName, lineno, - securityDomain); - } - - final Script compileString(String source, - Evaluator compiler, - ErrorReporter compilationErrorReporter, - String sourceName, int lineno, - Object securityDomain) - { - try { - return (Script) compileImpl(null, null, source, sourceName, lineno, - securityDomain, false, - compiler, compilationErrorReporter); - } catch (IOException ex) { - // Should not happen when dealing with source as string - throw new RuntimeException(); - } - } - - /** - * Compile a JavaScript function. - * <p> - * The function source must be a function definition as defined by - * ECMA (e.g., "function f(a) { return a; }"). - * - * @param scope the scope to compile relative to - * @param source the function definition source - * @param sourceName a string describing the source, such as a filename - * @param lineno the starting line number - * @param securityDomain an arbitrary object that specifies security - * information about the origin or owner of the script. For - * implementations that don't care about security, this value - * may be null. - * @return a Function that may later be called - * @see org.mozilla.javascript.Function - */ - public final Function compileFunction(Scriptable scope, String source, - String sourceName, int lineno, - Object securityDomain) - { - return compileFunction(scope, source, null, null, sourceName, lineno, - securityDomain); - } - - final Function compileFunction(Scriptable scope, String source, - Evaluator compiler, - ErrorReporter compilationErrorReporter, - String sourceName, int lineno, - Object securityDomain) - { - try { - return (Function) compileImpl(scope, null, source, sourceName, - lineno, securityDomain, true, - compiler, compilationErrorReporter); - } - catch (IOException ioe) { - // Should never happen because we just made the reader - // from a String - throw new RuntimeException(); - } - } - - /** - * Decompile the script. - * <p> - * The canonical source of the script is returned. - * - * @param script the script to decompile - * @param indent the number of spaces to indent the result - * @return a string representing the script source - */ - public final String decompileScript(Script script, int indent) - { - NativeFunction scriptImpl = (NativeFunction) script; - return scriptImpl.decompile(indent, 0); - } - - /** - * Decompile a JavaScript Function. - * <p> - * Decompiles a previously compiled JavaScript function object to - * canonical source. - * <p> - * Returns function body of '[native code]' if no decompilation - * information is available. - * - * @param fun the JavaScript function to decompile - * @param indent the number of spaces to indent the result - * @return a string representing the function source - */ - public final String decompileFunction(Function fun, int indent) - { - if (fun instanceof BaseFunction) - return ((BaseFunction)fun).decompile(indent, 0); - else - return "function " + fun.getClassName() + - "() {\n\t[native code]\n}\n"; - } - - /** - * Decompile the body of a JavaScript Function. - * <p> - * Decompiles the body a previously compiled JavaScript Function - * object to canonical source, omitting the function header and - * trailing brace. - * - * Returns '[native code]' if no decompilation information is available. - * - * @param fun the JavaScript function to decompile - * @param indent the number of spaces to indent the result - * @return a string representing the function body source. - */ - public final String decompileFunctionBody(Function fun, int indent) - { - if (fun instanceof BaseFunction) { - BaseFunction bf = (BaseFunction)fun; - return bf.decompile(indent, Decompiler.ONLY_BODY_FLAG); - } - // ALERT: not sure what the right response here is. - return "[native code]\n"; - } - - /** - * Create a new JavaScript object. - * - * Equivalent to evaluating "new Object()". - * @param scope the scope to search for the constructor and to evaluate - * against - * @return the new object - */ - public final Scriptable newObject(Scriptable scope) - { - return newObject(scope, "Object", ScriptRuntime.emptyArgs); - } - - /** - * Create a new JavaScript object by executing the named constructor. - * - * The call <code>newObject(scope, "Foo")</code> is equivalent to - * evaluating "new Foo()". - * - * @param scope the scope to search for the constructor and to evaluate against - * @param constructorName the name of the constructor to call - * @return the new object - */ - public final Scriptable newObject(Scriptable scope, String constructorName) - { - return newObject(scope, constructorName, ScriptRuntime.emptyArgs); - } - - /** - * Creates a new JavaScript object by executing the named constructor. - * - * Searches <code>scope</code> for the named constructor, calls it with - * the given arguments, and returns the result.<p> - * - * The code - * <pre> - * Object[] args = { "a", "b" }; - * newObject(scope, "Foo", args)</pre> - * is equivalent to evaluating "new Foo('a', 'b')", assuming that the Foo - * constructor has been defined in <code>scope</code>. - * - * @param scope The scope to search for the constructor and to evaluate - * against - * @param constructorName the name of the constructor to call - * @param args the array of arguments for the constructor - * @return the new object - */ - public final Scriptable newObject(Scriptable scope, String constructorName, - Object[] args) - { - scope = ScriptableObject.getTopLevelScope(scope); - Function ctor = ScriptRuntime.getExistingCtor(this, scope, - constructorName); - if (args == null) { args = ScriptRuntime.emptyArgs; } - return ctor.construct(this, scope, args); - } - - /** - * Create an array with a specified initial length. - * <p> - * @param scope the scope to create the object in - * @param length the initial length (JavaScript arrays may have - * additional properties added dynamically). - * @return the new array object - */ - public final Scriptable newArray(Scriptable scope, int length) - { - NativeArray result = new NativeArray(length); - ScriptRuntime.setObjectProtoAndParent(result, scope); - return result; - } - - /** - * Create an array with a set of initial elements. - * - * @param scope the scope to create the object in. - * @param elements the initial elements. Each object in this array - * must be an acceptable JavaScript type and type - * of array should be exactly Object[], not - * SomeObjectSubclass[]. - * @return the new array object. - */ - public final Scriptable newArray(Scriptable scope, Object[] elements) - { - if (elements.getClass().getComponentType() != ScriptRuntime.ObjectClass) - throw new IllegalArgumentException(); - NativeArray result = new NativeArray(elements); - ScriptRuntime.setObjectProtoAndParent(result, scope); - return result; - } - - /** - * Get the elements of a JavaScript array. - * <p> - * If the object defines a length property convertible to double number, - * then the number is converted Uint32 value as defined in Ecma 9.6 - * and Java array of that size is allocated. - * The array is initialized with the values obtained by - * calling get() on object for each value of i in [0,length-1]. If - * there is not a defined value for a property the Undefined value - * is used to initialize the corresponding element in the array. The - * Java array is then returned. - * If the object doesn't define a length property or it is not a number, - * empty array is returned. - * @param object the JavaScript array or array-like object - * @return a Java array of objects - * @since 1.4 release 2 - */ - public final Object[] getElements(Scriptable object) - { - return ScriptRuntime.getArrayElements(object); - } - - /** - * Convert the value to a JavaScript boolean value. - * <p> - * See ECMA 9.2. - * - * @param value a JavaScript value - * @return the corresponding boolean value converted using - * the ECMA rules - */ - public static boolean toBoolean(Object value) - { - return ScriptRuntime.toBoolean(value); - } - - /** - * Convert the value to a JavaScript Number value. - * <p> - * Returns a Java double for the JavaScript Number. - * <p> - * See ECMA 9.3. - * - * @param value a JavaScript value - * @return the corresponding double value converted using - * the ECMA rules - */ - public static double toNumber(Object value) - { - return ScriptRuntime.toNumber(value); - } - - /** - * Convert the value to a JavaScript String value. - * <p> - * See ECMA 9.8. - * <p> - * @param value a JavaScript value - * @return the corresponding String value converted using - * the ECMA rules - */ - public static String toString(Object value) - { - return ScriptRuntime.toString(value); - } - - /** - * Convert the value to an JavaScript object value. - * <p> - * Note that a scope must be provided to look up the constructors - * for Number, Boolean, and String. - * <p> - * See ECMA 9.9. - * <p> - * Additionally, arbitrary Java objects and classes will be - * wrapped in a Scriptable object with its Java fields and methods - * reflected as JavaScript properties of the object. - * - * @param value any Java object - * @param scope global scope containing constructors for Number, - * Boolean, and String - * @return new JavaScript object - */ - public static Scriptable toObject(Object value, Scriptable scope) - { - return ScriptRuntime.toObject(scope, value); - } - - /** - * @deprecated - * @see #toObject(Object, Scriptable) - */ - public static Scriptable toObject(Object value, Scriptable scope, - Class staticType) - { - return ScriptRuntime.toObject(scope, value); - } - - /** - * Convenient method to convert java value to its closest representation - * in JavaScript. - * <p> - * If value is an instance of String, Number, Boolean, Function or - * Scriptable, it is returned as it and will be treated as the corresponding - * JavaScript type of string, number, boolean, function and object. - * <p> - * Note that for Number instances during any arithmetic operation in - * JavaScript the engine will always use the result of - * <tt>Number.doubleValue()</tt> resulting in a precision loss if - * the number can not fit into double. - * <p> - * If value is an instance of Character, it will be converted to string of - * length 1 and its JavaScript type will be string. - * <p> - * The rest of values will be wrapped as LiveConnect objects - * by calling {@link WrapFactory#wrap(Context cx, Scriptable scope, - * Object obj, Class staticType)} as in: - * <pre> - * Context cx = Context.getCurrentContext(); - * return cx.getWrapFactory().wrap(cx, scope, value, null); - * </pre> - * - * @param value any Java object - * @param scope top scope object - * @return value suitable to pass to any API that takes JavaScript values. - */ - public static Object javaToJS(Object value, Scriptable scope) - { - if (value instanceof String || value instanceof Number - || value instanceof Boolean || value instanceof Scriptable) - { - return value; - } else if (value instanceof Character) { - return String.valueOf(((Character)value).charValue()); - } else { - Context cx = Context.getContext(); - return cx.getWrapFactory().wrap(cx, scope, value, null); - } - } - - /** - * Convert a JavaScript value into the desired type. - * Uses the semantics defined with LiveConnect3 and throws an - * Illegal argument exception if the conversion cannot be performed. - * @param value the JavaScript value to convert - * @param desiredType the Java type to convert to. Primitive Java - * types are represented using the TYPE fields in the corresponding - * wrapper class in java.lang. - * @return the converted value - * @throws EvaluatorException if the conversion cannot be performed - */ - public static Object jsToJava(Object value, Class desiredType) - throws EvaluatorException - { - return NativeJavaObject.coerceTypeImpl(desiredType, value); - } - - /** - * @deprecated - * @see #jsToJava(Object, Class) - * @throws IllegalArgumentException if the conversion cannot be performed. - * Note that {@link #jsToJava(Object, Class)} throws - * {@link EvaluatorException} instead. - */ - public static Object toType(Object value, Class desiredType) - throws IllegalArgumentException - { - try { - return jsToJava(value, desiredType); - } catch (EvaluatorException ex) { - IllegalArgumentException - ex2 = new IllegalArgumentException(ex.getMessage()); - Kit.initCause(ex2, ex); - throw ex2; - } - } - - /** - * Rethrow the exception wrapping it as the script runtime exception. - * Unless the exception is instance of {@link EcmaError} or - * {@link EvaluatorException} it will be wrapped as - * {@link WrappedException}, a subclass of {@link EvaluatorException}. - * The resulting exception object always contains - * source name and line number of script that triggered exception. - * <p> - * This method always throws an exception, its return value is provided - * only for convenience to allow a usage like: - * <pre> - * throw Context.throwAsScriptRuntimeEx(ex); - * </pre> - * to indicate that code after the method is unreachable. - * @throws EvaluatorException - * @throws EcmaError - */ - public static RuntimeException throwAsScriptRuntimeEx(Throwable e) - { - while ((e instanceof InvocationTargetException)) { - e = ((InvocationTargetException) e).getTargetException(); - } - // special handling of Error so scripts would not catch them - if (e instanceof Error) { - Context cx = getContext(); - if (cx == null || - !cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS)) - { - throw (Error)e; - } - } - if (e instanceof RhinoException) { - throw (RhinoException)e; - } - throw new WrappedException(e); - } - - /** - * Tell whether debug information is being generated. - * @since 1.3 - */ - public final boolean isGeneratingDebug() - { - return generatingDebug; - } - - /** - * Specify whether or not debug information should be generated. - * <p> - * Setting the generation of debug information on will set the - * optimization level to zero. - * @since 1.3 - */ - public final void setGeneratingDebug(boolean generatingDebug) - { - if (sealed) onSealedMutation(); - generatingDebugChanged = true; - if (generatingDebug && getOptimizationLevel() > 0) - setOptimizationLevel(0); - this.generatingDebug = generatingDebug; - } - - /** - * Tell whether source information is being generated. - * @since 1.3 - */ - public final boolean isGeneratingSource() - { - return generatingSource; - } - - /** - * Specify whether or not source information should be generated. - * <p> - * Without source information, evaluating the "toString" method - * on JavaScript functions produces only "[native code]" for - * the body of the function. - * Note that code generated without source is not fully ECMA - * conformant. - * @since 1.3 - */ - public final void setGeneratingSource(boolean generatingSource) - { - if (sealed) onSealedMutation(); - this.generatingSource = generatingSource; - } - - /** - * Get the current optimization level. - * <p> - * The optimization level is expressed as an integer between -1 and - * 9. - * @since 1.3 - * - */ - public final int getOptimizationLevel() - { - return optimizationLevel; - } - - /** - * Set the current optimization level. - * <p> - * The optimization level is expected to be an integer between -1 and - * 9. Any negative values will be interpreted as -1, and any values - * greater than 9 will be interpreted as 9. - * An optimization level of -1 indicates that interpretive mode will - * always be used. Levels 0 through 9 indicate that class files may - * be generated. Higher optimization levels trade off compile time - * performance for runtime performance. - * The optimizer level can't be set greater than -1 if the optimizer - * package doesn't exist at run time. - * @param optimizationLevel an integer indicating the level of - * optimization to perform - * @since 1.3 - * - */ - public final void setOptimizationLevel(int optimizationLevel) - { - if (sealed) onSealedMutation(); - if (optimizationLevel == -2) { - // To be compatible with Cocoon fork - optimizationLevel = -1; - } - checkOptimizationLevel(optimizationLevel); - if (codegenClass == null) - optimizationLevel = -1; - this.optimizationLevel = optimizationLevel; - } - - public static boolean isValidOptimizationLevel(int optimizationLevel) - { - return -1 <= optimizationLevel && optimizationLevel <= 9; - } - - public static void checkOptimizationLevel(int optimizationLevel) - { - if (isValidOptimizationLevel(optimizationLevel)) { - return; - } - throw new IllegalArgumentException( - "Optimization level outside [-1..9]: "+optimizationLevel); - } - - /** - * Returns the maximum stack depth (in terms of number of call frames) - * allowed in a single invocation of interpreter. If the set depth would be - * exceeded, the interpreter will throw an EvaluatorException in the script. - * Defaults to Integer.MAX_VALUE. The setting only has effect for - * interpreted functions (those compiled with optimization level set to -1). - * As the interpreter doesn't use the Java stack but rather manages its own - * stack in the heap memory, a runaway recursion in interpreted code would - * eventually consume all available memory and cause OutOfMemoryError - * instead of a StackOverflowError limited to only a single thread. This - * setting helps prevent such situations. - * - * @return The current maximum interpreter stack depth. - */ - public final int getMaximumInterpreterStackDepth() - { - return maximumInterpreterStackDepth; - } - - /** - * Sets the maximum stack depth (in terms of number of call frames) - * allowed in a single invocation of interpreter. If the set depth would be - * exceeded, the interpreter will throw an EvaluatorException in the script. - * Defaults to Integer.MAX_VALUE. The setting only has effect for - * interpreted functions (those compiled with optimization level set to -1). - * As the interpreter doesn't use the Java stack but rather manages its own - * stack in the heap memory, a runaway recursion in interpreted code would - * eventually consume all available memory and cause OutOfMemoryError - * instead of a StackOverflowError limited to only a single thread. This - * setting helps prevent such situations. - * - * @param max the new maximum interpreter stack depth - * @throws IllegalStateException if this context's optimization level is not - * -1 - * @throws IllegalArgumentException if the new depth is not at least 1 - */ - public final void setMaximumInterpreterStackDepth(int max) - { - if(sealed) onSealedMutation(); - if(optimizationLevel != -1) { - throw new IllegalStateException("Cannot set maximumInterpreterStackDepth when optimizationLevel != -1"); - } - if(max < 1) { - throw new IllegalArgumentException("Cannot set maximumInterpreterStackDepth to less than 1"); - } - maximumInterpreterStackDepth = max; - } - - /** - * Set the security controller for this context. - * <p> SecurityController may only be set if it is currently null - * and {@link SecurityController#hasGlobal()} is <tt>false</tt>. - * Otherwise a SecurityException is thrown. - * @param controller a SecurityController object - * @throws SecurityException if there is already a SecurityController - * object for this Context or globally installed. - * @see SecurityController#initGlobal(SecurityController controller) - * @see SecurityController#hasGlobal() - */ - public final void setSecurityController(SecurityController controller) - { - if (sealed) onSealedMutation(); - if (controller == null) throw new IllegalArgumentException(); - if (securityController != null) { - throw new SecurityException("Can not overwrite existing SecurityController object"); - } - if (SecurityController.hasGlobal()) { - throw new SecurityException("Can not overwrite existing global SecurityController object"); - } - securityController = controller; - } - - /** - * Set the LiveConnect access filter for this context. - * <p> {@link ClassShutter} may only be set if it is currently null. - * Otherwise a SecurityException is thrown. - * @param shutter a ClassShutter object - * @throws SecurityException if there is already a ClassShutter - * object for this Context - */ - public final void setClassShutter(ClassShutter shutter) - { - if (sealed) onSealedMutation(); - if (shutter == null) throw new IllegalArgumentException(); - if (classShutter != null) { - throw new SecurityException("Cannot overwrite existing " + - "ClassShutter object"); - } - classShutter = shutter; - } - - final ClassShutter getClassShutter() - { - return classShutter; - } - - /** - * Get a value corresponding to a key. - * <p> - * Since the Context is associated with a thread it can be - * used to maintain values that can be later retrieved using - * the current thread. - * <p> - * Note that the values are maintained with the Context, so - * if the Context is disassociated from the thread the values - * cannot be retrieved. Also, if private data is to be maintained - * in this manner the key should be a java.lang.Object - * whose reference is not divulged to untrusted code. - * @param key the key used to lookup the value - * @return a value previously stored using putThreadLocal. - */ - public final Object getThreadLocal(Object key) - { - if (hashtable == null) - return null; - return hashtable.get(key); - } - - /** - * Put a value that can later be retrieved using a given key. - * <p> - * @param key the key used to index the value - * @param value the value to save - */ - public final void putThreadLocal(Object key, Object value) - { - if (sealed) onSealedMutation(); - if (hashtable == null) - hashtable = new Hashtable(); - hashtable.put(key, value); - } - - /** - * Remove values from thread-local storage. - * @param key the key for the entry to remove. - * @since 1.5 release 2 - */ - public final void removeThreadLocal(Object key) - { - if (sealed) onSealedMutation(); - if (hashtable == null) - return; - hashtable.remove(key); - } - - /** - * @deprecated - * @see #FEATURE_DYNAMIC_SCOPE - * @see #hasFeature(int) - */ - public final boolean hasCompileFunctionsWithDynamicScope() - { - return compileFunctionsWithDynamicScopeFlag; - } - - /** - * @deprecated - * @see #FEATURE_DYNAMIC_SCOPE - * @see #hasFeature(int) - */ - public final void setCompileFunctionsWithDynamicScope(boolean flag) - { - if (sealed) onSealedMutation(); - compileFunctionsWithDynamicScopeFlag = flag; - } - - /** - * @deprecated - * @see ClassCache#get(Scriptable) - * @see ClassCache#setCachingEnabled(boolean) - */ - public static void setCachingEnabled(boolean cachingEnabled) - { - } - - /** - * Set a WrapFactory for this Context. - * <p> - * The WrapFactory allows custom object wrapping behavior for - * Java object manipulated with JavaScript. - * @see WrapFactory - * @since 1.5 Release 4 - */ - public final void setWrapFactory(WrapFactory wrapFactory) - { - if (sealed) onSealedMutation(); - if (wrapFactory == null) throw new IllegalArgumentException(); - this.wrapFactory = wrapFactory; - } - - /** - * Return the current WrapFactory, or null if none is defined. - * @see WrapFactory - * @since 1.5 Release 4 - */ - public final WrapFactory getWrapFactory() - { - if (wrapFactory == null) { - wrapFactory = new WrapFactory(); - } - return wrapFactory; - } - - /** - * Return the current debugger. - * @return the debugger, or null if none is attached. - */ - public final Debugger getDebugger() - { - return debugger; - } - - /** - * Return the debugger context data associated with current context. - * @return the debugger data, or null if debugger is not attached - */ - public final Object getDebuggerContextData() - { - return debuggerData; - } - - /** - * Set the associated debugger. - * @param debugger the debugger to be used on callbacks from - * the engine. - * @param contextData arbitrary object that debugger can use to store - * per Context data. - */ - public final void setDebugger(Debugger debugger, Object contextData) - { - if (sealed) onSealedMutation(); - this.debugger = debugger; - debuggerData = contextData; - } - - /** - * Return DebuggableScript instance if any associated with the script. - * If callable supports DebuggableScript implementation, the method - * returns it. Otherwise null is returned. - */ - public static DebuggableScript getDebuggableView(Script script) - { - if (script instanceof NativeFunction) { - return ((NativeFunction)script).getDebuggableView(); - } - return null; - } - - /** - * Controls certain aspects of script semantics. - * Should be overwritten to alter default behavior. - * <p> - * The default implementation calls - * {@link ContextFactory#hasFeature(Context cx, int featureIndex)} - * that allows to customize Context behavior without introducing - * Context subclasses. {@link ContextFactory} documentation gives - * an example of hasFeature implementation. - * - * @param featureIndex feature index to check - * @return true if the <code>featureIndex</code> feature is turned on - * @see #FEATURE_NON_ECMA_GET_YEAR - * @see #FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME - * @see #FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER - * @see #FEATURE_TO_STRING_AS_SOURCE - * @see #FEATURE_PARENT_PROTO_PROPRTIES - * @see #FEATURE_E4X - * @see #FEATURE_DYNAMIC_SCOPE - * @see #FEATURE_STRICT_VARS - * @see #FEATURE_STRICT_EVAL - * @see #FEATURE_LOCATION_INFORMATION_IN_ERROR - * @see #FEATURE_STRICT_MODE - * @see #FEATURE_WARNING_AS_ERROR - * @see #FEATURE_ENHANCED_JAVA_ACCESS - */ - public boolean hasFeature(int featureIndex) - { - ContextFactory f = getFactory(); - return f.hasFeature(this, featureIndex); - } - - /** - Returns an object which specifies an E4X implementation to use within - this <code>Context</code>. Note - that the XMLLib.Factory interface should be considered experimental. - - The default implementation uses the implementation provided by this - <code>Context</code>'s {@link ContextFactory}. - - @return An XMLLib.Factory. Should not return <code>null</code> if - {@link #FEATURE_E4X} is enabled. See {@link #hasFeature}. - */ - public XMLLib.Factory getE4xImplementationFactory() { - return getFactory().getE4xImplementationFactory(); - } - - /** - * Get threshold of executed instructions counter that triggers call to - * <code>observeInstructionCount()</code>. - * When the threshold is zero, instruction counting is disabled, - * otherwise each time the run-time executes at least the threshold value - * of script instructions, <code>observeInstructionCount()</code> will - * be called. - */ - public final int getInstructionObserverThreshold() - { - return instructionThreshold; - } - - /** - * Set threshold of executed instructions counter that triggers call to - * <code>observeInstructionCount()</code>. - * When the threshold is zero, instruction counting is disabled, - * otherwise each time the run-time executes at least the threshold value - * of script instructions, <code>observeInstructionCount()</code> will - * be called.<p/> - * Note that the meaning of "instruction" is not guaranteed to be - * consistent between compiled and interpretive modes: executing a given - * script or function in the different modes will result in different - * instruction counts against the threshold. - * {@link #setGenerateObserverCount} is called with true if - * <code>threshold</code> is greater than zero, false otherwise. - * @param threshold The instruction threshold - */ - public final void setInstructionObserverThreshold(int threshold) - { - if (sealed) onSealedMutation(); - if (threshold < 0) throw new IllegalArgumentException(); - instructionThreshold = threshold; - setGenerateObserverCount(threshold > 0); - } - - /** - * Turn on or off generation of code with callbacks to - * track the count of executed instructions. - * Currently only affects JVM byte code generation: this slows down the - * generated code, but code generated without the callbacks will not - * be counted toward instruction thresholds. Rhino's interpretive - * mode does instruction counting without inserting callbacks, so - * there is no requirement to compile code differently. - * @param generateObserverCount if true, generated code will contain - * calls to accumulate an estimate of the instructions executed. - */ - public void setGenerateObserverCount(boolean generateObserverCount) { - this.generateObserverCount = generateObserverCount; - } - - /** - * Allow application to monitor counter of executed script instructions - * in Context subclasses. - * Run-time calls this when instruction counting is enabled and the counter - * reaches limit set by <code>setInstructionObserverThreshold()</code>. - * The method is useful to observe long running scripts and if necessary - * to terminate them. - * <p> - * The instruction counting support is available only for interpreted - * scripts generated when the optimization level is set to -1. - * <p> - * The default implementation calls - * {@link ContextFactory#observeInstructionCount(Context cx, - * int instructionCount)} - * that allows to customize Context behavior without introducing - * Context subclasses. - * - * @param instructionCount amount of script instruction executed since - * last call to <code>observeInstructionCount</code> - * @throws Error to terminate the script - * @see #setOptimizationLevel(int) - */ - protected void observeInstructionCount(int instructionCount) - { - ContextFactory f = getFactory(); - f.observeInstructionCount(this, instructionCount); - } - - /** - * Create class loader for generated classes. - * The method calls {@link ContextFactory#createClassLoader(ClassLoader)} - * using the result of {@link #getFactory()}. - */ - public GeneratedClassLoader createClassLoader(ClassLoader parent) - { - ContextFactory f = getFactory(); - return f.createClassLoader(parent); - } - - public final ClassLoader getApplicationClassLoader() - { - if (applicationClassLoader == null) { - ContextFactory f = getFactory(); - ClassLoader loader = f.getApplicationClassLoader(); - if (loader == null) { - ClassLoader threadLoader - = VMBridge.instance.getCurrentThreadClassLoader(); - if (threadLoader != null - && Kit.testIfCanLoadRhinoClasses(threadLoader)) - { - // Thread.getContextClassLoader is not cached since - // its caching prevents it from GC which may lead to - // a memory leak and hides updates to - // Thread.getContextClassLoader - return threadLoader; - } - // Thread.getContextClassLoader can not load Rhino classes, - // try to use the loader of ContextFactory or Context - // subclasses. - Class fClass = f.getClass(); - if (fClass != ScriptRuntime.ContextFactoryClass) { - loader = fClass.getClassLoader(); - } else { - loader = getClass().getClassLoader(); - } - } - applicationClassLoader = loader; - } - return applicationClassLoader; - } - - public final void setApplicationClassLoader(ClassLoader loader) - { - if (sealed) onSealedMutation(); - if (loader == null) { - // restore default behaviour - applicationClassLoader = null; - return; - } - if (!Kit.testIfCanLoadRhinoClasses(loader)) { - throw new IllegalArgumentException( - "Loader can not resolve Rhino classes"); - } - applicationClassLoader = loader; - } - - /********** end of API **********/ - - /** - * Internal method that reports an error for missing calls to - * enter(). - */ - static Context getContext() - { - Context cx = getCurrentContext(); - if (cx == null) { - throw new RuntimeException( - "No Context associated with current Thread"); - } - return cx; - } - - private Object compileImpl(Scriptable scope, - Reader sourceReader, String sourceString, - String sourceName, int lineno, - Object securityDomain, boolean returnFunction, - Evaluator compiler, - ErrorReporter compilationErrorReporter) - throws IOException - { - if(sourceName == null) { - sourceName = "unnamed script"; - } - if (securityDomain != null && getSecurityController() == null) { - throw new IllegalArgumentException( - "securityDomain should be null if setSecurityController() was never called"); - } - - // One of sourceReader or sourceString has to be null - if (!(sourceReader == null ^ sourceString == null)) Kit.codeBug(); - // scope should be given if and only if compiling function - if (!(scope == null ^ returnFunction)) Kit.codeBug(); - - CompilerEnvirons compilerEnv = new CompilerEnvirons(); - compilerEnv.initFromContext(this); - if (compilationErrorReporter == null) { - compilationErrorReporter = compilerEnv.getErrorReporter(); - } - - if (debugger != null) { - if (sourceReader != null) { - sourceString = Kit.readReader(sourceReader); - sourceReader = null; - } - } - - /*APPJET*/ - Parser p = InformativeParser.makeParser(compilerEnv, - compilationErrorReporter); - if (returnFunction) { - p.calledByCompileFunction = true; - } - ScriptOrFnNode tree; - if (sourceString != null) { - tree = p.parse(sourceString, sourceName, lineno); - } else { - tree = p.parse(sourceReader, sourceName, lineno); - } - if (returnFunction) { - if (!(tree.getFunctionCount() == 1 - && tree.getFirstChild() != null - && tree.getFirstChild().getType() == Token.FUNCTION)) - { - // XXX: the check just look for the first child - // and allows for more nodes after it for compatibility - // with sources like function() {};;; - throw new IllegalArgumentException( - "compileFunction only accepts source with single JS function: "+sourceString); - } - } - - if (compiler == null) { - compiler = createCompiler(); - } - - String encodedSource = p.getEncodedSource(); - - Object bytecode = compiler.compile(compilerEnv, - tree, encodedSource, - returnFunction); - - if (debugger != null) { - if (sourceString == null) Kit.codeBug(); - if (bytecode instanceof DebuggableScript) { - DebuggableScript dscript = (DebuggableScript)bytecode; - notifyDebugger_r(this, dscript, sourceString); - } else { - throw new RuntimeException("NOT SUPPORTED"); - } - } - - Object result; - if (returnFunction) { - result = compiler.createFunctionObject(this, scope, bytecode, securityDomain); - } else { - result = compiler.createScriptObject(bytecode, securityDomain); - } - - return result; - } - - private static void notifyDebugger_r(Context cx, DebuggableScript dscript, - String debugSource) - { - cx.debugger.handleCompilationDone(cx, dscript, debugSource); - for (int i = 0; i != dscript.getFunctionCount(); ++i) { - notifyDebugger_r(cx, dscript.getFunction(i), debugSource); - } - } - - private static Class codegenClass = Kit.classOrNull( - "org.mozilla.javascript.optimizer.Codegen"); - private static Class interpreterClass = Kit.classOrNull( - "org.mozilla.javascript.Interpreter"); - - private Evaluator createCompiler() - { - Evaluator result = null; - if (optimizationLevel >= 0 && codegenClass != null) { - result = (Evaluator)Kit.newInstanceOrNull(codegenClass); - } - if (result == null) { - result = createInterpreter(); - } - return result; - } - - static Evaluator createInterpreter() - { - return (Evaluator)Kit.newInstanceOrNull(interpreterClass); - } - - static String getSourcePositionFromStack(int[] linep) - { - Context cx = getCurrentContext(); - if (cx == null) - return null; - if (cx.lastInterpreterFrame != null) { - Evaluator evaluator = createInterpreter(); - if (evaluator != null) - return evaluator.getSourcePositionFromStack(cx, linep); - } - /** - * A bit of a hack, but the only way to get filename and line - * number from an enclosing frame. - */ - CharArrayWriter writer = new CharArrayWriter(); - RuntimeException re = new RuntimeException(); - re.printStackTrace(new PrintWriter(writer)); - String s = writer.toString(); - int open = -1; - int close = -1; - int colon = -1; - for (int i=0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == ':') - colon = i; - else if (c == '(') - open = i; - else if (c == ')') - close = i; - else if (c == '\n' && open != -1 && close != -1 && colon != -1 && - open < colon && colon < close) - { - String fileStr = s.substring(open + 1, colon); - if (!fileStr.endsWith(".java")) { - String lineStr = s.substring(colon + 1, close); - try { - linep[0] = Integer.parseInt(lineStr); - if (linep[0] < 0) { - linep[0] = 0; - } - return fileStr; - } - catch (NumberFormatException e) { - // fall through - } - } - open = close = colon = -1; - } - } - - return null; - } - - RegExpProxy getRegExpProxy() - { - if (regExpProxy == null) { - Class cl = Kit.classOrNull( - "org.mozilla.javascript.regexp.RegExpImpl"); - if (cl != null) { - regExpProxy = (RegExpProxy)Kit.newInstanceOrNull(cl); - } - } - return regExpProxy; - } - - final boolean isVersionECMA1() - { - return version == VERSION_DEFAULT || version >= VERSION_1_3; - } - -// The method must NOT be public or protected - SecurityController getSecurityController() - { - SecurityController global = SecurityController.global(); - if (global != null) { - return global; - } - return securityController; - } - - public final boolean isGeneratingDebugChanged() - { - return generatingDebugChanged; - } - - /** - * Add a name to the list of names forcing the creation of real - * activation objects for functions. - * - * @param name the name of the object to add to the list - */ - public void addActivationName(String name) - { - if (sealed) onSealedMutation(); - if (activationNames == null) - activationNames = new Hashtable(5); - activationNames.put(name, name); - } - - /** - * Check whether the name is in the list of names of objects - * forcing the creation of activation objects. - * - * @param name the name of the object to test - * - * @return true if an function activation object is needed. - */ - public final boolean isActivationNeeded(String name) - { - return activationNames != null && activationNames.containsKey(name); - } - - /** - * Remove a name from the list of names forcing the creation of real - * activation objects for functions. - * - * @param name the name of the object to remove from the list - */ - public void removeActivationName(String name) - { - if (sealed) onSealedMutation(); - if (activationNames != null) - activationNames.remove(name); - } - - private static String implementationVersion; - - private final ContextFactory factory; - private boolean sealed; - private Object sealKey; - - Scriptable topCallScope; - NativeCall currentActivationCall; - XMLLib cachedXMLLib; - - // for Objects, Arrays to tag themselves as being printed out, - // so they don't print themselves out recursively. - // Use ObjToIntMap instead of java.util.HashSet for JDK 1.1 compatibility - ObjToIntMap iterating; - - Object interpreterSecurityDomain; - - int version; - - private SecurityController securityController; - private ClassShutter classShutter; - private ErrorReporter errorReporter; - RegExpProxy regExpProxy; - private Locale locale; - private boolean generatingDebug; - private boolean generatingDebugChanged; - private boolean generatingSource=true; - boolean compileFunctionsWithDynamicScopeFlag; - boolean useDynamicScope; - private int optimizationLevel; - private int maximumInterpreterStackDepth; - private WrapFactory wrapFactory; - Debugger debugger; - private Object debuggerData; - private int enterCount; - private Object propertyListeners; - private Hashtable hashtable; - private ClassLoader applicationClassLoader; - - /** - * This is the list of names of objects forcing the creation of - * function activation records. - */ - Hashtable activationNames; - - // For the interpreter to store the last frame for error reports etc. - Object lastInterpreterFrame; - - // For the interpreter to store information about previous invocations - // interpreter invocations - ObjArray previousInterpreterInvocations; - - // For instruction counting (interpreter only) - int instructionCount; - int instructionThreshold; - - // It can be used to return the second index-like result from function - int scratchIndex; - - // It can be used to return the second uint32 result from function - long scratchUint32; - - // It can be used to return the second Scriptable result from function - Scriptable scratchScriptable; - - // Generate an observer count on compiled code - public boolean generateObserverCount = false; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ContextAction.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ContextAction.java deleted file mode 100644 index 1c584a9..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ContextAction.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov, igor@fastmail.fm - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * Interface to represent arbitrary action that requires to have Context - * object associated with the current thread for its execution. - */ -public interface ContextAction -{ - /** - * Execute action using the supplied Context instance. - * When Rhino runtime calls the method, <tt>cx</tt> will be associated - * with the current thread as active context. - * - * @see Context#call(ContextAction) - * @see ContextFactory#call(ContextAction) - */ - public Object run(Context cx); -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ContextFactory.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ContextFactory.java deleted file mode 100644 index 4f9fde2..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ContextFactory.java +++ /dev/null @@ -1,594 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov, igor@fastmail.fm - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * Factory class that Rhino runtime uses to create new {@link Context} - * instances. A <code>ContextFactory</code> can also notify listeners - * about context creation and release. - * <p> - * When the Rhino runtime needs to create new {@link Context} instance during - * execution of {@link Context#enter()} or {@link Context}, it will call - * {@link #makeContext()} of the current global ContextFactory. - * See {@link #getGlobal()} and {@link #initGlobal(ContextFactory)}. - * <p> - * It is also possible to use explicit ContextFactory instances for Context - * creation. This is useful to have a set of independent Rhino runtime - * instances under single JVM. See {@link #call(ContextAction)}. - * <p> - * The following example demonstrates Context customization to terminate - * scripts running more then 10 seconds and to provide better compatibility - * with JavaScript code using MSIE-specific features. - * <pre> - * import org.mozilla.javascript.*; - * - * class MyFactory extends ContextFactory - * { - * - * // Custom {@link Context} to store execution time. - * private static class MyContext extends Context - * { - * long startTime; - * } - * - * static { - * // Initialize GlobalFactory with custom factory - * ContextFactory.initGlobal(new MyFactory()); - * } - * - * // Override {@link #makeContext()} - * protected Context makeContext() - * { - * MyContext cx = new MyContext(); - * // Use pure interpreter mode to allow for - * // {@link #observeInstructionCount(Context, int)} to work - * cx.setOptimizationLevel(-1); - * // Make Rhino runtime to call observeInstructionCount - * // each 10000 bytecode instructions - * cx.setInstructionObserverThreshold(10000); - * return cx; - * } - * - * // Override {@link #hasFeature(Context, int)} - * public boolean hasFeature(Context cx, int featureIndex) - * { - * // Turn on maximum compatibility with MSIE scripts - * switch (featureIndex) { - * case {@link Context#FEATURE_NON_ECMA_GET_YEAR}: - * return true; - * - * case {@link Context#FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME}: - * return true; - * - * case {@link Context#FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER}: - * return true; - * - * case {@link Context#FEATURE_PARENT_PROTO_PROPERTIES}: - * return false; - * } - * return super.hasFeature(cx, featureIndex); - * } - * - * // Override {@link #observeInstructionCount(Context, int)} - * protected void observeInstructionCount(Context cx, int instructionCount) - * { - * MyContext mcx = (MyContext)cx; - * long currentTime = System.currentTimeMillis(); - * if (currentTime - mcx.startTime > 10*1000) { - * // More then 10 seconds from Context creation time: - * // it is time to stop the script. - * // Throw Error instance to ensure that script will never - * // get control back through catch or finally. - * throw new Error(); - * } - * } - * - * // Override {@link #doTopCall(Callable, - Context, Scriptable, - Scriptable, Object[])} - * protected Object doTopCall(Callable callable, - * Context cx, Scriptable scope, - * Scriptable thisObj, Object[] args) - * { - * MyContext mcx = (MyContext)cx; - * mcx.startTime = System.currentTimeMillis(); - * - * return super.doTopCall(callable, cx, scope, thisObj, args); - * } - * - * } - * - * </pre> - */ - -public class ContextFactory -{ - private static volatile boolean hasCustomGlobal; - private static ContextFactory global = new ContextFactory(); - - private volatile boolean sealed; - - private final Object listenersLock = new Object(); - private volatile Object listeners; - private boolean disabledListening; - private ClassLoader applicationClassLoader; - - /** - * Listener of {@link Context} creation and release events. - */ - public interface Listener - { - /** - * Notify about newly created {@link Context} object. - */ - public void contextCreated(Context cx); - - /** - * Notify that the specified {@link Context} instance is no longer - * associated with the current thread. - */ - public void contextReleased(Context cx); - } - - /** - * Get global ContextFactory. - * - * @see #hasExplicitGlobal() - * @see #initGlobal(ContextFactory) - */ - public static ContextFactory getGlobal() - { - return global; - } - - /** - * Check if global factory was set. - * Return true to indicate that {@link #initGlobal(ContextFactory)} was - * already called and false to indicate that the global factory was not - * explicitly set. - * - * @see #getGlobal() - * @see #initGlobal(ContextFactory) - */ - public static boolean hasExplicitGlobal() - { - return hasCustomGlobal; - } - - /** - * Set global ContextFactory. - * The method can only be called once. - * - * @see #getGlobal() - * @see #hasExplicitGlobal() - */ - public synchronized static void initGlobal(ContextFactory factory) - { - if (factory == null) { - throw new IllegalArgumentException(); - } - if (hasCustomGlobal) { - throw new IllegalStateException(); - } - hasCustomGlobal = true; - global = factory; - } - - /** - * Create new {@link Context} instance to be associated with the current - * thread. - * This is a callback method used by Rhino to create {@link Context} - * instance when it is necessary to associate one with the current - * execution thread. <tt>makeContext()</tt> is allowed to call - * {@link Context#seal(Object)} on the result to prevent - * {@link Context} changes by hostile scripts or applets. - */ - protected Context makeContext() - { - return new Context(this); - } - - /** - * Implementation of {@link Context#hasFeature(int featureIndex)}. - * This can be used to customize {@link Context} without introducing - * additional subclasses. - */ - protected boolean hasFeature(Context cx, int featureIndex) - { - int version; - switch (featureIndex) { - case Context.FEATURE_NON_ECMA_GET_YEAR: - /* - * During the great date rewrite of 1.3, we tried to track the - * evolving ECMA standard, which then had a definition of - * getYear which always subtracted 1900. Which we - * implemented, not realizing that it was incompatible with - * the old behavior... now, rather than thrash the behavior - * yet again, we've decided to leave it with the - 1900 - * behavior and point people to the getFullYear method. But - * we try to protect existing scripts that have specified a - * version... - */ - version = cx.getLanguageVersion(); - return (version == Context.VERSION_1_0 - || version == Context.VERSION_1_1 - || version == Context.VERSION_1_2); - - case Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME: - return false; - - case Context.FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER: - return false; - - case Context.FEATURE_TO_STRING_AS_SOURCE: - version = cx.getLanguageVersion(); - return version == Context.VERSION_1_2; - - case Context.FEATURE_PARENT_PROTO_PROPERTIES: - return true; - - case Context.FEATURE_E4X: - version = cx.getLanguageVersion(); - return (version == Context.VERSION_DEFAULT - || version >= Context.VERSION_1_6); - - case Context.FEATURE_DYNAMIC_SCOPE: - return false; - - case Context.FEATURE_STRICT_VARS: - return false; - - case Context.FEATURE_STRICT_EVAL: - return false; - - case Context.FEATURE_LOCATION_INFORMATION_IN_ERROR: - return false; - - case Context.FEATURE_STRICT_MODE: - return false; - - case Context.FEATURE_WARNING_AS_ERROR: - return false; - - case Context.FEATURE_ENHANCED_JAVA_ACCESS: - return false; - } - // It is a bug to call the method with unknown featureIndex - throw new IllegalArgumentException(String.valueOf(featureIndex)); - } - - private boolean isDom3Present() { - Class nodeClass = Kit.classOrNull("org.w3c.dom.Node"); - if (nodeClass == null) return false; - // Check to see whether DOM3 is present; use a new method defined in - // DOM3 that is vital to our implementation - try { - nodeClass.getMethod("getUserData", new Class[] { String.class }); - return true; - } catch (NoSuchMethodException e) { - return false; - } - } - - /** - * Provides a default - * {@link org.mozilla.javascript.xml.XMLLib.Factory XMLLib.Factory} - * to be used by the <code>Context</code> instances produced by this - * factory. See {@link Context#getE4xImplementationFactory} for details. - * - * May return null, in which case E4X functionality is not supported in - * Rhino. - * - * The default implementation now prefers the DOM3 E4X implementation. - */ - protected org.mozilla.javascript.xml.XMLLib.Factory - getE4xImplementationFactory() - { - // Must provide default implementation, rather than abstract method, - // so that past implementors of ContextFactory do not fail at runtime - // upon invocation of this method. - // Note that the default implementation returns null if we - // neither have XMLBeans nor a DOM3 implementation present. - - if (isDom3Present()) { - return org.mozilla.javascript.xml.XMLLib.Factory.create( - "org.mozilla.javascript.xmlimpl.XMLLibImpl" - ); - } else if (Kit.classOrNull("org.apache.xmlbeans.XmlCursor") != null) { - return org.mozilla.javascript.xml.XMLLib.Factory.create( - "org.mozilla.javascript.xml.impl.xmlbeans.XMLLibImpl" - ); - } else { - return null; - } - } - - - /** - * Create class loader for generated classes. - * This method creates an instance of the default implementation - * of {@link GeneratedClassLoader}. Rhino uses this interface to load - * generated JVM classes when no {@link SecurityController} - * is installed. - * Application can override the method to provide custom class loading. - */ - protected GeneratedClassLoader createClassLoader(ClassLoader parent) - { - return new DefiningClassLoader(parent); - } - - /** - * Get ClassLoader to use when searching for Java classes. - * Unless it was explicitly initialized with - * {@link #initApplicationClassLoader(ClassLoader)} the method returns - * null to indicate that Thread.getContextClassLoader() should be used. - */ - public final ClassLoader getApplicationClassLoader() - { - return applicationClassLoader; - } - - /** - * Set explicit class loader to use when searching for Java classes. - * - * @see #getApplicationClassLoader() - */ - public final void initApplicationClassLoader(ClassLoader loader) - { - if (loader == null) - throw new IllegalArgumentException("loader is null"); - if (!Kit.testIfCanLoadRhinoClasses(loader)) - throw new IllegalArgumentException( - "Loader can not resolve Rhino classes"); - - if (this.applicationClassLoader != null) - throw new IllegalStateException( - "applicationClassLoader can only be set once"); - checkNotSealed(); - - this.applicationClassLoader = loader; - } - - /** - * Execute top call to script or function. - * When the runtime is about to execute a script or function that will - * create the first stack frame with scriptable code, it calls this method - * to perform the real call. In this way execution of any script - * happens inside this function. - */ - protected Object doTopCall(Callable callable, - Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - return callable.call(cx, scope, thisObj, args); - } - - /** - * Implementation of - * {@link Context#observeInstructionCount(int instructionCount)}. - * This can be used to customize {@link Context} without introducing - * additional subclasses. - */ - protected void observeInstructionCount(Context cx, int instructionCount) - { - } - - protected void onContextCreated(Context cx) - { - Object listeners = this.listeners; - for (int i = 0; ; ++i) { - Listener l = (Listener)Kit.getListener(listeners, i); - if (l == null) - break; - l.contextCreated(cx); - } - } - - protected void onContextReleased(Context cx) - { - Object listeners = this.listeners; - for (int i = 0; ; ++i) { - Listener l = (Listener)Kit.getListener(listeners, i); - if (l == null) - break; - l.contextReleased(cx); - } - } - - public final void addListener(Listener listener) - { - checkNotSealed(); - synchronized (listenersLock) { - if (disabledListening) { - throw new IllegalStateException(); - } - listeners = Kit.addListener(listeners, listener); - } - } - - public final void removeListener(Listener listener) - { - checkNotSealed(); - synchronized (listenersLock) { - if (disabledListening) { - throw new IllegalStateException(); - } - listeners = Kit.removeListener(listeners, listener); - } - } - - /** - * The method is used only to implement - * Context.disableStaticContextListening() - */ - final void disableContextListening() - { - checkNotSealed(); - synchronized (listenersLock) { - disabledListening = true; - listeners = null; - } - } - - /** - * Checks if this is a sealed ContextFactory. - * @see #seal() - */ - public final boolean isSealed() - { - return sealed; - } - - /** - * Seal this ContextFactory so any attempt to modify it like to add or - * remove its listeners will throw an exception. - * @see #isSealed() - */ - public final void seal() - { - checkNotSealed(); - sealed = true; - } - - protected final void checkNotSealed() - { - if (sealed) throw new IllegalStateException(); - } - - /** - * Call {@link ContextAction#run(Context cx)} - * using the {@link Context} instance associated with the current thread. - * If no Context is associated with the thread, then - * {@link #makeContext()} will be called to construct - * new Context instance. The instance will be temporary associated - * with the thread during call to {@link ContextAction#run(Context)}. - * - * @see ContextFactory#call(ContextAction) - * @see Context#call(ContextFactory factory, Callable callable, - * Scriptable scope, Scriptable thisObj, - * Object[] args) - */ - public final Object call(ContextAction action) - { - return Context.call(this, action); - } - - /** - * Get a context associated with the current thread, creating one if need - * be. The Context stores the execution state of the JavaScript engine, so - * it is required that the context be entered before execution may begin. - * Once a thread has entered a Context, then getCurrentContext() may be - * called to find the context that is associated with the current thread. - * <p> - * Calling <code>enterContext()</code> will return either the Context - * currently associated with the thread, or will create a new context and - * associate it with the current thread. Each call to - * <code>enterContext()</code> must have a matching call to - * {@link Context#exit()}. - * <pre> - * Context cx = contextFactory.enterContext(); - * try { - * ... - * cx.evaluateString(...); - * } finally { - * Context.exit(); - * } - * </pre> - * Instead of using <tt>enterContext()</tt>, <tt>exit()</tt> pair consider - * using {@link #call(ContextAction)} which guarantees proper association - * of Context instances with the current thread. - * With this method the above example becomes: - * <pre> - * ContextFactory.call(new ContextAction() { - * public Object run(Context cx) { - * ... - * cx.evaluateString(...); - * return null; - * } - * }); - * </pre> - * @return a Context associated with the current thread - * @see Context#getCurrentContext() - * @see Context#exit() - * @see #call(ContextAction) - */ - public Context enterContext() - { - return enterContext(null); - } - - /** - * @deprecated use {@link #enterContext()} instead - * @return a Context associated with the current thread - */ - public final Context enter() - { - return enterContext(null); - } - - /** - * @deprecated Use {@link Context#exit()} instead. - */ - public final void exit() - { - Context.exit(); - } - - /** - * Get a Context associated with the current thread, using the given - * Context if need be. - * <p> - * The same as <code>enterContext()</code> except that <code>cx</code> - * is associated with the current thread and returned if the current thread - * has no associated context and <code>cx</code> is not associated with any - * other thread. - * @param cx a Context to associate with the thread if possible - * @return a Context associated with the current thread - * @see #enterContext() - * @see #call(ContextAction) - * @throws IllegalStateException if <code>cx</code> is already associated - * with a different thread - */ - public final Context enterContext(Context cx) - { - return Context.enter(cx, this); - } -}
\ No newline at end of file diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ContextListener.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ContextListener.java deleted file mode 100644 index 5e17145..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ContextListener.java +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * @deprecated Embeddings that wish to customize newly created - * {@link Context} instances should implement - * {@link ContextFactory.Listener}. - */ -public interface ContextListener extends ContextFactory.Listener -{ - - /** - * @deprecated Rhino runtime never calls the method. - */ - public void contextEntered(Context cx); - - /** - * @deprecated Rhino runtime never calls the method. - */ - public void contextExited(Context cx); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/DToA.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/DToA.java deleted file mode 100644 index ad2a68a..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/DToA.java +++ /dev/null @@ -1,1271 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Waldemar Horwat - * Roger Lawrence - * Attila Szegedi - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -/**************************************************************** - * - * The author of this software is David M. Gay. - * - * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - * - ***************************************************************/ - -package org.mozilla.javascript; - -import java.math.BigInteger; - -class DToA { - - -/* "-0.0000...(1073 zeros after decimal point)...0001\0" is the longest string that we could produce, - * which occurs when printing -5e-324 in binary. We could compute a better estimate of the size of - * the output string and malloc fewer bytes depending on d and base, but why bother? */ - - private static final int DTOBASESTR_BUFFER_SIZE = 1078; - - private static char BASEDIGIT(int digit) { - return (char)((digit >= 10) ? 'a' - 10 + digit : '0' + digit); - } - - static final int - DTOSTR_STANDARD = 0, /* Either fixed or exponential format; round-trip */ - DTOSTR_STANDARD_EXPONENTIAL = 1, /* Always exponential format; round-trip */ - DTOSTR_FIXED = 2, /* Round to <precision> digits after the decimal point; exponential if number is large */ - DTOSTR_EXPONENTIAL = 3, /* Always exponential format; <precision> significant digits */ - DTOSTR_PRECISION = 4; /* Either fixed or exponential format; <precision> significant digits */ - - - private static final int Frac_mask = 0xfffff; - private static final int Exp_shift = 20; - private static final int Exp_msk1 = 0x100000; - - private static final long Frac_maskL = 0xfffffffffffffL; - private static final int Exp_shiftL = 52; - private static final long Exp_msk1L = 0x10000000000000L; - - private static final int Bias = 1023; - private static final int P = 53; - - private static final int Exp_shift1 = 20; - private static final int Exp_mask = 0x7ff00000; - private static final int Exp_mask_shifted = 0x7ff; - private static final int Bndry_mask = 0xfffff; - private static final int Log2P = 1; - - private static final int Sign_bit = 0x80000000; - private static final int Exp_11 = 0x3ff00000; - private static final int Ten_pmax = 22; - private static final int Quick_max = 14; - private static final int Bletch = 0x10; - private static final int Frac_mask1 = 0xfffff; - private static final int Int_max = 14; - private static final int n_bigtens = 5; - - - private static final double tens[] = { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22 - }; - - private static final double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; - - private static int lo0bits(int y) - { - int k; - int x = y; - - if ((x & 7) != 0) { - if ((x & 1) != 0) - return 0; - if ((x & 2) != 0) { - return 1; - } - return 2; - } - k = 0; - if ((x & 0xffff) == 0) { - k = 16; - x >>>= 16; - } - if ((x & 0xff) == 0) { - k += 8; - x >>>= 8; - } - if ((x & 0xf) == 0) { - k += 4; - x >>>= 4; - } - if ((x & 0x3) == 0) { - k += 2; - x >>>= 2; - } - if ((x & 1) == 0) { - k++; - x >>>= 1; - if ((x & 1) == 0) - return 32; - } - return k; - } - - /* Return the number (0 through 32) of most significant zero bits in x. */ - private static int hi0bits(int x) - { - int k = 0; - - if ((x & 0xffff0000) == 0) { - k = 16; - x <<= 16; - } - if ((x & 0xff000000) == 0) { - k += 8; - x <<= 8; - } - if ((x & 0xf0000000) == 0) { - k += 4; - x <<= 4; - } - if ((x & 0xc0000000) == 0) { - k += 2; - x <<= 2; - } - if ((x & 0x80000000) == 0) { - k++; - if ((x & 0x40000000) == 0) - return 32; - } - return k; - } - - private static void stuffBits(byte bits[], int offset, int val) - { - bits[offset] = (byte)(val >> 24); - bits[offset + 1] = (byte)(val >> 16); - bits[offset + 2] = (byte)(val >> 8); - bits[offset + 3] = (byte)(val); - } - - /* Convert d into the form b*2^e, where b is an odd integer. b is the returned - * Bigint and e is the returned binary exponent. Return the number of significant - * bits in b in bits. d must be finite and nonzero. */ - private static BigInteger d2b(double d, int[] e, int[] bits) - { - byte dbl_bits[]; - int i, k, y, z, de; - long dBits = Double.doubleToLongBits(d); - int d0 = (int)(dBits >>> 32); - int d1 = (int)(dBits); - - z = d0 & Frac_mask; - d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ - - if ((de = (d0 >>> Exp_shift)) != 0) - z |= Exp_msk1; - - if ((y = d1) != 0) { - dbl_bits = new byte[8]; - k = lo0bits(y); - y >>>= k; - if (k != 0) { - stuffBits(dbl_bits, 4, y | z << (32 - k)); - z >>= k; - } - else - stuffBits(dbl_bits, 4, y); - stuffBits(dbl_bits, 0, z); - i = (z != 0) ? 2 : 1; - } - else { - // JS_ASSERT(z); - dbl_bits = new byte[4]; - k = lo0bits(z); - z >>>= k; - stuffBits(dbl_bits, 0, z); - k += 32; - i = 1; - } - if (de != 0) { - e[0] = de - Bias - (P-1) + k; - bits[0] = P - k; - } - else { - e[0] = de - Bias - (P-1) + 1 + k; - bits[0] = 32*i - hi0bits(z); - } - return new BigInteger(dbl_bits); - } - - static String JS_dtobasestr(int base, double d) - { - if (!(2 <= base && base <= 36)) - throw new IllegalArgumentException("Bad base: "+base); - - /* Check for Infinity and NaN */ - if (Double.isNaN(d)) { - return "NaN"; - } else if (Double.isInfinite(d)) { - return (d > 0.0) ? "Infinity" : "-Infinity"; - } else if (d == 0) { - // ALERT: should it distinguish -0.0 from +0.0 ? - return "0"; - } - - boolean negative; - if (d >= 0.0) { - negative = false; - } else { - negative = true; - d = -d; - } - - /* Get the integer part of d including '-' sign. */ - String intDigits; - - double dfloor = Math.floor(d); - long lfloor = (long)dfloor; - if (lfloor == dfloor) { - // int part fits long - intDigits = Long.toString((negative) ? -lfloor : lfloor, base); - } else { - // BigInteger should be used - long floorBits = Double.doubleToLongBits(dfloor); - int exp = (int)(floorBits >> Exp_shiftL) & Exp_mask_shifted; - long mantissa; - if (exp == 0) { - mantissa = (floorBits & Frac_maskL) << 1; - } else { - mantissa = (floorBits & Frac_maskL) | Exp_msk1L; - } - if (negative) { - mantissa = -mantissa; - } - exp -= 1075; - BigInteger x = BigInteger.valueOf(mantissa); - if (exp > 0) { - x = x.shiftLeft(exp); - } else if (exp < 0) { - x = x.shiftRight(-exp); - } - intDigits = x.toString(base); - } - - if (d == dfloor) { - // No fraction part - return intDigits; - } else { - /* We have a fraction. */ - - char[] buffer; /* The output string */ - int p; /* index to current position in the buffer */ - int digit; - double df; /* The fractional part of d */ - BigInteger b; - - buffer = new char[DTOBASESTR_BUFFER_SIZE]; - p = 0; - df = d - dfloor; - - long dBits = Double.doubleToLongBits(d); - int word0 = (int)(dBits >> 32); - int word1 = (int)(dBits); - - int[] e = new int[1]; - int[] bbits = new int[1]; - - b = d2b(df, e, bbits); -// JS_ASSERT(e < 0); - /* At this point df = b * 2^e. e must be less than zero because 0 < df < 1. */ - - int s2 = -(word0 >>> Exp_shift1 & Exp_mask >> Exp_shift1); - if (s2 == 0) - s2 = -1; - s2 += Bias + P; - /* 1/2^s2 = (nextDouble(d) - d)/2 */ -// JS_ASSERT(-s2 < e); - BigInteger mlo = BigInteger.valueOf(1); - BigInteger mhi = mlo; - if ((word1 == 0) && ((word0 & Bndry_mask) == 0) - && ((word0 & (Exp_mask & Exp_mask << 1)) != 0)) { - /* The special case. Here we want to be within a quarter of the last input - significant digit instead of one half of it when the output string's value is less than d. */ - s2 += Log2P; - mhi = BigInteger.valueOf(1<<Log2P); - } - - b = b.shiftLeft(e[0] + s2); - BigInteger s = BigInteger.valueOf(1); - s = s.shiftLeft(s2); - /* At this point we have the following: - * s = 2^s2; - * 1 > df = b/2^s2 > 0; - * (d - prevDouble(d))/2 = mlo/2^s2; - * (nextDouble(d) - d)/2 = mhi/2^s2. */ - BigInteger bigBase = BigInteger.valueOf(base); - - boolean done = false; - do { - b = b.multiply(bigBase); - BigInteger[] divResult = b.divideAndRemainder(s); - b = divResult[1]; - digit = (char)(divResult[0].intValue()); - if (mlo == mhi) - mlo = mhi = mlo.multiply(bigBase); - else { - mlo = mlo.multiply(bigBase); - mhi = mhi.multiply(bigBase); - } - - /* Do we yet have the shortest string that will round to d? */ - int j = b.compareTo(mlo); - /* j is b/2^s2 compared with mlo/2^s2. */ - BigInteger delta = s.subtract(mhi); - int j1 = (delta.signum() <= 0) ? 1 : b.compareTo(delta); - /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */ - if (j1 == 0 && ((word1 & 1) == 0)) { - if (j > 0) - digit++; - done = true; - } else - if (j < 0 || (j == 0 && ((word1 & 1) == 0))) { - if (j1 > 0) { - /* Either dig or dig+1 would work here as the least significant digit. - Use whichever would produce an output value closer to d. */ - b = b.shiftLeft(1); - j1 = b.compareTo(s); - if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output - * such as 3.5 in base 3. */ - digit++; - } - done = true; - } else if (j1 > 0) { - digit++; - done = true; - } -// JS_ASSERT(digit < (uint32)base); - buffer[p++] = BASEDIGIT(digit); - } while (!done); - - StringBuffer sb = new StringBuffer(intDigits.length() + 1 + p); - sb.append(intDigits); - sb.append('.'); - sb.append(buffer, 0, p); - return sb.toString(); - } - - } - - /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. - * - * Inspired by "How to Print Floating-Point Numbers Accurately" by - * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101]. - * - * Modifications: - * 1. Rather than iterating, we use a simple numeric overestimate - * to determine k = floor(log10(d)). We scale relevant - * quantities using O(log2(k)) rather than O(k) multiplications. - * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't - * try to generate digits strictly left to right. Instead, we - * compute with fewer bits and propagate the carry if necessary - * when rounding the final digit up. This is often faster. - * 3. Under the assumption that input will be rounded nearest, - * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. - * That is, we allow equality in stopping tests when the - * round-nearest rule will give the same floating-point value - * as would satisfaction of the stopping test with strict - * inequality. - * 4. We remove common factors of powers of 2 from relevant - * quantities. - * 5. When converting floating-point integers less than 1e16, - * we use floating-point arithmetic rather than resorting - * to multiple-precision integers. - * 6. When asked to produce fewer than 15 digits, we first try - * to get by with floating-point arithmetic; we resort to - * multiple-precision integer arithmetic only if we cannot - * guarantee that the floating-point calculation has given - * the correctly rounded result. For k requested digits and - * "uniformly" distributed input, the probability is - * something like 10^(k-15) that we must resort to the Long - * calculation. - */ - - static int word0(double d) - { - long dBits = Double.doubleToLongBits(d); - return (int)(dBits >> 32); - } - - static double setWord0(double d, int i) - { - long dBits = Double.doubleToLongBits(d); - dBits = ((long)i << 32) | (dBits & 0x0FFFFFFFFL); - return Double.longBitsToDouble(dBits); - } - - static int word1(double d) - { - long dBits = Double.doubleToLongBits(d); - return (int)(dBits); - } - - /* Return b * 5^k. k must be nonnegative. */ - // XXXX the C version built a cache of these - static BigInteger pow5mult(BigInteger b, int k) - { - return b.multiply(BigInteger.valueOf(5).pow(k)); - } - - static boolean roundOff(StringBuffer buf) - { - int i = buf.length(); - while (i != 0) { - --i; - char c = buf.charAt(i); - if (c != '9') { - buf.setCharAt(i, (char)(c + 1)); - buf.setLength(i + 1); - return false; - } - } - buf.setLength(0); - return true; - } - - /* Always emits at least one digit. */ - /* If biasUp is set, then rounding in modes 2 and 3 will round away from zero - * when the number is exactly halfway between two representable values. For example, - * rounding 2.5 to zero digits after the decimal point will return 3 and not 2. - * 2.49 will still round to 2, and 2.51 will still round to 3. */ - /* bufsize should be at least 20 for modes 0 and 1. For the other modes, - * bufsize should be two greater than the maximum number of output characters expected. */ - static int - JS_dtoa(double d, int mode, boolean biasUp, int ndigits, - boolean[] sign, StringBuffer buf) - { - /* Arguments ndigits, decpt, sign are similar to those - of ecvt and fcvt; trailing zeros are suppressed from - the returned string. If not null, *rve is set to point - to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to 9999. - - mode: - 0 ==> shortest string that yields d when read in - and rounded to nearest. - 1 ==> like 0, but with Steele & White stopping rule; - e.g. with IEEE P754 arithmetic , mode 0 gives - 1e23 whereas mode 1 gives 9.999999999999999e22. - 2 ==> max(1,ndigits) significant digits. This gives a - return value similar to that of ecvt, except - that trailing zeros are suppressed. - 3 ==> through ndigits past the decimal point. This - gives a return value similar to that from fcvt, - except that trailing zeros are suppressed, and - ndigits can be negative. - 4-9 should give the same return values as 2-3, i.e., - 4 <= mode <= 9 ==> same return as mode - 2 + (mode & 1). These modes are mainly for - debugging; often they run slower but sometimes - faster than modes 2-3. - 4,5,8,9 ==> left-to-right digit generation. - 6-9 ==> don't try fast floating-point estimate - (if applicable). - - Values of mode other than 0-9 are treated as mode 0. - - Sufficient space is allocated to the return value - to hold the suppressed trailing zeros. - */ - - int b2, b5, i, ieps, ilim, ilim0, ilim1, - j, j1, k, k0, m2, m5, s2, s5; - char dig; - long L; - long x; - BigInteger b, b1, delta, mlo, mhi, S; - int[] be = new int[1]; - int[] bbits = new int[1]; - double d2, ds, eps; - boolean spec_case, denorm, k_check, try_quick, leftright; - - if ((word0(d) & Sign_bit) != 0) { - /* set sign for everything, including 0's and NaNs */ - sign[0] = true; - // word0(d) &= ~Sign_bit; /* clear sign bit */ - d = setWord0(d, word0(d) & ~Sign_bit); - } - else - sign[0] = false; - - if ((word0(d) & Exp_mask) == Exp_mask) { - /* Infinity or NaN */ - buf.append(((word1(d) == 0) && ((word0(d) & Frac_mask) == 0)) ? "Infinity" : "NaN"); - return 9999; - } - if (d == 0) { -// no_digits: - buf.setLength(0); - buf.append('0'); /* copy "0" to buffer */ - return 1; - } - - b = d2b(d, be, bbits); - if ((i = (word0(d) >>> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) { - d2 = setWord0(d, (word0(d) & Frac_mask1) | Exp_11); - /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 - * log10(x) = log(x) / log(10) - * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) - * - * This suggests computing an approximation k to log10(d) by - * - * k = (i - Bias)*0.301029995663981 - * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); - * - * We want k to be too large rather than too small. - * The error in the first-order Taylor series approximation - * is in our favor, so we just round up the constant enough - * to compensate for any error in the multiplication of - * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, - * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, - * adding 1e-13 to the constant term more than suffices. - * Hence we adjust the constant term to 0.1760912590558. - * (We could get a more accurate k by invoking log10, - * but this is probably not worthwhile.) - */ - i -= Bias; - denorm = false; - } - else { - /* d is denormalized */ - i = bbits[0] + be[0] + (Bias + (P-1) - 1); - x = (i > 32) ? word0(d) << (64 - i) | word1(d) >>> (i - 32) : word1(d) << (32 - i); -// d2 = x; -// word0(d2) -= 31*Exp_msk1; /* adjust exponent */ - d2 = setWord0(x, word0(x) - 31*Exp_msk1); - i -= (Bias + (P-1) - 1) + 1; - denorm = true; - } - /* At this point d = f*2^i, where 1 <= f < 2. d2 is an approximation of f. */ - ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; - k = (int)ds; - if (ds < 0.0 && ds != k) - k--; /* want k = floor(ds) */ - k_check = true; - if (k >= 0 && k <= Ten_pmax) { - if (d < tens[k]) - k--; - k_check = false; - } - /* At this point floor(log10(d)) <= k <= floor(log10(d))+1. - If k_check is zero, we're guaranteed that k = floor(log10(d)). */ - j = bbits[0] - i - 1; - /* At this point d = b/2^j, where b is an odd integer. */ - if (j >= 0) { - b2 = 0; - s2 = j; - } - else { - b2 = -j; - s2 = 0; - } - if (k >= 0) { - b5 = 0; - s5 = k; - s2 += k; - } - else { - b2 -= k; - b5 = -k; - s5 = 0; - } - /* At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5), where b is an odd integer, - b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0. */ - if (mode < 0 || mode > 9) - mode = 0; - try_quick = true; - if (mode > 5) { - mode -= 4; - try_quick = false; - } - leftright = true; - ilim = ilim1 = 0; - switch(mode) { - case 0: - case 1: - ilim = ilim1 = -1; - i = 18; - ndigits = 0; - break; - case 2: - leftright = false; - /* no break */ - case 4: - if (ndigits <= 0) - ndigits = 1; - ilim = ilim1 = i = ndigits; - break; - case 3: - leftright = false; - /* no break */ - case 5: - i = ndigits + k + 1; - ilim = i; - ilim1 = i - 1; - if (i <= 0) - i = 1; - } - /* ilim is the maximum number of significant digits we want, based on k and ndigits. */ - /* ilim1 is the maximum number of significant digits we want, based on k and ndigits, - when it turns out that k was computed too high by one. */ - - boolean fast_failed = false; - if (ilim >= 0 && ilim <= Quick_max && try_quick) { - - /* Try to get by with floating-point arithmetic. */ - - i = 0; - d2 = d; - k0 = k; - ilim0 = ilim; - ieps = 2; /* conservative */ - /* Divide d by 10^k, keeping track of the roundoff error and avoiding overflows. */ - if (k > 0) { - ds = tens[k&0xf]; - j = k >> 4; - if ((j & Bletch) != 0) { - /* prevent overflows */ - j &= Bletch - 1; - d /= bigtens[n_bigtens-1]; - ieps++; - } - for(; (j != 0); j >>= 1, i++) - if ((j & 1) != 0) { - ieps++; - ds *= bigtens[i]; - } - d /= ds; - } - else if ((j1 = -k) != 0) { - d *= tens[j1 & 0xf]; - for(j = j1 >> 4; (j != 0); j >>= 1, i++) - if ((j & 1) != 0) { - ieps++; - d *= bigtens[i]; - } - } - /* Check that k was computed correctly. */ - if (k_check && d < 1.0 && ilim > 0) { - if (ilim1 <= 0) - fast_failed = true; - else { - ilim = ilim1; - k--; - d *= 10.; - ieps++; - } - } - /* eps bounds the cumulative error. */ -// eps = ieps*d + 7.0; -// word0(eps) -= (P-1)*Exp_msk1; - eps = ieps*d + 7.0; - eps = setWord0(eps, word0(eps) - (P-1)*Exp_msk1); - if (ilim == 0) { - S = mhi = null; - d -= 5.0; - if (d > eps) { - buf.append('1'); - k++; - return k + 1; - } - if (d < -eps) { - buf.setLength(0); - buf.append('0'); /* copy "0" to buffer */ - return 1; - } - fast_failed = true; - } - if (!fast_failed) { - fast_failed = true; - if (leftright) { - /* Use Steele & White method of only - * generating digits needed. - */ - eps = 0.5/tens[ilim-1] - eps; - for(i = 0;;) { - L = (long)d; - d -= L; - buf.append((char)('0' + L)); - if (d < eps) { - return k + 1; - } - if (1.0 - d < eps) { -// goto bump_up; - char lastCh; - while (true) { - lastCh = buf.charAt(buf.length() - 1); - buf.setLength(buf.length() - 1); - if (lastCh != '9') break; - if (buf.length() == 0) { - k++; - lastCh = '0'; - break; - } - } - buf.append((char)(lastCh + 1)); - return k + 1; - } - if (++i >= ilim) - break; - eps *= 10.0; - d *= 10.0; - } - } - else { - /* Generate ilim digits, then fix them up. */ - eps *= tens[ilim-1]; - for(i = 1;; i++, d *= 10.0) { - L = (long)d; - d -= L; - buf.append((char)('0' + L)); - if (i == ilim) { - if (d > 0.5 + eps) { -// goto bump_up; - char lastCh; - while (true) { - lastCh = buf.charAt(buf.length() - 1); - buf.setLength(buf.length() - 1); - if (lastCh != '9') break; - if (buf.length() == 0) { - k++; - lastCh = '0'; - break; - } - } - buf.append((char)(lastCh + 1)); - return k + 1; - } - else - if (d < 0.5 - eps) { - stripTrailingZeroes(buf); -// while(*--s == '0') ; -// s++; - return k + 1; - } - break; - } - } - } - } - if (fast_failed) { - buf.setLength(0); - d = d2; - k = k0; - ilim = ilim0; - } - } - - /* Do we have a "small" integer? */ - - if (be[0] >= 0 && k <= Int_max) { - /* Yes. */ - ds = tens[k]; - if (ndigits < 0 && ilim <= 0) { - S = mhi = null; - if (ilim < 0 || d < 5*ds || (!biasUp && d == 5*ds)) { - buf.setLength(0); - buf.append('0'); /* copy "0" to buffer */ - return 1; - } - buf.append('1'); - k++; - return k + 1; - } - for(i = 1;; i++) { - L = (long) (d / ds); - d -= L*ds; - buf.append((char)('0' + L)); - if (i == ilim) { - d += d; - if ((d > ds) || (d == ds && (((L & 1) != 0) || biasUp))) { -// bump_up: -// while(*--s == '9') -// if (s == buf) { -// k++; -// *s = '0'; -// break; -// } -// ++*s++; - char lastCh; - while (true) { - lastCh = buf.charAt(buf.length() - 1); - buf.setLength(buf.length() - 1); - if (lastCh != '9') break; - if (buf.length() == 0) { - k++; - lastCh = '0'; - break; - } - } - buf.append((char)(lastCh + 1)); - } - break; - } - d *= 10.0; - if (d == 0) - break; - } - return k + 1; - } - - m2 = b2; - m5 = b5; - mhi = mlo = null; - if (leftright) { - if (mode < 2) { - i = (denorm) ? be[0] + (Bias + (P-1) - 1 + 1) : 1 + P - bbits[0]; - /* i is 1 plus the number of trailing zero bits in d's significand. Thus, - (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k. */ - } - else { - j = ilim - 1; - if (m5 >= j) - m5 -= j; - else { - s5 += j -= m5; - b5 += j; - m5 = 0; - } - if ((i = ilim) < 0) { - m2 -= i; - i = 0; - } - /* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */ - } - b2 += i; - s2 += i; - mhi = BigInteger.valueOf(1); - /* (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed (when mode >= 2) or - input (when mode < 2) significant digit, divided by 10^k. */ - } - /* We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5). Reduce common factors in - b2, m2, and s2 without changing the equalities. */ - if (m2 > 0 && s2 > 0) { - i = (m2 < s2) ? m2 : s2; - b2 -= i; - m2 -= i; - s2 -= i; - } - - /* Fold b5 into b and m5 into mhi. */ - if (b5 > 0) { - if (leftright) { - if (m5 > 0) { - mhi = pow5mult(mhi, m5); - b1 = mhi.multiply(b); - b = b1; - } - if ((j = b5 - m5) != 0) - b = pow5mult(b, j); - } - else - b = pow5mult(b, b5); - } - /* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and - (mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input significant digit, divided by 10^k. */ - - S = BigInteger.valueOf(1); - if (s5 > 0) - S = pow5mult(S, s5); - /* Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and - (mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input significant digit, divided by 10^k. */ - - /* Check for special case that d is a normalized power of 2. */ - spec_case = false; - if (mode < 2) { - if ( (word1(d) == 0) && ((word0(d) & Bndry_mask) == 0) - && ((word0(d) & (Exp_mask & Exp_mask << 1)) != 0) - ) { - /* The special case. Here we want to be within a quarter of the last input - significant digit instead of one half of it when the decimal output string's value is less than d. */ - b2 += Log2P; - s2 += Log2P; - spec_case = true; - } - } - - /* Arrange for convenient computation of quotients: - * shift left if necessary so divisor has 4 leading 0 bits. - * - * Perhaps we should just compute leading 28 bits of S once - * and for all and pass them and a shift to quorem, so it - * can do shifts and ors to compute the numerator for q. - */ - byte [] S_bytes = S.toByteArray(); - int S_hiWord = 0; - for (int idx = 0; idx < 4; idx++) { - S_hiWord = (S_hiWord << 8); - if (idx < S_bytes.length) - S_hiWord |= (S_bytes[idx] & 0xFF); - } - if ((i = (((s5 != 0) ? 32 - hi0bits(S_hiWord) : 1) + s2) & 0x1f) != 0) - i = 32 - i; - /* i is the number of leading zero bits in the most significant word of S*2^s2. */ - if (i > 4) { - i -= 4; - b2 += i; - m2 += i; - s2 += i; - } - else if (i < 4) { - i += 28; - b2 += i; - m2 += i; - s2 += i; - } - /* Now S*2^s2 has exactly four leading zero bits in its most significant word. */ - if (b2 > 0) - b = b.shiftLeft(b2); - if (s2 > 0) - S = S.shiftLeft(s2); - /* Now we have d/10^k = b/S and - (mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */ - if (k_check) { - if (b.compareTo(S) < 0) { - k--; - b = b.multiply(BigInteger.valueOf(10)); /* we botched the k estimate */ - if (leftright) - mhi = mhi.multiply(BigInteger.valueOf(10)); - ilim = ilim1; - } - } - /* At this point 1 <= d/10^k = b/S < 10. */ - - if (ilim <= 0 && mode > 2) { - /* We're doing fixed-mode output and d is less than the minimum nonzero output in this mode. - Output either zero or the minimum nonzero output depending on which is closer to d. */ - if ((ilim < 0 ) - || ((i = b.compareTo(S = S.multiply(BigInteger.valueOf(5)))) < 0) - || ((i == 0 && !biasUp))) { - /* Always emit at least one digit. If the number appears to be zero - using the current mode, then emit one '0' digit and set decpt to 1. */ - /*no_digits: - k = -1 - ndigits; - goto ret; */ - buf.setLength(0); - buf.append('0'); /* copy "0" to buffer */ - return 1; -// goto no_digits; - } -// one_digit: - buf.append('1'); - k++; - return k + 1; - } - if (leftright) { - if (m2 > 0) - mhi = mhi.shiftLeft(m2); - - /* Compute mlo -- check for special case - * that d is a normalized power of 2. - */ - - mlo = mhi; - if (spec_case) { - mhi = mlo; - mhi = mhi.shiftLeft(Log2P); - } - /* mlo/S = maximum acceptable error, divided by 10^k, if the output is less than d. */ - /* mhi/S = maximum acceptable error, divided by 10^k, if the output is greater than d. */ - - for(i = 1;;i++) { - BigInteger[] divResult = b.divideAndRemainder(S); - b = divResult[1]; - dig = (char)(divResult[0].intValue() + '0'); - /* Do we yet have the shortest decimal string - * that will round to d? - */ - j = b.compareTo(mlo); - /* j is b/S compared with mlo/S. */ - delta = S.subtract(mhi); - j1 = (delta.signum() <= 0) ? 1 : b.compareTo(delta); - /* j1 is b/S compared with 1 - mhi/S. */ - if ((j1 == 0) && (mode == 0) && ((word1(d) & 1) == 0)) { - if (dig == '9') { - buf.append('9'); - if (roundOff(buf)) { - k++; - buf.append('1'); - } - return k + 1; -// goto round_9_up; - } - if (j > 0) - dig++; - buf.append(dig); - return k + 1; - } - if ((j < 0) - || ((j == 0) - && (mode == 0) - && ((word1(d) & 1) == 0) - )) { - if (j1 > 0) { - /* Either dig or dig+1 would work here as the least significant decimal digit. - Use whichever would produce a decimal value closer to d. */ - b = b.shiftLeft(1); - j1 = b.compareTo(S); - if (((j1 > 0) || (j1 == 0 && (((dig & 1) == 1) || biasUp))) - && (dig++ == '9')) { - buf.append('9'); - if (roundOff(buf)) { - k++; - buf.append('1'); - } - return k + 1; -// goto round_9_up; - } - } - buf.append(dig); - return k + 1; - } - if (j1 > 0) { - if (dig == '9') { /* possible if i == 1 */ -// round_9_up: -// *s++ = '9'; -// goto roundoff; - buf.append('9'); - if (roundOff(buf)) { - k++; - buf.append('1'); - } - return k + 1; - } - buf.append((char)(dig + 1)); - return k + 1; - } - buf.append(dig); - if (i == ilim) - break; - b = b.multiply(BigInteger.valueOf(10)); - if (mlo == mhi) - mlo = mhi = mhi.multiply(BigInteger.valueOf(10)); - else { - mlo = mlo.multiply(BigInteger.valueOf(10)); - mhi = mhi.multiply(BigInteger.valueOf(10)); - } - } - } - else - for(i = 1;; i++) { -// (char)(dig = quorem(b,S) + '0'); - BigInteger[] divResult = b.divideAndRemainder(S); - b = divResult[1]; - dig = (char)(divResult[0].intValue() + '0'); - buf.append(dig); - if (i >= ilim) - break; - b = b.multiply(BigInteger.valueOf(10)); - } - - /* Round off last digit */ - - b = b.shiftLeft(1); - j = b.compareTo(S); - if ((j > 0) || (j == 0 && (((dig & 1) == 1) || biasUp))) { -// roundoff: -// while(*--s == '9') -// if (s == buf) { -// k++; -// *s++ = '1'; -// goto ret; -// } -// ++*s++; - if (roundOff(buf)) { - k++; - buf.append('1'); - return k + 1; - } - } - else { - stripTrailingZeroes(buf); -// while(*--s == '0') ; -// s++; - } -// ret: -// Bfree(S); -// if (mhi) { -// if (mlo && mlo != mhi) -// Bfree(mlo); -// Bfree(mhi); -// } -// ret1: -// Bfree(b); -// JS_ASSERT(s < buf + bufsize); - return k + 1; - } - - private static void - stripTrailingZeroes(StringBuffer buf) - { -// while(*--s == '0') ; -// s++; - int bl = buf.length(); - while(bl-->0 && buf.charAt(bl) == '0') { - // empty - } - buf.setLength(bl + 1); - } - - /* Mapping of JSDToStrMode -> JS_dtoa mode */ - private static final int dtoaModes[] = { - 0, /* DTOSTR_STANDARD */ - 0, /* DTOSTR_STANDARD_EXPONENTIAL, */ - 3, /* DTOSTR_FIXED, */ - 2, /* DTOSTR_EXPONENTIAL, */ - 2}; /* DTOSTR_PRECISION */ - - static void - JS_dtostr(StringBuffer buffer, int mode, int precision, double d) - { - int decPt; /* Position of decimal point relative to first digit returned by JS_dtoa */ - boolean[] sign = new boolean[1]; /* true if the sign bit was set in d */ - int nDigits; /* Number of significand digits returned by JS_dtoa */ - -// JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL ? DTOSTR_STANDARD_BUFFER_SIZE : -// DTOSTR_VARIABLE_BUFFER_SIZE(precision))); - - if (mode == DTOSTR_FIXED && (d >= 1e21 || d <= -1e21)) - mode = DTOSTR_STANDARD; /* Change mode here rather than below because the buffer may not be large enough to hold a large integer. */ - - decPt = JS_dtoa(d, dtoaModes[mode], mode >= DTOSTR_FIXED, precision, sign, buffer); - nDigits = buffer.length(); - - /* If Infinity, -Infinity, or NaN, return the string regardless of the mode. */ - if (decPt != 9999) { - boolean exponentialNotation = false; - int minNDigits = 0; /* Minimum number of significand digits required by mode and precision */ - int p; - - switch (mode) { - case DTOSTR_STANDARD: - if (decPt < -5 || decPt > 21) - exponentialNotation = true; - else - minNDigits = decPt; - break; - - case DTOSTR_FIXED: - if (precision >= 0) - minNDigits = decPt + precision; - else - minNDigits = decPt; - break; - - case DTOSTR_EXPONENTIAL: -// JS_ASSERT(precision > 0); - minNDigits = precision; - /* Fall through */ - case DTOSTR_STANDARD_EXPONENTIAL: - exponentialNotation = true; - break; - - case DTOSTR_PRECISION: -// JS_ASSERT(precision > 0); - minNDigits = precision; - if (decPt < -5 || decPt > precision) - exponentialNotation = true; - break; - } - - /* If the number has fewer than minNDigits, pad it with zeros at the end */ - if (nDigits < minNDigits) { - p = minNDigits; - nDigits = minNDigits; - do { - buffer.append('0'); - } while (buffer.length() != p); - } - - if (exponentialNotation) { - /* Insert a decimal point if more than one significand digit */ - if (nDigits != 1) { - buffer.insert(1, '.'); - } - buffer.append('e'); - if ((decPt - 1) >= 0) - buffer.append('+'); - buffer.append(decPt - 1); -// JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d", decPt-1); - } else if (decPt != nDigits) { - /* Some kind of a fraction in fixed notation */ -// JS_ASSERT(decPt <= nDigits); - if (decPt > 0) { - /* dd...dd . dd...dd */ - buffer.insert(decPt, '.'); - } else { - /* 0 . 00...00dd...dd */ - for (int i = 0; i < 1 - decPt; i++) - buffer.insert(0, '0'); - buffer.insert(1, '.'); - } - } - } - - /* If negative and neither -0.0 nor NaN, output a leading '-'. */ - if (sign[0] && - !(word0(d) == Sign_bit && word1(d) == 0) && - !((word0(d) & Exp_mask) == Exp_mask && - ((word1(d) != 0) || ((word0(d) & Frac_mask) != 0)))) { - buffer.insert(0, '-'); - } - } - -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Decompiler.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Decompiler.java deleted file mode 100644 index 8547d37..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Decompiler.java +++ /dev/null @@ -1,918 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Mike Ang - * Igor Bukanov - * Bob Jervis - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * The following class save decompilation information about the source. - * Source information is returned from the parser as a String - * associated with function nodes and with the toplevel script. When - * saved in the constant pool of a class, this string will be UTF-8 - * encoded, and token values will occupy a single byte. - - * Source is saved (mostly) as token numbers. The tokens saved pretty - * much correspond to the token stream of a 'canonical' representation - * of the input program, as directed by the parser. (There were a few - * cases where tokens could have been left out where decompiler could - * easily reconstruct them, but I left them in for clarity). (I also - * looked adding source collection to TokenStream instead, where I - * could have limited the changes to a few lines in getToken... but - * this wouldn't have saved any space in the resulting source - * representation, and would have meant that I'd have to duplicate - * parser logic in the decompiler to disambiguate situations where - * newlines are important.) The function decompile expands the - * tokens back into their string representations, using simple - * lookahead to correct spacing and indentation. - * - * Assignments are saved as two-token pairs (Token.ASSIGN, op). Number tokens - * are stored inline, as a NUMBER token, a character representing the type, and - * either 1 or 4 characters representing the bit-encoding of the number. String - * types NAME, STRING and OBJECT are currently stored as a token type, - * followed by a character giving the length of the string (assumed to - * be less than 2^16), followed by the characters of the string - * inlined into the source string. Changing this to some reference to - * to the string in the compiled class' constant pool would probably - * save a lot of space... but would require some method of deriving - * the final constant pool entry from information available at parse - * time. - */ -public class Decompiler -{ - /** - * Flag to indicate that the decompilation should omit the - * function header and trailing brace. - */ - public static final int ONLY_BODY_FLAG = 1 << 0; - - /** - * Flag to indicate that the decompilation generates toSource result. - */ - public static final int TO_SOURCE_FLAG = 1 << 1; - - /** - * Decompilation property to specify initial ident value. - */ - public static final int INITIAL_INDENT_PROP = 1; - - /** - * Decompilation property to specify default identation offset. - */ - public static final int INDENT_GAP_PROP = 2; - - /** - * Decompilation property to specify identation offset for case labels. - */ - public static final int CASE_GAP_PROP = 3; - - // Marker to denote the last RC of function so it can be distinguished from - // the last RC of object literals in case of function expressions - private static final int FUNCTION_END = Token.LAST_TOKEN + 1; - - String getEncodedSource() - { - return sourceToString(0); - } - - int getCurrentOffset() - { - return sourceTop; - } - - int markFunctionStart(int functionType) - { - int savedOffset = getCurrentOffset(); - addToken(Token.FUNCTION); - append((char)functionType); - return savedOffset; - } - - int markFunctionEnd(int functionStart) - { - int offset = getCurrentOffset(); - append((char)FUNCTION_END); - return offset; - } - - void addToken(int token) - { - if (!(0 <= token && token <= Token.LAST_TOKEN)) - throw new IllegalArgumentException(); - - append((char)token); - } - - void addEOL(int token) - { - if (!(0 <= token && token <= Token.LAST_TOKEN)) - throw new IllegalArgumentException(); - - append((char)token); - append((char)Token.EOL); - } - - void addName(String str) - { - addToken(Token.NAME); - appendString(str); - } - - void addString(String str) - { - addToken(Token.STRING); - appendString(str); - } - - void addRegexp(String regexp, String flags) - { - addToken(Token.REGEXP); - appendString('/' + regexp + '/' + flags); - } - - void addNumber(double n) - { - addToken(Token.NUMBER); - - /* encode the number in the source stream. - * Save as NUMBER type (char | char char char char) - * where type is - * 'D' - double, 'S' - short, 'J' - long. - - * We need to retain float vs. integer type info to keep the - * behavior of liveconnect type-guessing the same after - * decompilation. (Liveconnect tries to present 1.0 to Java - * as a float/double) - * OPT: This is no longer true. We could compress the format. - - * This may not be the most space-efficient encoding; - * the chars created below may take up to 3 bytes in - * constant pool UTF-8 encoding, so a Double could take - * up to 12 bytes. - */ - - long lbits = (long)n; - if (lbits != n) { - // if it's floating point, save as a Double bit pattern. - // (12/15/97 our scanner only returns Double for f.p.) - lbits = Double.doubleToLongBits(n); - append('D'); - append((char)(lbits >> 48)); - append((char)(lbits >> 32)); - append((char)(lbits >> 16)); - append((char)lbits); - } - else { - // we can ignore negative values, bc they're already prefixed - // by NEG - if (lbits < 0) Kit.codeBug(); - - // will it fit in a char? - // this gives a short encoding for integer values up to 2^16. - if (lbits <= Character.MAX_VALUE) { - append('S'); - append((char)lbits); - } - else { // Integral, but won't fit in a char. Store as a long. - append('J'); - append((char)(lbits >> 48)); - append((char)(lbits >> 32)); - append((char)(lbits >> 16)); - append((char)lbits); - } - } - } - - private void appendString(String str) - { - int L = str.length(); - int lengthEncodingSize = 1; - if (L >= 0x8000) { - lengthEncodingSize = 2; - } - int nextTop = sourceTop + lengthEncodingSize + L; - if (nextTop > sourceBuffer.length) { - increaseSourceCapacity(nextTop); - } - if (L >= 0x8000) { - // Use 2 chars to encode strings exceeding 32K, were the highest - // bit in the first char indicates presence of the next byte - sourceBuffer[sourceTop] = (char)(0x8000 | (L >>> 16)); - ++sourceTop; - } - sourceBuffer[sourceTop] = (char)L; - ++sourceTop; - str.getChars(0, L, sourceBuffer, sourceTop); - sourceTop = nextTop; - } - - private void append(char c) - { - if (sourceTop == sourceBuffer.length) { - increaseSourceCapacity(sourceTop + 1); - } - sourceBuffer[sourceTop] = c; - ++sourceTop; - } - - private void increaseSourceCapacity(int minimalCapacity) - { - // Call this only when capacity increase is must - if (minimalCapacity <= sourceBuffer.length) Kit.codeBug(); - int newCapacity = sourceBuffer.length * 2; - if (newCapacity < minimalCapacity) { - newCapacity = minimalCapacity; - } - char[] tmp = new char[newCapacity]; - System.arraycopy(sourceBuffer, 0, tmp, 0, sourceTop); - sourceBuffer = tmp; - } - - private String sourceToString(int offset) - { - if (offset < 0 || sourceTop < offset) Kit.codeBug(); - return new String(sourceBuffer, offset, sourceTop - offset); - } - - /** - * Decompile the source information associated with this js - * function/script back into a string. For the most part, this - * just means translating tokens back to their string - * representations; there's a little bit of lookahead logic to - * decide the proper spacing/indentation. Most of the work in - * mapping the original source to the prettyprinted decompiled - * version is done by the parser. - * - * @param source encoded source tree presentation - * - * @param flags flags to select output format - * - * @param properties indentation properties - * - */ - public static String decompile(String source, int flags, - UintMap properties) - { - int length = source.length(); - if (length == 0) { return ""; } - - int indent = properties.getInt(INITIAL_INDENT_PROP, 0); - if (indent < 0) throw new IllegalArgumentException(); - int indentGap = properties.getInt(INDENT_GAP_PROP, 4); - if (indentGap < 0) throw new IllegalArgumentException(); - int caseGap = properties.getInt(CASE_GAP_PROP, 2); - if (caseGap < 0) throw new IllegalArgumentException(); - - StringBuffer result = new StringBuffer(); - boolean justFunctionBody = (0 != (flags & Decompiler.ONLY_BODY_FLAG)); - boolean toSource = (0 != (flags & Decompiler.TO_SOURCE_FLAG)); - - // Spew tokens in source, for debugging. - // as TYPE number char - if (printSource) { - System.err.println("length:" + length); - for (int i = 0; i < length; ++i) { - // Note that tokenToName will fail unless Context.printTrees - // is true. - String tokenname = null; - if (Token.printNames) { - tokenname = Token.name(source.charAt(i)); - } - if (tokenname == null) { - tokenname = "---"; - } - String pad = tokenname.length() > 7 - ? "\t" - : "\t\t"; - System.err.println - (tokenname - + pad + (int)source.charAt(i) - + "\t'" + ScriptRuntime.escapeString - (source.substring(i, i+1)) - + "'"); - } - System.err.println(); - } - - int braceNesting = 0; - boolean afterFirstEOL = false; - int i = 0; - int topFunctionType; - if (source.charAt(i) == Token.SCRIPT) { - ++i; - topFunctionType = -1; - } else { - topFunctionType = source.charAt(i + 1); - } - - if (!toSource) { - // add an initial newline to exactly match js. - result.append('\n'); - for (int j = 0; j < indent; j++) - result.append(' '); - } else { - if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) { - result.append('('); - } - } - - while (i < length) { - switch(source.charAt(i)) { - case Token.GET: - case Token.SET: - result.append(source.charAt(i) == Token.GET ? "get " : "set "); - ++i; - i = printSourceString(source, i + 1, false, result); - // Now increment one more to get past the FUNCTION token - ++i; - break; - - case Token.NAME: - case Token.REGEXP: // re-wrapped in '/'s in parser... - i = printSourceString(source, i + 1, false, result); - continue; - - case Token.STRING: - i = printSourceString(source, i + 1, true, result); - continue; - - case Token.NUMBER: - i = printSourceNumber(source, i + 1, result); - continue; - - case Token.TRUE: - result.append("true"); - break; - - case Token.FALSE: - result.append("false"); - break; - - case Token.NULL: - result.append("null"); - break; - - case Token.THIS: - result.append("this"); - break; - - case Token.FUNCTION: - ++i; // skip function type - result.append("function "); - break; - - case FUNCTION_END: - // Do nothing - break; - - case Token.COMMA: - result.append(", "); - break; - - case Token.LC: - ++braceNesting; - if (Token.EOL == getNext(source, length, i)) - indent += indentGap; - result.append('{'); - break; - - case Token.RC: { - --braceNesting; - /* don't print the closing RC if it closes the - * toplevel function and we're called from - * decompileFunctionBody. - */ - if (justFunctionBody && braceNesting == 0) - break; - - result.append('}'); - switch (getNext(source, length, i)) { - case Token.EOL: - case FUNCTION_END: - indent -= indentGap; - break; - case Token.WHILE: - case Token.ELSE: - indent -= indentGap; - result.append(' '); - break; - } - break; - } - case Token.LP: - result.append('('); - break; - - case Token.RP: - result.append(')'); - if (Token.LC == getNext(source, length, i)) - result.append(' '); - break; - - case Token.LB: - result.append('['); - break; - - case Token.RB: - result.append(']'); - break; - - case Token.EOL: { - if (toSource) break; - boolean newLine = true; - if (!afterFirstEOL) { - afterFirstEOL = true; - if (justFunctionBody) { - /* throw away just added 'function name(...) {' - * and restore the original indent - */ - result.setLength(0); - indent -= indentGap; - newLine = false; - } - } - if (newLine) { - result.append('\n'); - } - - /* add indent if any tokens remain, - * less setback if next token is - * a label, case or default. - */ - if (i + 1 < length) { - int less = 0; - int nextToken = source.charAt(i + 1); - if (nextToken == Token.CASE - || nextToken == Token.DEFAULT) - { - less = indentGap - caseGap; - } else if (nextToken == Token.RC) { - less = indentGap; - } - - /* elaborate check against label... skip past a - * following inlined NAME and look for a COLON. - */ - else if (nextToken == Token.NAME) { - int afterName = getSourceStringEnd(source, i + 2); - if (source.charAt(afterName) == Token.COLON) - less = indentGap; - } - - for (; less < indent; less++) - result.append(' '); - } - break; - } - case Token.DOT: - result.append('.'); - break; - - case Token.NEW: - result.append("new "); - break; - - case Token.DELPROP: - result.append("delete "); - break; - - case Token.IF: - result.append("if "); - break; - - case Token.ELSE: - result.append("else "); - break; - - case Token.FOR: - result.append("for "); - break; - - case Token.IN: - result.append(" in "); - break; - - case Token.WITH: - result.append("with "); - break; - - case Token.WHILE: - result.append("while "); - break; - - case Token.DO: - result.append("do "); - break; - - case Token.TRY: - result.append("try "); - break; - - case Token.CATCH: - result.append("catch "); - break; - - case Token.FINALLY: - result.append("finally "); - break; - - case Token.THROW: - result.append("throw "); - break; - - case Token.SWITCH: - result.append("switch "); - break; - - case Token.BREAK: - result.append("break"); - if (Token.NAME == getNext(source, length, i)) - result.append(' '); - break; - - case Token.CONTINUE: - result.append("continue"); - if (Token.NAME == getNext(source, length, i)) - result.append(' '); - break; - - case Token.CASE: - result.append("case "); - break; - - case Token.DEFAULT: - result.append("default"); - break; - - case Token.RETURN: - result.append("return"); - if (Token.SEMI != getNext(source, length, i)) - result.append(' '); - break; - - case Token.VAR: - result.append("var "); - break; - - case Token.LET: - result.append("let "); - break; - - case Token.SEMI: - result.append(';'); - if (Token.EOL != getNext(source, length, i)) { - // separators in FOR - result.append(' '); - } - break; - - case Token.ASSIGN: - result.append(" = "); - break; - - case Token.ASSIGN_ADD: - result.append(" += "); - break; - - case Token.ASSIGN_SUB: - result.append(" -= "); - break; - - case Token.ASSIGN_MUL: - result.append(" *= "); - break; - - case Token.ASSIGN_DIV: - result.append(" /= "); - break; - - case Token.ASSIGN_MOD: - result.append(" %= "); - break; - - case Token.ASSIGN_BITOR: - result.append(" |= "); - break; - - case Token.ASSIGN_BITXOR: - result.append(" ^= "); - break; - - case Token.ASSIGN_BITAND: - result.append(" &= "); - break; - - case Token.ASSIGN_LSH: - result.append(" <<= "); - break; - - case Token.ASSIGN_RSH: - result.append(" >>= "); - break; - - case Token.ASSIGN_URSH: - result.append(" >>>= "); - break; - - case Token.HOOK: - result.append(" ? "); - break; - - case Token.OBJECTLIT: - // pun OBJECTLIT to mean colon in objlit property - // initialization. - // This needs to be distinct from COLON in the general case - // to distinguish from the colon in a ternary... which needs - // different spacing. - result.append(':'); - break; - - case Token.COLON: - if (Token.EOL == getNext(source, length, i)) - // it's the end of a label - result.append(':'); - else - // it's the middle part of a ternary - result.append(" : "); - break; - - case Token.OR: - result.append(" || "); - break; - - case Token.AND: - result.append(" && "); - break; - - case Token.BITOR: - result.append(" | "); - break; - - case Token.BITXOR: - result.append(" ^ "); - break; - - case Token.BITAND: - result.append(" & "); - break; - - case Token.SHEQ: - result.append(" === "); - break; - - case Token.SHNE: - result.append(" !== "); - break; - - case Token.EQ: - result.append(" == "); - break; - - case Token.NE: - result.append(" != "); - break; - - case Token.LE: - result.append(" <= "); - break; - - case Token.LT: - result.append(" < "); - break; - - case Token.GE: - result.append(" >= "); - break; - - case Token.GT: - result.append(" > "); - break; - - case Token.INSTANCEOF: - result.append(" instanceof "); - break; - - case Token.LSH: - result.append(" << "); - break; - - case Token.RSH: - result.append(" >> "); - break; - - case Token.URSH: - result.append(" >>> "); - break; - - case Token.TYPEOF: - result.append("typeof "); - break; - - case Token.VOID: - result.append("void "); - break; - - case Token.CONST: - result.append("const "); - break; - - case Token.YIELD: - result.append("yield "); - break; - - case Token.NOT: - result.append('!'); - break; - - case Token.BITNOT: - result.append('~'); - break; - - case Token.POS: - result.append('+'); - break; - - case Token.NEG: - result.append('-'); - break; - - case Token.INC: - result.append("++"); - break; - - case Token.DEC: - result.append("--"); - break; - - case Token.ADD: - result.append(" + "); - break; - - case Token.SUB: - result.append(" - "); - break; - - case Token.MUL: - result.append(" * "); - break; - - case Token.DIV: - result.append(" / "); - break; - - case Token.MOD: - result.append(" % "); - break; - - case Token.COLONCOLON: - result.append("::"); - break; - - case Token.DOTDOT: - result.append(".."); - break; - - case Token.DOTQUERY: - result.append(".("); - break; - - case Token.XMLATTR: - result.append('@'); - break; - - default: - // If we don't know how to decompile it, raise an exception. - throw new RuntimeException("Token: " + - Token.name(source.charAt(i))); - } - ++i; - } - - if (!toSource) { - // add that trailing newline if it's an outermost function. - if (!justFunctionBody) - result.append('\n'); - } else { - if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) { - result.append(')'); - } - } - - return result.toString(); - } - - private static int getNext(String source, int length, int i) - { - return (i + 1 < length) ? source.charAt(i + 1) : Token.EOF; - } - - private static int getSourceStringEnd(String source, int offset) - { - return printSourceString(source, offset, false, null); - } - - private static int printSourceString(String source, int offset, - boolean asQuotedString, - StringBuffer sb) - { - int length = source.charAt(offset); - ++offset; - if ((0x8000 & length) != 0) { - length = ((0x7FFF & length) << 16) | source.charAt(offset); - ++offset; - } - if (sb != null) { - String str = source.substring(offset, offset + length); - if (!asQuotedString) { - sb.append(str); - } else { - sb.append('"'); - sb.append(ScriptRuntime.escapeString(str)); - sb.append('"'); - } - } - return offset + length; - } - - private static int printSourceNumber(String source, int offset, - StringBuffer sb) - { - double number = 0.0; - char type = source.charAt(offset); - ++offset; - if (type == 'S') { - if (sb != null) { - int ival = source.charAt(offset); - number = ival; - } - ++offset; - } else if (type == 'J' || type == 'D') { - if (sb != null) { - long lbits; - lbits = (long)source.charAt(offset) << 48; - lbits |= (long)source.charAt(offset + 1) << 32; - lbits |= (long)source.charAt(offset + 2) << 16; - lbits |= source.charAt(offset + 3); - if (type == 'J') { - number = lbits; - } else { - number = Double.longBitsToDouble(lbits); - } - } - offset += 4; - } else { - // Bad source - throw new RuntimeException(); - } - if (sb != null) { - sb.append(ScriptRuntime.numberToString(number, 10)); - } - return offset; - } - - private char[] sourceBuffer = new char[128]; - -// Per script/function source buffer top: parent source does not include a -// nested functions source and uses function index as a reference instead. - private int sourceTop; - -// whether to do a debug print of the source information, when decompiling. - private static final boolean printSource = false; - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/DefaultErrorReporter.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/DefaultErrorReporter.java deleted file mode 100644 index c7d93d4..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/DefaultErrorReporter.java +++ /dev/null @@ -1,113 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This is the default error reporter for JavaScript. - * - * @author Norris Boyd - */ -class DefaultErrorReporter implements ErrorReporter -{ - static final DefaultErrorReporter instance = new DefaultErrorReporter(); - - private boolean forEval; - private ErrorReporter chainedReporter; - - private DefaultErrorReporter() { } - - static ErrorReporter forEval(ErrorReporter reporter) - { - DefaultErrorReporter r = new DefaultErrorReporter(); - r.forEval = true; - r.chainedReporter = reporter; - return r; - } - - public void warning(String message, String sourceURI, int line, - String lineText, int lineOffset) - { - if (chainedReporter != null) { - chainedReporter.warning( - message, sourceURI, line, lineText, lineOffset); - } else { - // Do nothing - } - } - - public void error(String message, String sourceURI, int line, - String lineText, int lineOffset) - { - if (forEval) { - // Assume error message strings that start with "TypeError: " - // should become TypeError exceptions. A bit of a hack, but we - // don't want to change the ErrorReporter interface. - String error = "SyntaxError"; - final String TYPE_ERROR_NAME = "TypeError"; - final String DELIMETER = ": "; - final String prefix = TYPE_ERROR_NAME + DELIMETER; - if (message.startsWith(prefix)) { - error = TYPE_ERROR_NAME; - message = message.substring(prefix.length()); - } - throw ScriptRuntime.constructError(error, message, sourceURI, - line, lineText, lineOffset); - } - if (chainedReporter != null) { - chainedReporter.error( - message, sourceURI, line, lineText, lineOffset); - } else { - throw runtimeError( - message, sourceURI, line, lineText, lineOffset); - } - } - - public EvaluatorException runtimeError(String message, String sourceURI, - int line, String lineText, - int lineOffset) - { - if (chainedReporter != null) { - return chainedReporter.runtimeError( - message, sourceURI, line, lineText, lineOffset); - } else { - return new EvaluatorException( - message, sourceURI, line, lineText, lineOffset); - } - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/DefiningClassLoader.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/DefiningClassLoader.java deleted file mode 100644 index 5864b5d..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/DefiningClassLoader.java +++ /dev/null @@ -1,88 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Roger Lawrence - * Patrick Beard - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * Load generated classes. - * - * @author Norris Boyd - */ -public class DefiningClassLoader extends ClassLoader - implements GeneratedClassLoader -{ - public DefiningClassLoader() { - this.parentLoader = getClass().getClassLoader(); - } - - public DefiningClassLoader(ClassLoader parentLoader) { - this.parentLoader = parentLoader; - } - - public Class defineClass(String name, byte[] data) { - // Use our own protection domain for the generated classes. - // TODO: we might want to use a separate protection domain for classes - // compiled from scripts, based on where the script was loaded from. - return super.defineClass(name, data, 0, data.length, - SecurityUtilities.getProtectionDomain(getClass())); - } - - public void linkClass(Class cl) { - resolveClass(cl); - } - - public Class loadClass(String name, boolean resolve) - throws ClassNotFoundException - { - Class cl = findLoadedClass(name); - if (cl == null) { - if (parentLoader != null) { - cl = parentLoader.loadClass(name); - } else { - cl = findSystemClass(name); - } - } - if (resolve) { - resolveClass(cl); - } - return cl; - } - - private final ClassLoader parentLoader; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Delegator.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Delegator.java deleted file mode 100644 index e044863..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Delegator.java +++ /dev/null @@ -1,266 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Delegator.java, released - * Sep 27, 2000. - * - * The Initial Developer of the Original Code is - * Matthias Radestock. <matthias@sorted.org>. - * Portions created by the Initial Developer are Copyright (C) 2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * This is a helper class for implementing wrappers around Scriptable - * objects. It implements the Function interface and delegates all - * invocations to a delegee Scriptable object. The normal use of this - * class involves creating a sub-class and overriding one or more of - * the methods. - * - * A useful application is the implementation of interceptors, - * pre/post conditions, debugging. - * - * @see Function - * @see Scriptable - * @author Matthias Radestock - */ - -public class Delegator implements Function { - - protected Scriptable obj = null; - - /** - * Create a Delegator prototype. - * - * This constructor should only be used for creating prototype - * objects of Delegator. - * - * @see org.mozilla.javascript.Delegator#construct - */ - public Delegator() { - } - - /** - * Create a new Delegator that forwards requests to a delegee - * Scriptable object. - * - * @param obj the delegee - * @see org.mozilla.javascript.Scriptable - */ - public Delegator(Scriptable obj) { - this.obj = obj; - } - - /** - * Crete new Delegator instance. - * The default implementation calls this.getClass().newInstance(). - * - * @see #construct(Context cx, Scriptable scope, Object[] args) - */ - protected Delegator newInstance() - { - try { - return this.getClass().newInstance(); - } catch (Exception ex) { - throw Context.throwAsScriptRuntimeEx(ex); - } - } - - /** - * Retrieve the delegee. - * - * @return the delegee - */ - public Scriptable getDelegee() { - return obj; - } - /** - * Set the delegee. - * - * @param obj the delegee - * @see org.mozilla.javascript.Scriptable - */ - public void setDelegee(Scriptable obj) { - this.obj = obj; - } - /** - * @see org.mozilla.javascript.Scriptable#getClassName - */ - public String getClassName() { - return obj.getClassName(); - } - /** - * @see org.mozilla.javascript.Scriptable#get(String, Scriptable) - */ - public Object get(String name, Scriptable start) { - return obj.get(name,start); - } - /** - * @see org.mozilla.javascript.Scriptable#get(int, Scriptable) - */ - public Object get(int index, Scriptable start) { - return obj.get(index,start); - } - /** - * @see org.mozilla.javascript.Scriptable#has(String, Scriptable) - */ - public boolean has(String name, Scriptable start) { - return obj.has(name,start); - } - /** - * @see org.mozilla.javascript.Scriptable#has(int, Scriptable) - */ - public boolean has(int index, Scriptable start) { - return obj.has(index,start); - } - /** - * @see org.mozilla.javascript.Scriptable#put(String, Scriptable, Object) - */ - public void put(String name, Scriptable start, Object value) { - obj.put(name,start,value); - } - /** - * @see org.mozilla.javascript.Scriptable#put(int, Scriptable, Object) - */ - public void put(int index, Scriptable start, Object value) { - obj.put(index,start,value); - } - /** - * @see org.mozilla.javascript.Scriptable#delete(String) - */ - public void delete(String name) { - obj.delete(name); - } - /** - * @see org.mozilla.javascript.Scriptable#delete(int) - */ - public void delete(int index) { - obj.delete(index); - } - /** - * @see org.mozilla.javascript.Scriptable#getPrototype - */ - public Scriptable getPrototype() { - return obj.getPrototype(); - } - /** - * @see org.mozilla.javascript.Scriptable#setPrototype - */ - public void setPrototype(Scriptable prototype) { - obj.setPrototype(prototype); - } - /** - * @see org.mozilla.javascript.Scriptable#getParentScope - */ - public Scriptable getParentScope() { - return obj.getParentScope(); - } - /** - * @see org.mozilla.javascript.Scriptable#setParentScope - */ - public void setParentScope(Scriptable parent) { - obj.setParentScope(parent); - } - /** - * @see org.mozilla.javascript.Scriptable#getIds - */ - public Object[] getIds() { - return obj.getIds(); - } - /** - * Note that this method does not get forwarded to the delegee if - * the <code>hint</code> parameter is null, - * <code>ScriptRuntime.ScriptableClass</code> or - * <code>ScriptRuntime.FunctionClass</code>. Instead the object - * itself is returned. - * - * @param hint the type hint - * @return the default value - * - * @see org.mozilla.javascript.Scriptable#getDefaultValue - */ - public Object getDefaultValue(Class hint) { - return (hint == null || - hint == ScriptRuntime.ScriptableClass || - hint == ScriptRuntime.FunctionClass) ? - this : obj.getDefaultValue(hint); - } - /** - * @see org.mozilla.javascript.Scriptable#hasInstance - */ - public boolean hasInstance(Scriptable instance) { - return obj.hasInstance(instance); - } - /** - * @see org.mozilla.javascript.Function#call - */ - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - return ((Function)obj).call(cx,scope,thisObj,args); - } - - /** - * Note that if the <code>delegee</code> is <code>null</code>, - * this method creates a new instance of the Delegator itself - * rathert than forwarding the call to the - * <code>delegee</code>. This permits the use of Delegator - * prototypes. - * - * @param cx the current Context for this thread - * @param scope an enclosing scope of the caller except - * when the function is called from a closure. - * @param args the array of arguments - * @return the allocated object - * - * @see Function#construct(Context, Scriptable, Object[]) - */ - public Scriptable construct(Context cx, Scriptable scope, Object[] args) - { - if (obj == null) { - //this little trick allows us to declare prototype objects for - //Delegators - Delegator n = newInstance(); - Scriptable delegee; - if (args.length == 0) { - delegee = new NativeObject(); - } else { - delegee = ScriptRuntime.toObject(cx, scope, args[0]); - } - n.setDelegee(delegee); - return n; - } - else { - return ((Function)obj).construct(cx,scope,args); - } - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/EcmaError.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/EcmaError.java deleted file mode 100644 index 1fd8f03..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/EcmaError.java +++ /dev/null @@ -1,160 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * The class of exceptions raised by the engine as described in - * ECMA edition 3. See section 15.11.6 in particular. - */ -public class EcmaError extends RhinoException -{ - static final long serialVersionUID = -6261226256957286699L; - - private String errorName; - private String errorMessage; - - /** - * Create an exception with the specified detail message. - * - * Errors internal to the JavaScript engine will simply throw a - * RuntimeException. - * - * @param sourceName the name of the source reponsible for the error - * @param lineNumber the line number of the source - * @param columnNumber the columnNumber of the source (may be zero if - * unknown) - * @param lineSource the source of the line containing the error (may be - * null if unknown) - */ - EcmaError(String errorName, String errorMessage, - String sourceName, int lineNumber, - String lineSource, int columnNumber) - { - recordErrorOrigin(sourceName, lineNumber, lineSource, columnNumber); - this.errorName = errorName; - this.errorMessage = errorMessage; - } - - /** - * @deprecated EcmaError error instances should not be constructed - * explicitly since they are generated by the engine. - */ - public EcmaError(Scriptable nativeError, String sourceName, - int lineNumber, int columnNumber, String lineSource) - { - this("InternalError", ScriptRuntime.toString(nativeError), - sourceName, lineNumber, lineSource, columnNumber); - } - - public String details() - { - return errorName+": "+errorMessage; - } - - /** - * Gets the name of the error. - * - * ECMA edition 3 defines the following - * errors: EvalError, RangeError, ReferenceError, - * SyntaxError, TypeError, and URIError. Additional error names - * may be added in the future. - * - * See ECMA edition 3, 15.11.7.9. - * - * @return the name of the error. - */ - public String getName() - { - return errorName; - } - - /** - * Gets the message corresponding to the error. - * - * See ECMA edition 3, 15.11.7.10. - * - * @return an implemenation-defined string describing the error. - */ - public String getErrorMessage() - { - return errorMessage; - } - - /** - * @deprecated Use {@link RhinoException#sourceName()} from the super class. - */ - public String getSourceName() - { - return sourceName(); - } - - /** - * @deprecated Use {@link RhinoException#lineNumber()} from the super class. - */ - public int getLineNumber() - { - return lineNumber(); - } - - /** - * @deprecated - * Use {@link RhinoException#columnNumber()} from the super class. - */ - public int getColumnNumber() { - return columnNumber(); - } - - /** - * @deprecated Use {@link RhinoException#lineSource()} from the super class. - */ - public String getLineSource() { - return lineSource(); - } - - /** - * @deprecated - * Always returns <b>null</b>. - */ - public Scriptable getErrorObject() - { - return null; - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ErrorReporter.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ErrorReporter.java deleted file mode 100644 index 4649370..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ErrorReporter.java +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * This is interface defines a protocol for the reporting of - * errors during JavaScript translation or execution. - * - * @author Norris Boyd - */ - -public interface ErrorReporter { - - /** - * Report a warning. - * - * The implementing class may choose to ignore the warning - * if it desires. - * - * @param message a String describing the warning - * @param sourceName a String describing the JavaScript source - * where the warning occured; typically a filename or URL - * @param line the line number associated with the warning - * @param lineSource the text of the line (may be null) - * @param lineOffset the offset into lineSource where problem was detected - */ - void warning(String message, String sourceName, int line, - String lineSource, int lineOffset); - - /** - * Report an error. - * - * The implementing class is free to throw an exception if - * it desires. - * - * If execution has not yet begun, the JavaScript engine is - * free to find additional errors rather than terminating - * the translation. It will not execute a script that had - * errors, however. - * - * @param message a String describing the error - * @param sourceName a String describing the JavaScript source - * where the error occured; typically a filename or URL - * @param line the line number associated with the error - * @param lineSource the text of the line (may be null) - * @param lineOffset the offset into lineSource where problem was detected - */ - void error(String message, String sourceName, int line, - String lineSource, int lineOffset); - - /** - * Creates an EvaluatorException that may be thrown. - * - * runtimeErrors, unlike errors, will always terminate the - * current script. - * - * @param message a String describing the error - * @param sourceName a String describing the JavaScript source - * where the error occured; typically a filename or URL - * @param line the line number associated with the error - * @param lineSource the text of the line (may be null) - * @param lineOffset the offset into lineSource where problem was detected - * @return an EvaluatorException that will be thrown. - */ - EvaluatorException runtimeError(String message, String sourceName, - int line, String lineSource, - int lineOffset); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Evaluator.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Evaluator.java deleted file mode 100644 index e222af3..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Evaluator.java +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.util.List; - -/** - * Abstraction of evaluation, which can be implemented either by an - * interpreter or compiler. - */ -public interface Evaluator { - - /** - * Compile the script or function from intermediate representation - * tree into an executable form. - * - * @param compilerEnv Compiler environment - * @param tree intermediate representation - * @param encodedSource encoding of the source code for decompilation - * @param returnFunction if true, compiling a function - * @return an opaque object that can be passed to either - * createFunctionObject or createScriptObject, depending on the - * value of returnFunction - */ - public Object compile(CompilerEnvirons compilerEnv, - ScriptOrFnNode tree, - String encodedSource, - boolean returnFunction); - - /** - * Create a function object. - * - * @param cx Current context - * @param scope scope of the function - * @param bytecode opaque object returned by compile - * @param staticSecurityDomain security domain - * @return Function object that can be called - */ - public Function createFunctionObject(Context cx, Scriptable scope, - Object bytecode, Object staticSecurityDomain); - - /** - * Create a script object. - * - * @param bytecode opaque object returned by compile - * @param staticSecurityDomain security domain - * @return Script object that can be evaluated - */ - public Script createScriptObject(Object bytecode, - Object staticSecurityDomain); - - /** - * Capture stack information from the given exception. - * @param ex an exception thrown during execution - */ - public void captureStackInfo(RhinoException ex); - - /** - * Get the source position information by examining the stack. - * @param cx Context - * @param linep Array object of length >= 1; getSourcePositionFromStack - * will assign the line number to linep[0]. - * @return the name of the file or other source container - */ - public String getSourcePositionFromStack(Context cx, int[] linep); - - /** - * Given a native stack trace, patch it with script-specific source - * and line information - * @param ex exception - * @param nativeStackTrace the native stack trace - * @return patched stack trace - */ - public String getPatchedStack(RhinoException ex, - String nativeStackTrace); - - /** - * Get the script stack for the given exception - * @param ex exception from execution - * @return list of strings for the stack trace - */ - public List getScriptStack(RhinoException ex); - - /** - * Mark the given script to indicate it was created by a call to - * eval() or to a Function constructor. - * @param script script to mark as from eval - */ - public void setEvalScriptFlag(Script script); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/EvaluatorException.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/EvaluatorException.java deleted file mode 100644 index 7b4e7cc..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/EvaluatorException.java +++ /dev/null @@ -1,123 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - - -package org.mozilla.javascript; - -/** - * The class of exceptions thrown by the JavaScript engine. - */ -public class EvaluatorException extends RhinoException -{ - static final long serialVersionUID = -8743165779676009808L; - - public EvaluatorException(String detail) - { - super(detail); - } - - /** - * Create an exception with the specified detail message. - * - * Errors internal to the JavaScript engine will simply throw a - * RuntimeException. - * - * @param detail the error message - * @param sourceName the name of the source reponsible for the error - * @param lineNumber the line number of the source - */ - public EvaluatorException(String detail, String sourceName, - int lineNumber) - { - this(detail, sourceName, lineNumber, null, 0); - } - - /** - * Create an exception with the specified detail message. - * - * Errors internal to the JavaScript engine will simply throw a - * RuntimeException. - * - * @param detail the error message - * @param sourceName the name of the source responsible for the error - * @param lineNumber the line number of the source - * @param columnNumber the columnNumber of the source (may be zero if - * unknown) - * @param lineSource the source of the line containing the error (may be - * null if unknown) - */ - public EvaluatorException(String detail, String sourceName, int lineNumber, - String lineSource, int columnNumber) - { - super(detail); - recordErrorOrigin(sourceName, lineNumber, lineSource, columnNumber); - } - - /** - * @deprecated Use {@link RhinoException#sourceName()} from the super class. - */ - public String getSourceName() - { - return sourceName(); - } - - /** - * @deprecated Use {@link RhinoException#lineNumber()} from the super class. - */ - public int getLineNumber() - { - return lineNumber(); - } - - /** - * @deprecated Use {@link RhinoException#columnNumber()} from the super class. - */ - public int getColumnNumber() - { - return columnNumber(); - } - - /** - * @deprecated Use {@link RhinoException#lineSource()} from the super class. - */ - public String getLineSource() - { - return lineSource(); - } - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Function.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Function.java deleted file mode 100644 index a4377e6..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Function.java +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * This is interface that all functions in JavaScript must implement. - * The interface provides for calling functions and constructors. - * - * @see org.mozilla.javascript.Scriptable - * @author Norris Boyd - */ - -public interface Function extends Scriptable, Callable -{ - /** - * Call the function. - * - * Note that the array of arguments is not guaranteed to have - * length greater than 0. - * - * @param cx the current Context for this thread - * @param scope the scope to execute the function relative to. This is - * set to the value returned by getParentScope() except - * when the function is called from a closure. - * @param thisObj the JavaScript <code>this</code> object - * @param args the array of arguments - * @return the result of the call - */ - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args); - - /** - * Call the function as a constructor. - * - * This method is invoked by the runtime in order to satisfy a use - * of the JavaScript <code>new</code> operator. This method is - * expected to create a new object and return it. - * - * @param cx the current Context for this thread - * @param scope an enclosing scope of the caller except - * when the function is called from a closure. - * @param args the array of arguments - * @return the allocated object - */ - public Scriptable construct(Context cx, Scriptable scope, Object[] args); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionNode.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionNode.java deleted file mode 100644 index 484167e..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionNode.java +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; -import java.util.ArrayList; -import java.util.HashMap; - -public class FunctionNode extends ScriptOrFnNode { - - public FunctionNode(String name) { - super(Token.FUNCTION); - functionName = name; - } - - public String getFunctionName() { - return functionName; - } - - public boolean requiresActivation() { - return itsNeedsActivation; - } - - public boolean getIgnoreDynamicScope() { - return itsIgnoreDynamicScope; - } - - public boolean isGenerator() { - return itsIsGenerator; - } - - public void addResumptionPoint(Node target) { - if (generatorResumePoints == null) - generatorResumePoints = new ArrayList(); - generatorResumePoints.add(target); - } - - public ArrayList getResumptionPoints() { - return generatorResumePoints; - } - - public HashMap getLiveLocals() { - return liveLocals; - } - - public void addLiveLocals(Node node, int[] locals) { - if (liveLocals == null) - liveLocals = new HashMap(); - liveLocals.put(node, locals); - } - - /** - * There are three types of functions that can be defined. The first - * is a function statement. This is a function appearing as a top-level - * statement (i.e., not nested inside some other statement) in either a - * script or a function. - * - * The second is a function expression, which is a function appearing in - * an expression except for the third type, which is... - * - * The third type is a function expression where the expression is the - * top-level expression in an expression statement. - * - * The three types of functions have different treatment and must be - * distinguished. - */ - public static final int FUNCTION_STATEMENT = 1; - public static final int FUNCTION_EXPRESSION = 2; - public static final int FUNCTION_EXPRESSION_STATEMENT = 3; - - public int getFunctionType() { - return itsFunctionType; - } - - String functionName; - int itsFunctionType; - boolean itsNeedsActivation; - boolean itsIgnoreDynamicScope; - boolean itsIsGenerator; - ArrayList generatorResumePoints; - HashMap liveLocals; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionObject.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionObject.java deleted file mode 100644 index 8fa4e68..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionObject.java +++ /dev/null @@ -1,569 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * David C. Navas - * Ted Neward - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -import java.lang.reflect.*; -import java.io.*; - -public class FunctionObject extends BaseFunction -{ - static final long serialVersionUID = -5332312783643935019L; - - /** - * Create a JavaScript function object from a Java method. - * - * <p>The <code>member</code> argument must be either a java.lang.reflect.Method - * or a java.lang.reflect.Constructor and must match one of two forms.<p> - * - * The first form is a member with zero or more parameters - * of the following types: Object, String, boolean, Scriptable, - * int, or double. The Long type is not supported - * because the double representation of a long (which is the - * EMCA-mandated storage type for Numbers) may lose precision. - * If the member is a Method, the return value must be void or one - * of the types allowed for parameters.<p> - * - * The runtime will perform appropriate conversions based - * upon the type of the parameter. A parameter type of - * Object specifies that no conversions are to be done. A parameter - * of type String will use Context.toString to convert arguments. - * Similarly, parameters of type double, boolean, and Scriptable - * will cause Context.toNumber, Context.toBoolean, and - * Context.toObject, respectively, to be called.<p> - * - * If the method is not static, the Java 'this' value will - * correspond to the JavaScript 'this' value. Any attempt - * to call the function with a 'this' value that is not - * of the right Java type will result in an error.<p> - * - * The second form is the variable arguments (or "varargs") - * form. If the FunctionObject will be used as a constructor, - * the member must have the following parameters - * <pre> - * (Context cx, Object[] args, Function ctorObj, - * boolean inNewExpr)</pre> - * and if it is a Method, be static and return an Object result.<p> - * - * Otherwise, if the FunctionObject will <i>not</i> be used to define a - * constructor, the member must be a static Method with parameters - * (Context cx, Scriptable thisObj, Object[] args, - * Function funObj) </pre> - * <pre> - * and an Object result.<p> - * - * When the function varargs form is called as part of a function call, - * the <code>args</code> parameter contains the - * arguments, with <code>thisObj</code> - * set to the JavaScript 'this' value. <code>funObj</code> - * is the function object for the invoked function.<p> - * - * When the constructor varargs form is called or invoked while evaluating - * a <code>new</code> expression, <code>args</code> contains the - * arguments, <code>ctorObj</code> refers to this FunctionObject, and - * <code>inNewExpr</code> is true if and only if a <code>new</code> - * expression caused the call. This supports defining a function that - * has different behavior when called as a constructor than when - * invoked as a normal function call. (For example, the Boolean - * constructor, when called as a function, - * will convert to boolean rather than creating a new object.)<p> - * - * @param name the name of the function - * @param methodOrConstructor a java.lang.reflect.Method or a java.lang.reflect.Constructor - * that defines the object - * @param scope enclosing scope of function - * @see org.mozilla.javascript.Scriptable - */ - public FunctionObject(String name, Member methodOrConstructor, - Scriptable scope) - { - if (methodOrConstructor instanceof Constructor) { - member = new MemberBox((Constructor) methodOrConstructor); - isStatic = true; // well, doesn't take a 'this' - } else { - member = new MemberBox((Method) methodOrConstructor); - isStatic = member.isStatic(); - } - String methodName = member.getName(); - this.functionName = name; - Class[] types = member.argTypes; - int arity = types.length; - if (arity == 4 && (types[1].isArray() || types[2].isArray())) { - // Either variable args or an error. - if (types[1].isArray()) { - if (!isStatic || - types[0] != ScriptRuntime.ContextClass || - types[1].getComponentType() != ScriptRuntime.ObjectClass || - types[2] != ScriptRuntime.FunctionClass || - types[3] != Boolean.TYPE) - { - throw Context.reportRuntimeError1( - "msg.varargs.ctor", methodName); - } - parmsLength = VARARGS_CTOR; - } else { - if (!isStatic || - types[0] != ScriptRuntime.ContextClass || - types[1] != ScriptRuntime.ScriptableClass || - types[2].getComponentType() != ScriptRuntime.ObjectClass || - types[3] != ScriptRuntime.FunctionClass) - { - throw Context.reportRuntimeError1( - "msg.varargs.fun", methodName); - } - parmsLength = VARARGS_METHOD; - } - } else { - parmsLength = arity; - if (arity > 0) { - typeTags = new byte[arity]; - for (int i = 0; i != arity; ++i) { - int tag = getTypeTag(types[i]); - if (tag == JAVA_UNSUPPORTED_TYPE) { - throw Context.reportRuntimeError2( - "msg.bad.parms", types[i].getName(), methodName); - } - typeTags[i] = (byte)tag; - } - } - } - - if (member.isMethod()) { - Method method = member.method(); - Class returnType = method.getReturnType(); - if (returnType == Void.TYPE) { - hasVoidReturn = true; - } else { - returnTypeTag = getTypeTag(returnType); - } - } else { - Class ctorType = member.getDeclaringClass(); - if (!ScriptRuntime.ScriptableClass.isAssignableFrom(ctorType)) { - throw Context.reportRuntimeError1( - "msg.bad.ctor.return", ctorType.getName()); - } - } - - ScriptRuntime.setFunctionProtoAndParent(this, scope); - } - - /** - * @return One of <tt>JAVA_*_TYPE</tt> constants to indicate desired type - * or {@link #JAVA_UNSUPPORTED_TYPE} if the convertion is not - * possible - */ - public static int getTypeTag(Class type) - { - if (type == ScriptRuntime.StringClass) - return JAVA_STRING_TYPE; - if (type == ScriptRuntime.IntegerClass || type == Integer.TYPE) - return JAVA_INT_TYPE; - if (type == ScriptRuntime.BooleanClass || type == Boolean.TYPE) - return JAVA_BOOLEAN_TYPE; - if (type == ScriptRuntime.DoubleClass || type == Double.TYPE) - return JAVA_DOUBLE_TYPE; - if (ScriptRuntime.ScriptableClass.isAssignableFrom(type)) - return JAVA_SCRIPTABLE_TYPE; - if (type == ScriptRuntime.ObjectClass) - return JAVA_OBJECT_TYPE; - - // Note that the long type is not supported; see the javadoc for - // the constructor for this class - - return JAVA_UNSUPPORTED_TYPE; - } - - public static Object convertArg(Context cx, Scriptable scope, - Object arg, int typeTag) - { - switch (typeTag) { - case JAVA_STRING_TYPE: - if (arg instanceof String) - return arg; - return ScriptRuntime.toString(arg); - case JAVA_INT_TYPE: - if (arg instanceof Integer) - return arg; - return new Integer(ScriptRuntime.toInt32(arg)); - case JAVA_BOOLEAN_TYPE: - if (arg instanceof Boolean) - return arg; - return ScriptRuntime.toBoolean(arg) ? Boolean.TRUE - : Boolean.FALSE; - case JAVA_DOUBLE_TYPE: - if (arg instanceof Double) - return arg; - return new Double(ScriptRuntime.toNumber(arg)); - case JAVA_SCRIPTABLE_TYPE: - if (arg instanceof Scriptable) - return arg; - return ScriptRuntime.toObject(cx, scope, arg); - case JAVA_OBJECT_TYPE: - return arg; - default: - throw new IllegalArgumentException(); - } - } - - /** - * Return the value defined by the method used to construct the object - * (number of parameters of the method, or 1 if the method is a "varargs" - * form). - */ - public int getArity() { - return parmsLength < 0 ? 1 : parmsLength; - } - - /** - * Return the same value as {@link #getArity()}. - */ - public int getLength() { - return getArity(); - } - - public String getFunctionName() - { - return (functionName == null) ? "" : functionName; - } - - /** - * Get Java method or constructor this function represent. - */ - public Member getMethodOrConstructor() - { - if (member.isMethod()) { - return member.method(); - } else { - return member.ctor(); - } - } - - static Method findSingleMethod(Method[] methods, String name) - { - Method found = null; - for (int i = 0, N = methods.length; i != N; ++i) { - Method method = methods[i]; - if (method != null && name.equals(method.getName())) { - if (found != null) { - throw Context.reportRuntimeError2( - "msg.no.overload", name, - method.getDeclaringClass().getName()); - } - found = method; - } - } - return found; - } - - /** - * Returns all public methods declared by the specified class. This excludes - * inherited methods. - * - * @param clazz the class from which to pull public declared methods - * @return the public methods declared in the specified class - * @see Class#getDeclaredMethods() - */ - static Method[] getMethodList(Class clazz) { - Method[] methods = null; - try { - // getDeclaredMethods may be rejected by the security manager - // but getMethods is more expensive - if (!sawSecurityException) - methods = clazz.getDeclaredMethods(); - } catch (SecurityException e) { - // If we get an exception once, give up on getDeclaredMethods - sawSecurityException = true; - } - if (methods == null) { - methods = clazz.getMethods(); - } - int count = 0; - for (int i=0; i < methods.length; i++) { - if (sawSecurityException - ? methods[i].getDeclaringClass() != clazz - : !Modifier.isPublic(methods[i].getModifiers())) - { - methods[i] = null; - } else { - count++; - } - } - Method[] result = new Method[count]; - int j=0; - for (int i=0; i < methods.length; i++) { - if (methods[i] != null) - result[j++] = methods[i]; - } - return result; - } - - /** - * Define this function as a JavaScript constructor. - * <p> - * Sets up the "prototype" and "constructor" properties. Also - * calls setParent and setPrototype with appropriate values. - * Then adds the function object as a property of the given scope, using - * <code>prototype.getClassName()</code> - * as the name of the property. - * - * @param scope the scope in which to define the constructor (typically - * the global object) - * @param prototype the prototype object - * @see org.mozilla.javascript.Scriptable#setParentScope - * @see org.mozilla.javascript.Scriptable#setPrototype - * @see org.mozilla.javascript.Scriptable#getClassName - */ - public void addAsConstructor(Scriptable scope, Scriptable prototype) - { - initAsConstructor(scope, prototype); - defineProperty(scope, prototype.getClassName(), - this, ScriptableObject.DONTENUM); - } - - void initAsConstructor(Scriptable scope, Scriptable prototype) - { - ScriptRuntime.setFunctionProtoAndParent(this, scope); - setImmunePrototypeProperty(prototype); - - prototype.setParentScope(this); - - defineProperty(prototype, "constructor", this, - ScriptableObject.DONTENUM | - ScriptableObject.PERMANENT | - ScriptableObject.READONLY); - setParentScope(scope); - } - - /** - * @deprecated Use {@link #getTypeTag(Class)} - * and {@link #convertArg(Context, Scriptable, Object, int)} - * for type convertion. - */ - public static Object convertArg(Context cx, Scriptable scope, - Object arg, Class desired) - { - int tag = getTypeTag(desired); - if (tag == JAVA_UNSUPPORTED_TYPE) { - throw Context.reportRuntimeError1 - ("msg.cant.convert", desired.getName()); - } - return convertArg(cx, scope, arg, tag); - } - - /** - * Performs conversions on argument types if needed and - * invokes the underlying Java method or constructor. - * <p> - * Implements Function.call. - * - * @see org.mozilla.javascript.Function#call( - * Context, Scriptable, Scriptable, Object[]) - */ - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - Object result; - boolean checkMethodResult = false; - - if (parmsLength < 0) { - if (parmsLength == VARARGS_METHOD) { - Object[] invokeArgs = { cx, thisObj, args, this }; - result = member.invoke(null, invokeArgs); - checkMethodResult = true; - } else { - boolean inNewExpr = (thisObj == null); - Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE; - Object[] invokeArgs = { cx, args, this, b }; - result = (member.isCtor()) - ? member.newInstance(invokeArgs) - : member.invoke(null, invokeArgs); - } - - } else { - if (!isStatic) { - Class clazz = member.getDeclaringClass(); - if (!clazz.isInstance(thisObj)) { - boolean compatible = false; - if (thisObj == scope) { - Scriptable parentScope = getParentScope(); - if (scope != parentScope) { - // Call with dynamic scope for standalone function, - // use parentScope as thisObj - compatible = clazz.isInstance(parentScope); - if (compatible) { - thisObj = parentScope; - } - } - } - if (!compatible) { - // Couldn't find an object to call this on. - throw ScriptRuntime.typeError1("msg.incompat.call", - functionName); - } - } - } - - Object[] invokeArgs; - if (parmsLength == args.length) { - // Do not allocate new argument array if java arguments are - // the same as the original js ones. - invokeArgs = args; - for (int i = 0; i != parmsLength; ++i) { - Object arg = args[i]; - Object converted = convertArg(cx, scope, arg, typeTags[i]); - if (arg != converted) { - if (invokeArgs == args) { - invokeArgs = args.clone(); - } - invokeArgs[i] = converted; - } - } - } else if (parmsLength == 0) { - invokeArgs = ScriptRuntime.emptyArgs; - } else { - invokeArgs = new Object[parmsLength]; - for (int i = 0; i != parmsLength; ++i) { - Object arg = (i < args.length) - ? args[i] - : Undefined.instance; - invokeArgs[i] = convertArg(cx, scope, arg, typeTags[i]); - } - } - - if (member.isMethod()) { - result = member.invoke(thisObj, invokeArgs); - checkMethodResult = true; - } else { - result = member.newInstance(invokeArgs); - } - - } - - if (checkMethodResult) { - if (hasVoidReturn) { - result = Undefined.instance; - } else if (returnTypeTag == JAVA_UNSUPPORTED_TYPE) { - result = cx.getWrapFactory().wrap(cx, scope, result, null); - } - // XXX: the code assumes that if returnTypeTag == JAVA_OBJECT_TYPE - // then the Java method did a proper job of converting the - // result to JS primitive or Scriptable to avoid - // potentially costly Context.javaToJS call. - } - - return result; - } - - /** - * Return new {@link Scriptable} instance using the default - * constructor for the class of the underlying Java method. - * Return null to indicate that the call method should be used to create - * new objects. - */ - public Scriptable createObject(Context cx, Scriptable scope) { - if (member.isCtor() || parmsLength == VARARGS_CTOR) { - return null; - } - Scriptable result; - try { - result = (Scriptable) member.getDeclaringClass().newInstance(); - } catch (Exception ex) { - throw Context.throwAsScriptRuntimeEx(ex); - } - - result.setPrototype(getClassPrototype()); - result.setParentScope(getParentScope()); - return result; - } - - boolean isVarArgsMethod() { - return parmsLength == VARARGS_METHOD; - } - - boolean isVarArgsConstructor() { - return parmsLength == VARARGS_CTOR; - } - - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - if (parmsLength > 0) { - Class[] types = member.argTypes; - typeTags = new byte[parmsLength]; - for (int i = 0; i != parmsLength; ++i) { - typeTags[i] = (byte)getTypeTag(types[i]); - } - } - if (member.isMethod()) { - Method method = member.method(); - Class returnType = method.getReturnType(); - if (returnType == Void.TYPE) { - hasVoidReturn = true; - } else { - returnTypeTag = getTypeTag(returnType); - } - } - } - - private static final short VARARGS_METHOD = -1; - private static final short VARARGS_CTOR = -2; - - private static boolean sawSecurityException; - - public static final int JAVA_UNSUPPORTED_TYPE = 0; - public static final int JAVA_STRING_TYPE = 1; - public static final int JAVA_INT_TYPE = 2; - public static final int JAVA_BOOLEAN_TYPE = 3; - public static final int JAVA_DOUBLE_TYPE = 4; - public static final int JAVA_SCRIPTABLE_TYPE = 5; - public static final int JAVA_OBJECT_TYPE = 6; - - MemberBox member; - private String functionName; - private transient byte[] typeTags; - private int parmsLength; - private transient boolean hasVoidReturn; - private transient int returnTypeTag; - private boolean isStatic; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/GeneratedClassLoader.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/GeneratedClassLoader.java deleted file mode 100644 index 0f73615..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/GeneratedClassLoader.java +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * Interface to define classes from generated byte code. - */ -public interface GeneratedClassLoader { - - /** - * Define a new Java class. - * Classes created via this method should have the same class loader. - * - * @param name fully qualified class name - * @param data class byte code - * @return new class object - */ - public Class defineClass(String name, byte[] data); - - /** - * Link the given class. - * - * @param cl Class instance returned from the previous call to - * {@link #defineClass(String, byte[])} - * @see java.lang.ClassLoader - */ - public void linkClass(Class cl); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IRFactory.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IRFactory.java deleted file mode 100644 index 1f51cb1..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IRFactory.java +++ /dev/null @@ -1,1607 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Ethan Hugg - * Bob Jervis - * Terry Lucas - * Milen Nankov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.util.List; -import java.util.ArrayList; - -/** - * This class allows the creation of nodes, and follows the Factory pattern. - * - * @see Node - * @author Mike McCabe - * @author Norris Boyd - */ -final class IRFactory -{ - IRFactory(Parser parser) - { - this.parser = parser; - } - - ScriptOrFnNode createScript() - { - return new ScriptOrFnNode(Token.SCRIPT); - } - - /** - * Script (for associating file/url names with toplevel scripts.) - */ - void initScript(ScriptOrFnNode scriptNode, Node body) - { - Node children = body.getFirstChild(); - if (children != null) { scriptNode.addChildrenToBack(children); } - } - - /** - * Leaf - */ - Node createLeaf(int nodeType) - { - return new Node(nodeType); - } - - /** - * Statement leaf nodes. - */ - - Node createSwitch(Node expr, int lineno) - { - // - // The switch will be rewritten from: - // - // switch (expr) { - // case test1: statements1; - // ... - // default: statementsDefault; - // ... - // case testN: statementsN; - // } - // - // to: - // - // { - // switch (expr) { - // case test1: goto label1; - // ... - // case testN: goto labelN; - // } - // goto labelDefault; - // label1: - // statements1; - // ... - // labelDefault: - // statementsDefault; - // ... - // labelN: - // statementsN; - // breakLabel: - // } - // - // where inside switch each "break;" without label will be replaced - // by "goto breakLabel". - // - // If the original switch does not have the default label, then - // the transformed code would contain after the switch instead of - // goto labelDefault; - // the following goto: - // goto breakLabel; - // - - Node.Jump switchNode = new Node.Jump(Token.SWITCH, expr, lineno); - Node block = new Node(Token.BLOCK, switchNode); - return block; - } - - /** - * If caseExpression argument is null it indicate default label. - */ - void addSwitchCase(Node switchBlock, Node caseExpression, Node statements) - { - if (switchBlock.getType() != Token.BLOCK) throw Kit.codeBug(); - Node.Jump switchNode = (Node.Jump)switchBlock.getFirstChild(); - if (switchNode.getType() != Token.SWITCH) throw Kit.codeBug(); - - Node gotoTarget = Node.newTarget(); - if (caseExpression != null) { - Node.Jump caseNode = new Node.Jump(Token.CASE, caseExpression); - caseNode.target = gotoTarget; - switchNode.addChildToBack(caseNode); - } else { - switchNode.setDefault(gotoTarget); - } - switchBlock.addChildToBack(gotoTarget); - switchBlock.addChildToBack(statements); - } - - void closeSwitch(Node switchBlock) - { - if (switchBlock.getType() != Token.BLOCK) throw Kit.codeBug(); - Node.Jump switchNode = (Node.Jump)switchBlock.getFirstChild(); - if (switchNode.getType() != Token.SWITCH) throw Kit.codeBug(); - - Node switchBreakTarget = Node.newTarget(); - // switchNode.target is only used by NodeTransformer - // to detect switch end - switchNode.target = switchBreakTarget; - - Node defaultTarget = switchNode.getDefault(); - if (defaultTarget == null) { - defaultTarget = switchBreakTarget; - } - - switchBlock.addChildAfter(makeJump(Token.GOTO, defaultTarget), - switchNode); - switchBlock.addChildToBack(switchBreakTarget); - } - - Node createVariables(int token, int lineno) - { - return new Node(token, lineno); - } - - Node createExprStatement(Node expr, int lineno) - { - int type; - if (parser.insideFunction()) { - type = Token.EXPR_VOID; - } else { - type = Token.EXPR_RESULT; - } - return new Node(type, expr, lineno); - } - - Node createExprStatementNoReturn(Node expr, int lineno) - { - return new Node(Token.EXPR_VOID, expr, lineno); - } - - Node createDefaultNamespace(Node expr, int lineno) - { - // default xml namespace requires activation - setRequiresActivation(); - Node n = createUnary(Token.DEFAULTNAMESPACE, expr); - Node result = createExprStatement(n, lineno); - return result; - } - - /** - * Name - */ - Node createName(String name) - { - checkActivationName(name, Token.NAME); - return Node.newString(Token.NAME, name); - } - - private Node createName(int type, String name, Node child) - { - Node result = createName(name); - result.setType(type); - if (child != null) - result.addChildToBack(child); - return result; - } - - /** - * String (for literals) - */ - Node createString(String string) - { - return Node.newString(string); - } - - /** - * Number (for literals) - */ - Node createNumber(double number) - { - return Node.newNumber(number); - } - - /** - * Catch clause of try/catch/finally - * @param varName the name of the variable to bind to the exception - * @param catchCond the condition under which to catch the exception. - * May be null if no condition is given. - * @param stmts the statements in the catch clause - * @param lineno the starting line number of the catch clause - */ - Node createCatch(String varName, Node catchCond, Node stmts, int lineno) - { - if (catchCond == null) { - catchCond = new Node(Token.EMPTY); - } - return new Node(Token.CATCH, createName(varName), - catchCond, stmts, lineno); - } - - /** - * Throw - */ - Node createThrow(Node expr, int lineno) - { - return new Node(Token.THROW, expr, lineno); - } - - /** - * Return - */ - Node createReturn(Node expr, int lineno) - { - return expr == null - ? new Node(Token.RETURN, lineno) - : new Node(Token.RETURN, expr, lineno); - } - - /** - * Debugger - */ - Node createDebugger(int lineno) - { - return new Node(Token.DEBUGGER, lineno); - } - - /** - * Label - */ - Node createLabel(int lineno) - { - return new Node.Jump(Token.LABEL, lineno); - } - - Node getLabelLoop(Node label) - { - return ((Node.Jump)label).getLoop(); - } - - /** - * Label - */ - Node createLabeledStatement(Node labelArg, Node statement) - { - Node.Jump label = (Node.Jump)labelArg; - - // Make a target and put it _after_ the statement - // node. And in the LABEL node, so breaks get the - // right target. - - Node breakTarget = Node.newTarget(); - Node block = new Node(Token.BLOCK, label, statement, breakTarget); - label.target = breakTarget; - - return block; - } - - /** - * Break (possibly labeled) - */ - Node createBreak(Node breakStatement, int lineno) - { - Node.Jump n = new Node.Jump(Token.BREAK, lineno); - Node.Jump jumpStatement; - int t = breakStatement.getType(); - if (t == Token.LOOP || t == Token.LABEL) { - jumpStatement = (Node.Jump)breakStatement; - } else if (t == Token.BLOCK - && breakStatement.getFirstChild().getType() == Token.SWITCH) - { - jumpStatement = (Node.Jump)breakStatement.getFirstChild(); - } else { - throw Kit.codeBug(); - } - n.setJumpStatement(jumpStatement); - return n; - } - - /** - * Continue (possibly labeled) - */ - Node createContinue(Node loop, int lineno) - { - if (loop.getType() != Token.LOOP) Kit.codeBug(); - Node.Jump n = new Node.Jump(Token.CONTINUE, lineno); - n.setJumpStatement((Node.Jump)loop); - return n; - } - - /** - * Statement block - * Creates the empty statement block - * Must make subsequent calls to add statements to the node - */ - Node createBlock(int lineno) - { - return new Node(Token.BLOCK, lineno); - } - - FunctionNode createFunction(String name) - { - return new FunctionNode(name); - } - - Node initFunction(FunctionNode fnNode, int functionIndex, - Node statements, int functionType) - { - fnNode.itsFunctionType = functionType; - fnNode.addChildToBack(statements); - - int functionCount = fnNode.getFunctionCount(); - if (functionCount != 0) { - // Functions containing other functions require activation objects - fnNode.itsNeedsActivation = true; - } - - if (functionType == FunctionNode.FUNCTION_EXPRESSION) { - String name = fnNode.getFunctionName(); - if (name != null && name.length() != 0) { - // A function expression needs to have its name as a - // variable (if it isn't already allocated as a variable). - // See ECMA Ch. 13. We add code to the beginning of the - // function to initialize a local variable of the - // function's name to the function value. - Node setFn = new Node(Token.EXPR_VOID, - new Node(Token.SETNAME, - Node.newString(Token.BINDNAME, name), - new Node(Token.THISFN))); - statements.addChildrenToFront(setFn); - } - } - - // Add return to end if needed. - Node lastStmt = statements.getLastChild(); - if (lastStmt == null || lastStmt.getType() != Token.RETURN) { - statements.addChildToBack(new Node(Token.RETURN)); - } - - Node result = Node.newString(Token.FUNCTION, - fnNode.getFunctionName()); - result.putIntProp(Node.FUNCTION_PROP, functionIndex); - return result; - } - - /** - * Add a child to the back of the given node. This function - * breaks the Factory abstraction, but it removes a requirement - * from implementors of Node. - */ - void addChildToBack(Node parent, Node child) - { - parent.addChildToBack(child); - } - - /** - * Create a node that can be used to hold lexically scoped variable - * definitions (via let declarations). - * - * @param token the token of the node to create - * @param lineno line number of source - * @return the created node - */ - Node createScopeNode(int token, int lineno) { - return new Node.Scope(token, lineno); - } - - /** - * Create loop node. The parser will later call - * createWhile|createDoWhile|createFor|createForIn - * to finish loop generation. - */ - Node createLoopNode(Node loopLabel, int lineno) - { - Node.Jump result = new Node.Scope(Token.LOOP, lineno); - if (loopLabel != null) { - ((Node.Jump)loopLabel).setLoop(result); - } - return result; - } - - /** - * While - */ - Node createWhile(Node loop, Node cond, Node body) - { - return createLoop((Node.Jump)loop, LOOP_WHILE, body, cond, - null, null); - } - - /** - * DoWhile - */ - Node createDoWhile(Node loop, Node body, Node cond) - { - return createLoop((Node.Jump)loop, LOOP_DO_WHILE, body, cond, - null, null); - } - - /** - * For - */ - Node createFor(Node loop, Node init, Node test, Node incr, Node body) - { - if (init.getType() == Token.LET) { - // rewrite "for (let i=s; i < N; i++)..." as - // "let (i=s) { for (; i < N; i++)..." so that "s" is evaluated - // outside the scope of the for. - Node.Scope let = Node.Scope.splitScope((Node.Scope)loop); - let.setType(Token.LET); - let.addChildrenToBack(init); - let.addChildToBack(createLoop((Node.Jump)loop, LOOP_FOR, body, test, - new Node(Token.EMPTY), incr)); - return let; - } - return createLoop((Node.Jump)loop, LOOP_FOR, body, test, init, incr); - } - - private Node createLoop(Node.Jump loop, int loopType, Node body, Node cond, - Node init, Node incr) - { - Node bodyTarget = Node.newTarget(); - Node condTarget = Node.newTarget(); - if (loopType == LOOP_FOR && cond.getType() == Token.EMPTY) { - cond = new Node(Token.TRUE); - } - Node.Jump IFEQ = new Node.Jump(Token.IFEQ, cond); - IFEQ.target = bodyTarget; - Node breakTarget = Node.newTarget(); - - loop.addChildToBack(bodyTarget); - loop.addChildrenToBack(body); - if (loopType == LOOP_WHILE || loopType == LOOP_FOR) { - // propagate lineno to condition - loop.addChildrenToBack(new Node(Token.EMPTY, loop.getLineno())); - } - loop.addChildToBack(condTarget); - loop.addChildToBack(IFEQ); - loop.addChildToBack(breakTarget); - - loop.target = breakTarget; - Node continueTarget = condTarget; - - if (loopType == LOOP_WHILE || loopType == LOOP_FOR) { - // Just add a GOTO to the condition in the do..while - loop.addChildToFront(makeJump(Token.GOTO, condTarget)); - - if (loopType == LOOP_FOR) { - int initType = init.getType(); - if (initType != Token.EMPTY) { - if (initType != Token.VAR && initType != Token.LET) { - init = new Node(Token.EXPR_VOID, init); - } - loop.addChildToFront(init); - } - Node incrTarget = Node.newTarget(); - loop.addChildAfter(incrTarget, body); - if (incr.getType() != Token.EMPTY) { - incr = new Node(Token.EXPR_VOID, incr); - loop.addChildAfter(incr, incrTarget); - } - continueTarget = incrTarget; - } - } - - loop.setContinue(continueTarget); - - return loop; - } - - /** - * For .. In - * - */ - Node createForIn(int declType, Node loop, Node lhs, Node obj, Node body, - boolean isForEach) - { - int destructuring = -1; - int destructuringLen = 0; - Node lvalue; - int type = lhs.getType(); - if (type == Token.VAR || type == Token.LET) { - Node lastChild = lhs.getLastChild(); - if (lhs.getFirstChild() != lastChild) { - /* - * check that there was only one variable given. - * we can't do this in the parser, because then the - * parser would have to know something about the - * 'init' node of the for-in loop. - */ - parser.reportError("msg.mult.index"); - } - if (lastChild.getType() == Token.ARRAYLIT || - lastChild.getType() == Token.OBJECTLIT) - { - type = destructuring = lastChild.getType(); - lvalue = lastChild; - destructuringLen = lastChild.getIntProp( - Node.DESTRUCTURING_ARRAY_LENGTH, 0); - } else if (lastChild.getType() == Token.NAME) { - lvalue = Node.newString(Token.NAME, lastChild.getString()); - } else { - parser.reportError("msg.bad.for.in.lhs"); - return obj; - } - } else if (type == Token.ARRAYLIT || type == Token.OBJECTLIT) { - destructuring = type; - lvalue = lhs; - destructuringLen = lhs.getIntProp(Node.DESTRUCTURING_ARRAY_LENGTH, 0); - } else { - lvalue = makeReference(lhs); - if (lvalue == null) { - parser.reportError("msg.bad.for.in.lhs"); - return obj; - } - } - - Node localBlock = new Node(Token.LOCAL_BLOCK); - int initType = (isForEach) ? Token.ENUM_INIT_VALUES : - (destructuring != -1) ? Token.ENUM_INIT_ARRAY : - Token.ENUM_INIT_KEYS; - Node init = new Node(initType, obj); - init.putProp(Node.LOCAL_BLOCK_PROP, localBlock); - Node cond = new Node(Token.ENUM_NEXT); - cond.putProp(Node.LOCAL_BLOCK_PROP, localBlock); - Node id = new Node(Token.ENUM_ID); - id.putProp(Node.LOCAL_BLOCK_PROP, localBlock); - - Node newBody = new Node(Token.BLOCK); - Node assign; - if (destructuring != -1) { - assign = createDestructuringAssignment(declType, lvalue, id); - if (!isForEach && (destructuring == Token.OBJECTLIT || - destructuringLen != 2)) - { - // destructuring assignment is only allowed in for..each or - // with an array type of length 2 (to hold key and value) - parser.reportError("msg.bad.for.in.destruct"); - } - } else { - assign = simpleAssignment(lvalue, id); - } - newBody.addChildToBack(new Node(Token.EXPR_VOID, assign)); - newBody.addChildToBack(body); - - loop = createWhile(loop, cond, newBody); - loop.addChildToFront(init); - if (type == Token.VAR || type == Token.LET) - loop.addChildToFront(lhs); - localBlock.addChildToBack(loop); - - return localBlock; - } - - /** - * Try/Catch/Finally - * - * The IRFactory tries to express as much as possible in the tree; - * the responsibilities remaining for Codegen are to add the Java - * handlers: (Either (but not both) of TARGET and FINALLY might not - * be defined) - - * - a catch handler for javascript exceptions that unwraps the - * exception onto the stack and GOTOes to the catch target - - * - a finally handler - - * ... and a goto to GOTO around these handlers. - */ - Node createTryCatchFinally(Node tryBlock, Node catchBlocks, - Node finallyBlock, int lineno) - { - boolean hasFinally = (finallyBlock != null) - && (finallyBlock.getType() != Token.BLOCK - || finallyBlock.hasChildren()); - - // short circuit - if (tryBlock.getType() == Token.BLOCK && !tryBlock.hasChildren() - && !hasFinally) - { - return tryBlock; - } - - boolean hasCatch = catchBlocks.hasChildren(); - - // short circuit - if (!hasFinally && !hasCatch) { - // bc finally might be an empty block... - return tryBlock; - } - - - Node handlerBlock = new Node(Token.LOCAL_BLOCK); - Node.Jump pn = new Node.Jump(Token.TRY, tryBlock, lineno); - pn.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock); - - if (hasCatch) { - // jump around catch code - Node endCatch = Node.newTarget(); - pn.addChildToBack(makeJump(Token.GOTO, endCatch)); - - // make a TARGET for the catch that the tcf node knows about - Node catchTarget = Node.newTarget(); - pn.target = catchTarget; - // mark it - pn.addChildToBack(catchTarget); - - // - // Given - // - // try { - // tryBlock; - // } catch (e if condition1) { - // something1; - // ... - // - // } catch (e if conditionN) { - // somethingN; - // } catch (e) { - // somethingDefault; - // } - // - // rewrite as - // - // try { - // tryBlock; - // goto after_catch: - // } catch (x) { - // with (newCatchScope(e, x)) { - // if (condition1) { - // something1; - // goto after_catch; - // } - // } - // ... - // with (newCatchScope(e, x)) { - // if (conditionN) { - // somethingN; - // goto after_catch; - // } - // } - // with (newCatchScope(e, x)) { - // somethingDefault; - // goto after_catch; - // } - // } - // after_catch: - // - // If there is no default catch, then the last with block - // arround "somethingDefault;" is replaced by "rethrow;" - - // It is assumed that catch handler generation will store - // exeception object in handlerBlock register - - // Block with local for exception scope objects - Node catchScopeBlock = new Node(Token.LOCAL_BLOCK); - - // expects catchblocks children to be (cond block) pairs. - Node cb = catchBlocks.getFirstChild(); - boolean hasDefault = false; - int scopeIndex = 0; - while (cb != null) { - int catchLineNo = cb.getLineno(); - - Node name = cb.getFirstChild(); - Node cond = name.getNext(); - Node catchStatement = cond.getNext(); - cb.removeChild(name); - cb.removeChild(cond); - cb.removeChild(catchStatement); - - // Add goto to the catch statement to jump out of catch - // but prefix it with LEAVEWITH since try..catch produces - // "with"code in order to limit the scope of the exception - // object. - catchStatement.addChildToBack(new Node(Token.LEAVEWITH)); - catchStatement.addChildToBack(makeJump(Token.GOTO, endCatch)); - - // Create condition "if" when present - Node condStmt; - if (cond.getType() == Token.EMPTY) { - condStmt = catchStatement; - hasDefault = true; - } else { - condStmt = createIf(cond, catchStatement, null, - catchLineNo); - } - - // Generate code to create the scope object and store - // it in catchScopeBlock register - Node catchScope = new Node(Token.CATCH_SCOPE, name, - createUseLocal(handlerBlock)); - catchScope.putProp(Node.LOCAL_BLOCK_PROP, catchScopeBlock); - catchScope.putIntProp(Node.CATCH_SCOPE_PROP, scopeIndex); - catchScopeBlock.addChildToBack(catchScope); - - // Add with statement based on catch scope object - catchScopeBlock.addChildToBack( - createWith(createUseLocal(catchScopeBlock), condStmt, - catchLineNo)); - - // move to next cb - cb = cb.getNext(); - ++scopeIndex; - } - pn.addChildToBack(catchScopeBlock); - if (!hasDefault) { - // Generate code to rethrow if no catch clause was executed - Node rethrow = new Node(Token.RETHROW); - rethrow.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock); - pn.addChildToBack(rethrow); - } - - pn.addChildToBack(endCatch); - } - - if (hasFinally) { - Node finallyTarget = Node.newTarget(); - pn.setFinally(finallyTarget); - - // add jsr finally to the try block - pn.addChildToBack(makeJump(Token.JSR, finallyTarget)); - - // jump around finally code - Node finallyEnd = Node.newTarget(); - pn.addChildToBack(makeJump(Token.GOTO, finallyEnd)); - - pn.addChildToBack(finallyTarget); - Node fBlock = new Node(Token.FINALLY, finallyBlock); - fBlock.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock); - pn.addChildToBack(fBlock); - - pn.addChildToBack(finallyEnd); - } - handlerBlock.addChildToBack(pn); - return handlerBlock; - } - - /** - * Throw, Return, Label, Break and Continue are defined in ASTFactory. - */ - - /** - * With - */ - Node createWith(Node obj, Node body, int lineno) - { - setRequiresActivation(); - Node result = new Node(Token.BLOCK, lineno); - result.addChildToBack(new Node(Token.ENTERWITH, obj)); - Node bodyNode = new Node(Token.WITH, body, lineno); - result.addChildrenToBack(bodyNode); - result.addChildToBack(new Node(Token.LEAVEWITH)); - return result; - } - - /** - * DOTQUERY - */ - public Node createDotQuery (Node obj, Node body, int lineno) - { - setRequiresActivation(); - Node result = new Node(Token.DOTQUERY, obj, body, lineno); - return result; - } - - Node createArrayLiteral(ObjArray elems, int skipCount, int destructuringLen) - { - int length = elems.size(); - int[] skipIndexes = null; - if (skipCount != 0) { - skipIndexes = new int[skipCount]; - } - Node array = new Node(Token.ARRAYLIT); - for (int i = 0, j = 0; i != length; ++i) { - Node elem = (Node)elems.get(i); - if (elem != null) { - array.addChildToBack(elem); - } else { - skipIndexes[j] = i; - ++j; - } - } - if (skipCount != 0) { - array.putProp(Node.SKIP_INDEXES_PROP, skipIndexes); - } - array.putIntProp(Node.DESTRUCTURING_ARRAY_LENGTH, destructuringLen); - return array; - } - - /** - * Object Literals - * <BR> createObjectLiteral rewrites its argument as object - * creation plus object property entries, so later compiler - * stages don't need to know about object literals. - */ - Node createObjectLiteral(ObjArray elems) - { - int size = elems.size() / 2; - Node object = new Node(Token.OBJECTLIT); - Object[] properties; - if (size == 0) { - properties = ScriptRuntime.emptyArgs; - } else { - properties = new Object[size]; - for (int i = 0; i != size; ++i) { - properties[i] = elems.get(2 * i); - Node value = (Node)elems.get(2 * i + 1); - object.addChildToBack(value); - } - } - object.putProp(Node.OBJECT_IDS_PROP, properties); - return object; - } - - /** - * Regular expressions - */ - Node createRegExp(int regexpIndex) - { - Node n = new Node(Token.REGEXP); - n.putIntProp(Node.REGEXP_PROP, regexpIndex); - return n; - } - - /** - * If statement - */ - Node createIf(Node cond, Node ifTrue, Node ifFalse, int lineno) - { - int condStatus = isAlwaysDefinedBoolean(cond); - if (condStatus == ALWAYS_TRUE_BOOLEAN) { - return ifTrue; - } else if (condStatus == ALWAYS_FALSE_BOOLEAN) { - if (ifFalse != null) { - return ifFalse; - } - // Replace if (false) xxx by empty block - return new Node(Token.BLOCK, lineno); - } - - Node result = new Node(Token.BLOCK, lineno); - Node ifNotTarget = Node.newTarget(); - Node.Jump IFNE = new Node.Jump(Token.IFNE, cond); - IFNE.target = ifNotTarget; - - result.addChildToBack(IFNE); - result.addChildrenToBack(ifTrue); - - if (ifFalse != null) { - Node endTarget = Node.newTarget(); - result.addChildToBack(makeJump(Token.GOTO, endTarget)); - result.addChildToBack(ifNotTarget); - result.addChildrenToBack(ifFalse); - result.addChildToBack(endTarget); - } else { - result.addChildToBack(ifNotTarget); - } - - return result; - } - - Node createCondExpr(Node cond, Node ifTrue, Node ifFalse) - { - int condStatus = isAlwaysDefinedBoolean(cond); - if (condStatus == ALWAYS_TRUE_BOOLEAN) { - return ifTrue; - } else if (condStatus == ALWAYS_FALSE_BOOLEAN) { - return ifFalse; - } - return new Node(Token.HOOK, cond, ifTrue, ifFalse); - } - - /** - * Unary - */ - Node createUnary(int nodeType, Node child) - { - int childType = child.getType(); - switch (nodeType) { - case Token.DELPROP: { - Node n; - if (childType == Token.NAME) { - // Transform Delete(Name "a") - // to Delete(Bind("a"), String("a")) - child.setType(Token.BINDNAME); - Node left = child; - Node right = Node.newString(child.getString()); - n = new Node(nodeType, left, right); - } else if (childType == Token.GETPROP || - childType == Token.GETELEM) - { - Node left = child.getFirstChild(); - Node right = child.getLastChild(); - child.removeChild(left); - child.removeChild(right); - n = new Node(nodeType, left, right); - } else if (childType == Token.GET_REF) { - Node ref = child.getFirstChild(); - child.removeChild(ref); - n = new Node(Token.DEL_REF, ref); - } else { - n = new Node(Token.TRUE); - } - return n; - } - case Token.TYPEOF: - if (childType == Token.NAME) { - child.setType(Token.TYPEOFNAME); - return child; - } - break; - case Token.BITNOT: - if (childType == Token.NUMBER) { - int value = ScriptRuntime.toInt32(child.getDouble()); - child.setDouble(~value); - return child; - } - break; - case Token.NEG: - if (childType == Token.NUMBER) { - child.setDouble(-child.getDouble()); - return child; - } - break; - case Token.NOT: { - int status = isAlwaysDefinedBoolean(child); - if (status != 0) { - int type; - if (status == ALWAYS_TRUE_BOOLEAN) { - type = Token.FALSE; - } else { - type = Token.TRUE; - } - if (childType == Token.TRUE || childType == Token.FALSE) { - child.setType(type); - return child; - } - return new Node(type); - } - break; - } - } - return new Node(nodeType, child); - } - - Node createYield(Node child, int lineno) - { - if (!parser.insideFunction()) { - parser.reportError("msg.bad.yield"); - } - setRequiresActivation(); - setIsGenerator(); - if (child != null) - return new Node(Token.YIELD, child, lineno); - else - return new Node(Token.YIELD, lineno); - } - - Node createCallOrNew(int nodeType, Node child) - { - int type = Node.NON_SPECIALCALL; - if (child.getType() == Token.NAME) { - String name = child.getString(); - if (name.equals("eval")) { - type = Node.SPECIALCALL_EVAL; - } else if (name.equals("With")) { - type = Node.SPECIALCALL_WITH; - } - } else if (child.getType() == Token.GETPROP) { - String name = child.getLastChild().getString(); - if (name.equals("eval")) { - type = Node.SPECIALCALL_EVAL; - } - } - Node node = new Node(nodeType, child); - if (type != Node.NON_SPECIALCALL) { - // Calls to these functions require activation objects. - setRequiresActivation(); - node.putIntProp(Node.SPECIALCALL_PROP, type); - } - return node; - } - - Node createIncDec(int nodeType, boolean post, Node child) - { - child = makeReference(child); - if (child == null) { - String msg; - if (nodeType == Token.DEC) { - msg = "msg.bad.decr"; - } else { - msg = "msg.bad.incr"; - } - parser.reportError(msg); - return null; - } - - int childType = child.getType(); - - switch (childType) { - case Token.NAME: - case Token.GETPROP: - case Token.GETELEM: - case Token.GET_REF: { - Node n = new Node(nodeType, child); - int incrDecrMask = 0; - if (nodeType == Token.DEC) { - incrDecrMask |= Node.DECR_FLAG; - } - if (post) { - incrDecrMask |= Node.POST_FLAG; - } - n.putIntProp(Node.INCRDECR_PROP, incrDecrMask); - return n; - } - } - throw Kit.codeBug(); - } - - Node createPropertyGet(Node target, String namespace, String name, - int memberTypeFlags) - { - if (namespace == null && memberTypeFlags == 0) { - if (target == null) { - return createName(name); - } - checkActivationName(name, Token.GETPROP); - if (ScriptRuntime.isSpecialProperty(name)) { - Node ref = new Node(Token.REF_SPECIAL, target); - ref.putProp(Node.NAME_PROP, name); - return new Node(Token.GET_REF, ref); - } - return new Node(Token.GETPROP, target, createString(name)); - } - Node elem = createString(name); - memberTypeFlags |= Node.PROPERTY_FLAG; - return createMemberRefGet(target, namespace, elem, memberTypeFlags); - } - - Node createElementGet(Node target, String namespace, Node elem, - int memberTypeFlags) - { - // OPT: could optimize to createPropertyGet - // iff elem is string that can not be number - if (namespace == null && memberTypeFlags == 0) { - // stand-alone [aaa] as primary expression is array literal - // declaration and should not come here! - if (target == null) throw Kit.codeBug(); - return new Node(Token.GETELEM, target, elem); - } - return createMemberRefGet(target, namespace, elem, memberTypeFlags); - } - - private Node createMemberRefGet(Node target, String namespace, Node elem, - int memberTypeFlags) - { - Node nsNode = null; - if (namespace != null) { - // See 11.1.2 in ECMA 357 - if (namespace.equals("*")) { - nsNode = new Node(Token.NULL); - } else { - nsNode = createName(namespace); - } - } - Node ref; - if (target == null) { - if (namespace == null) { - ref = new Node(Token.REF_NAME, elem); - } else { - ref = new Node(Token.REF_NS_NAME, nsNode, elem); - } - } else { - if (namespace == null) { - ref = new Node(Token.REF_MEMBER, target, elem); - } else { - ref = new Node(Token.REF_NS_MEMBER, target, nsNode, elem); - } - } - if (memberTypeFlags != 0) { - ref.putIntProp(Node.MEMBER_TYPE_PROP, memberTypeFlags); - } - return new Node(Token.GET_REF, ref); - } - - /** - * Binary - */ - Node createBinary(int nodeType, Node left, Node right) - { - switch (nodeType) { - - case Token.ADD: - // numerical addition and string concatenation - if (left.type == Token.STRING) { - String s2; - if (right.type == Token.STRING) { - s2 = right.getString(); - } else if (right.type == Token.NUMBER) { - s2 = ScriptRuntime.numberToString(right.getDouble(), 10); - } else { - break; - } - String s1 = left.getString(); - left.setString(s1.concat(s2)); - return left; - } else if (left.type == Token.NUMBER) { - if (right.type == Token.NUMBER) { - left.setDouble(left.getDouble() + right.getDouble()); - return left; - } else if (right.type == Token.STRING) { - String s1, s2; - s1 = ScriptRuntime.numberToString(left.getDouble(), 10); - s2 = right.getString(); - right.setString(s1.concat(s2)); - return right; - } - } - // can't do anything if we don't know both types - since - // 0 + object is supposed to call toString on the object and do - // string concantenation rather than addition - break; - - case Token.SUB: - // numerical subtraction - if (left.type == Token.NUMBER) { - double ld = left.getDouble(); - if (right.type == Token.NUMBER) { - //both numbers - left.setDouble(ld - right.getDouble()); - return left; - } else if (ld == 0.0) { - // first 0: 0-x -> -x - return new Node(Token.NEG, right); - } - } else if (right.type == Token.NUMBER) { - if (right.getDouble() == 0.0) { - //second 0: x - 0 -> +x - // can not make simply x because x - 0 must be number - return new Node(Token.POS, left); - } - } - break; - - case Token.MUL: - // numerical multiplication - if (left.type == Token.NUMBER) { - double ld = left.getDouble(); - if (right.type == Token.NUMBER) { - //both numbers - left.setDouble(ld * right.getDouble()); - return left; - } else if (ld == 1.0) { - // first 1: 1 * x -> +x - return new Node(Token.POS, right); - } - } else if (right.type == Token.NUMBER) { - if (right.getDouble() == 1.0) { - //second 1: x * 1 -> +x - // can not make simply x because x - 0 must be number - return new Node(Token.POS, left); - } - } - // can't do x*0: Infinity * 0 gives NaN, not 0 - break; - - case Token.DIV: - // number division - if (right.type == Token.NUMBER) { - double rd = right.getDouble(); - if (left.type == Token.NUMBER) { - // both constants -- just divide, trust Java to handle x/0 - left.setDouble(left.getDouble() / rd); - return left; - } else if (rd == 1.0) { - // second 1: x/1 -> +x - // not simply x to force number convertion - return new Node(Token.POS, left); - } - } - break; - - case Token.AND: { - // Since x && y gives x, not false, when Boolean(x) is false, - // and y, not Boolean(y), when Boolean(x) is true, x && y - // can only be simplified if x is defined. See bug 309957. - - int leftStatus = isAlwaysDefinedBoolean(left); - if (leftStatus == ALWAYS_FALSE_BOOLEAN) { - // if the first one is false, just return it - return left; - } else if (leftStatus == ALWAYS_TRUE_BOOLEAN) { - // if first is true, set to second - return right; - } - break; - } - - case Token.OR: { - // Since x || y gives x, not true, when Boolean(x) is true, - // and y, not Boolean(y), when Boolean(x) is false, x || y - // can only be simplified if x is defined. See bug 309957. - - int leftStatus = isAlwaysDefinedBoolean(left); - if (leftStatus == ALWAYS_TRUE_BOOLEAN) { - // if the first one is true, just return it - return left; - } else if (leftStatus == ALWAYS_FALSE_BOOLEAN) { - // if first is false, set to second - return right; - } - break; - } - } - - return new Node(nodeType, left, right); - } - - private Node simpleAssignment(Node left, Node right) - { - int nodeType = left.getType(); - switch (nodeType) { - case Token.NAME: - left.setType(Token.BINDNAME); - return new Node(Token.SETNAME, left, right); - - case Token.GETPROP: - case Token.GETELEM: { - Node obj = left.getFirstChild(); - Node id = left.getLastChild(); - int type; - if (nodeType == Token.GETPROP) { - type = Token.SETPROP; - } else { - type = Token.SETELEM; - } - return new Node(type, obj, id, right); - } - case Token.GET_REF: { - Node ref = left.getFirstChild(); - checkMutableReference(ref); - return new Node(Token.SET_REF, ref, right); - } - } - - throw Kit.codeBug(); - } - - private void checkMutableReference(Node n) - { - int memberTypeFlags = n.getIntProp(Node.MEMBER_TYPE_PROP, 0); - if ((memberTypeFlags & Node.DESCENDANTS_FLAG) != 0) { - parser.reportError("msg.bad.assign.left"); - } - } - - Node createAssignment(int assignType, Node left, Node right) - { - Node ref = makeReference(left); - if (ref == null) { - if (left.getType() == Token.ARRAYLIT || - left.getType() == Token.OBJECTLIT) - { - if (assignType != Token.ASSIGN) { - parser.reportError("msg.bad.destruct.op"); - return right; - } - return createDestructuringAssignment(-1, left, right); - } - parser.reportError("msg.bad.assign.left"); - return right; - } - left = ref; - - int assignOp; - switch (assignType) { - case Token.ASSIGN: - return simpleAssignment(left, right); - case Token.ASSIGN_BITOR: assignOp = Token.BITOR; break; - case Token.ASSIGN_BITXOR: assignOp = Token.BITXOR; break; - case Token.ASSIGN_BITAND: assignOp = Token.BITAND; break; - case Token.ASSIGN_LSH: assignOp = Token.LSH; break; - case Token.ASSIGN_RSH: assignOp = Token.RSH; break; - case Token.ASSIGN_URSH: assignOp = Token.URSH; break; - case Token.ASSIGN_ADD: assignOp = Token.ADD; break; - case Token.ASSIGN_SUB: assignOp = Token.SUB; break; - case Token.ASSIGN_MUL: assignOp = Token.MUL; break; - case Token.ASSIGN_DIV: assignOp = Token.DIV; break; - case Token.ASSIGN_MOD: assignOp = Token.MOD; break; - default: throw Kit.codeBug(); - } - - int nodeType = left.getType(); - switch (nodeType) { - case Token.NAME: { - Node op = new Node(assignOp, left, right); - Node lvalueLeft = Node.newString(Token.BINDNAME, left.getString()); - return new Node(Token.SETNAME, lvalueLeft, op); - } - case Token.GETPROP: - case Token.GETELEM: { - Node obj = left.getFirstChild(); - Node id = left.getLastChild(); - - int type = nodeType == Token.GETPROP - ? Token.SETPROP_OP - : Token.SETELEM_OP; - - Node opLeft = new Node(Token.USE_STACK); - Node op = new Node(assignOp, opLeft, right); - return new Node(type, obj, id, op); - } - case Token.GET_REF: { - ref = left.getFirstChild(); - checkMutableReference(ref); - Node opLeft = new Node(Token.USE_STACK); - Node op = new Node(assignOp, opLeft, right); - return new Node(Token.SET_REF_OP, ref, op); - } - } - - throw Kit.codeBug(); - } - - /** - * Given a destructuring assignment with a left hand side parsed - * as an array or object literal and a right hand side expression, - * rewrite as a series of assignments to the variables defined in - * left from property accesses to the expression on the right. - * @param type declaration type: Token.VAR or Token.LET or -1 - * @param left array or object literal containing NAME nodes for - * variables to assign - * @param right expression to assign from - * @return expression that performs a series of assignments to - * the variables defined in left - */ - Node createDestructuringAssignment(int type, Node left, Node right) - { - String tempName = parser.currentScriptOrFn.getNextTempName(); - Node result = destructuringAssignmentHelper(type, left, right, - tempName); - Node comma = result.getLastChild(); - comma.addChildToBack(createName(tempName)); - return result; - } - - private Node destructuringAssignmentHelper(int variableType, Node left, - Node right, String tempName) - { - Node result = createScopeNode(Token.LETEXPR, - parser.getCurrentLineNumber()); - result.addChildToFront(new Node(Token.LET, - createName(Token.NAME, tempName, right))); - try { - parser.pushScope(result); - parser.defineSymbol(Token.LET, tempName); - } finally { - parser.popScope(); - } - Node comma = new Node(Token.COMMA); - result.addChildToBack(comma); - final int setOp = variableType == Token.CONST ? Token.SETCONST - : Token.SETNAME; - List<String> destructuringNames = new ArrayList<String>(); - boolean empty = true; - int type = left.getType(); - if (type == Token.ARRAYLIT) { - int index = 0; - int[] skipIndices = (int[])left.getProp(Node.SKIP_INDEXES_PROP); - int skip = 0; - Node n = left.getFirstChild(); - for (;;) { - if (skipIndices != null) { - while (skip < skipIndices.length && - skipIndices[skip] == index) { - skip++; - index++; - } - } - if (n == null) - break; - Node rightElem = new Node(Token.GETELEM, - createName(tempName), - createNumber(index)); - if (n.getType() == Token.NAME) { - String name = n.getString(); - comma.addChildToBack(new Node(setOp, - createName(Token.BINDNAME, name, null), - rightElem)); - if (variableType != -1) { - parser.defineSymbol(variableType, name); - destructuringNames.add(name); - } - } else { - comma.addChildToBack( - destructuringAssignmentHelper(variableType, n, - rightElem, - parser.currentScriptOrFn.getNextTempName())); - } - index++; - empty = false; - n = n.getNext(); - } - } else if (type == Token.OBJECTLIT) { - int index = 0; - Object[] propertyIds = (Object[]) - left.getProp(Node.OBJECT_IDS_PROP); - for (Node n = left.getFirstChild(); n != null; n = n.getNext()) - { - Object id = propertyIds[index]; - Node rightElem = id instanceof String - ? new Node(Token.GETPROP, - createName(tempName), - createString((String)id)) - : new Node(Token.GETELEM, - createName(tempName), - createNumber(((Number)id).intValue())); - if (n.getType() == Token.NAME) { - String name = n.getString(); - comma.addChildToBack(new Node(setOp, - createName(Token.BINDNAME, name, null), - rightElem)); - if (variableType != -1) { - parser.defineSymbol(variableType, name); - destructuringNames.add(name); - } - } else { - comma.addChildToBack( - destructuringAssignmentHelper(variableType, n, - rightElem, - parser.currentScriptOrFn.getNextTempName())); - } - index++; - empty = false; - } - } else if (type == Token.GETPROP || type == Token.GETELEM) { - comma.addChildToBack(simpleAssignment(left, createName(tempName))); - } else { - parser.reportError("msg.bad.assign.left"); - } - if (empty) { - // Don't want a COMMA node with no children. Just add a zero. - comma.addChildToBack(createNumber(0)); - } - result.putProp(Node.DESTRUCTURING_NAMES, destructuringNames); - return result; - } - - Node createUseLocal(Node localBlock) - { - if (Token.LOCAL_BLOCK != localBlock.getType()) throw Kit.codeBug(); - Node result = new Node(Token.LOCAL_LOAD); - result.putProp(Node.LOCAL_BLOCK_PROP, localBlock); - return result; - } - - private Node.Jump makeJump(int type, Node target) - { - Node.Jump n = new Node.Jump(type); - n.target = target; - return n; - } - - private Node makeReference(Node node) - { - int type = node.getType(); - switch (type) { - case Token.NAME: - case Token.GETPROP: - case Token.GETELEM: - case Token.GET_REF: - return node; - case Token.CALL: - node.setType(Token.REF_CALL); - return new Node(Token.GET_REF, node); - } - // Signal caller to report error - return null; - } - - // Check if Node always mean true or false in boolean context - private static int isAlwaysDefinedBoolean(Node node) - { - switch (node.getType()) { - case Token.FALSE: - case Token.NULL: - return ALWAYS_FALSE_BOOLEAN; - case Token.TRUE: - return ALWAYS_TRUE_BOOLEAN; - case Token.NUMBER: { - double num = node.getDouble(); - if (num == num && num != 0.0) { - return ALWAYS_TRUE_BOOLEAN; - } else { - return ALWAYS_FALSE_BOOLEAN; - } - } - } - return 0; - } - - private void checkActivationName(String name, int token) - { - if (parser.insideFunction()) { - boolean activation = false; - if ("arguments".equals(name) - || (parser.compilerEnv.activationNames != null - && parser.compilerEnv.activationNames.containsKey(name))) - { - activation = true; - } else if ("length".equals(name)) { - if (token == Token.GETPROP - && parser.compilerEnv.getLanguageVersion() - == Context.VERSION_1_2) - { - // Use of "length" in 1.2 requires an activation object. - activation = true; - } - } - if (activation) { - setRequiresActivation(); - } - } - } - - private void setRequiresActivation() - { - if (parser.insideFunction()) { - ((FunctionNode)parser.currentScriptOrFn).itsNeedsActivation = true; - } - } - - private void setIsGenerator() - { - if (parser.insideFunction()) { - ((FunctionNode)parser.currentScriptOrFn).itsIsGenerator = true; - } - } - - private Parser parser; - - private static final int LOOP_DO_WHILE = 0; - private static final int LOOP_WHILE = 1; - private static final int LOOP_FOR = 2; - - private static final int ALWAYS_TRUE_BOOLEAN = 1; - private static final int ALWAYS_FALSE_BOOLEAN = -1; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IdFunctionCall.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IdFunctionCall.java deleted file mode 100644 index 713fabf..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IdFunctionCall.java +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * Master for id-based functions that knows their properties and how to - * execute them. - */ -public interface IdFunctionCall -{ - /** - * 'thisObj' will be null if invoked as constructor, in which case - * instance of Scriptable should be returned - */ - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args); - -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IdFunctionObject.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IdFunctionObject.java deleted file mode 100644 index c578dfa..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IdFunctionObject.java +++ /dev/null @@ -1,189 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -public class IdFunctionObject extends BaseFunction -{ - - static final long serialVersionUID = -5332312783643935019L; - - public IdFunctionObject(IdFunctionCall idcall, Object tag, int id, int arity) - { - if (arity < 0) - throw new IllegalArgumentException(); - - this.idcall = idcall; - this.tag = tag; - this.methodId = id; - this.arity = arity; - if (arity < 0) throw new IllegalArgumentException(); - } - - public IdFunctionObject(IdFunctionCall idcall, Object tag, int id, - String name, int arity, Scriptable scope) - { - super(scope, null); - - if (arity < 0) - throw new IllegalArgumentException(); - if (name == null) - throw new IllegalArgumentException(); - - this.idcall = idcall; - this.tag = tag; - this.methodId = id; - this.arity = arity; - this.functionName = name; - } - - public void initFunction(String name, Scriptable scope) - { - if (name == null) throw new IllegalArgumentException(); - if (scope == null) throw new IllegalArgumentException(); - this.functionName = name; - setParentScope(scope); - } - - public final boolean hasTag(Object tag) - { - return this.tag == tag; - } - - public final int methodId() - { - return methodId; - } - - public final void markAsConstructor(Scriptable prototypeProperty) - { - useCallAsConstructor = true; - setImmunePrototypeProperty(prototypeProperty); - } - - public final void addAsProperty(Scriptable target) - { - ScriptableObject.defineProperty(target, functionName, this, - ScriptableObject.DONTENUM); - } - - public void exportAsScopeProperty() - { - addAsProperty(getParentScope()); - } - - public Scriptable getPrototype() - { - // Lazy initialization of prototype: for native functions this - // may not be called at all - Scriptable proto = super.getPrototype(); - if (proto == null) { - proto = getFunctionPrototype(getParentScope()); - setPrototype(proto); - } - return proto; - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - return idcall.execIdCall(this, cx, scope, thisObj, args); - } - - public Scriptable createObject(Context cx, Scriptable scope) - { - if (useCallAsConstructor) { - return null; - } - // Throw error if not explicitly coded to be used as constructor, - // to satisfy ECMAScript standard (see bugzilla 202019). - // To follow current (2003-05-01) SpiderMonkey behavior, change it to: - // return super.createObject(cx, scope); - throw ScriptRuntime.typeError1("msg.not.ctor", functionName); - } - - String decompile(int indent, int flags) - { - StringBuffer sb = new StringBuffer(); - boolean justbody = (0 != (flags & Decompiler.ONLY_BODY_FLAG)); - if (!justbody) { - sb.append("function "); - sb.append(getFunctionName()); - sb.append("() { "); - } - sb.append("[native code for "); - if (idcall instanceof Scriptable) { - Scriptable sobj = (Scriptable)idcall; - sb.append(sobj.getClassName()); - sb.append('.'); - } - sb.append(getFunctionName()); - sb.append(", arity="); - sb.append(getArity()); - sb.append(justbody ? "]\n" : "] }\n"); - return sb.toString(); - } - - public int getArity() - { - return arity; - } - - public int getLength() { return getArity(); } - - public String getFunctionName() - { - return (functionName == null) ? "" : functionName; - } - - public final RuntimeException unknown() - { - // It is program error to call id-like methods for unknown function - return new IllegalArgumentException( - "BAD FUNCTION ID="+methodId+" MASTER="+idcall); - } - - private final IdFunctionCall idcall; - private final Object tag; - private final int methodId; - private int arity; - private boolean useCallAsConstructor; - private String functionName; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IdScriptableObject.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IdScriptableObject.java deleted file mode 100644 index 2b3ecf3..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/IdScriptableObject.java +++ /dev/null @@ -1,734 +0,0 @@ -/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.*; - -/** -Base class for native object implementation that uses IdFunctionObject to export its methods to script via <class-name>.prototype object. - -Any descendant should implement at least the following methods: - findInstanceIdInfo - getInstanceIdName - execIdCall - methodArity - -To define non-function properties, the descendant should override - getInstanceIdValue - setInstanceIdValue -to get/set property value and provide its default attributes. - - -To customize initializition of constructor and protype objects, descendant -may override scopeInit or fillConstructorProperties methods. - -*/ -public abstract class IdScriptableObject extends ScriptableObject - implements IdFunctionCall -{ - private transient volatile PrototypeValues prototypeValues; - - private static final class PrototypeValues implements Serializable - { - static final long serialVersionUID = 3038645279153854371L; - - private static final int VALUE_SLOT = 0; - private static final int NAME_SLOT = 1; - private static final int SLOT_SPAN = 2; - - private IdScriptableObject obj; - private int maxId; - private volatile Object[] valueArray; - private volatile short[] attributeArray; - private volatile int lastFoundId = 1; - - // The following helps to avoid creation of valueArray during runtime - // initialization for common case of "constructor" property - int constructorId; - private IdFunctionObject constructor; - private short constructorAttrs; - - PrototypeValues(IdScriptableObject obj, int maxId) - { - if (obj == null) throw new IllegalArgumentException(); - if (maxId < 1) throw new IllegalArgumentException(); - this.obj = obj; - this.maxId = maxId; - } - - final int getMaxId() - { - return maxId; - } - - final void initValue(int id, String name, Object value, int attributes) - { - if (!(1 <= id && id <= maxId)) - throw new IllegalArgumentException(); - if (name == null) - throw new IllegalArgumentException(); - if (value == NOT_FOUND) - throw new IllegalArgumentException(); - ScriptableObject.checkValidAttributes(attributes); - if (obj.findPrototypeId(name) != id) - throw new IllegalArgumentException(name); - - if (id == constructorId) { - if (!(value instanceof IdFunctionObject)) { - throw new IllegalArgumentException("consructor should be initialized with IdFunctionObject"); - } - constructor = (IdFunctionObject)value; - constructorAttrs = (short)attributes; - return; - } - - initSlot(id, name, value, attributes); - } - - private void initSlot(int id, String name, Object value, - int attributes) - { - Object[] array = valueArray; - if (array == null) - throw new IllegalStateException(); - - if (value == null) { - value = UniqueTag.NULL_VALUE; - } - int index = (id - 1) * SLOT_SPAN; - synchronized (this) { - Object value2 = array[index + VALUE_SLOT]; - if (value2 == null) { - array[index + VALUE_SLOT] = value; - array[index + NAME_SLOT] = name; - attributeArray[id - 1] = (short)attributes; - } else { - if (!name.equals(array[index + NAME_SLOT])) - throw new IllegalStateException(); - } - } - } - - final IdFunctionObject createPrecachedConstructor() - { - if (constructorId != 0) throw new IllegalStateException(); - constructorId = obj.findPrototypeId("constructor"); - if (constructorId == 0) { - throw new IllegalStateException( - "No id for constructor property"); - } - obj.initPrototypeId(constructorId); - if (constructor == null) { - throw new IllegalStateException( - obj.getClass().getName()+".initPrototypeId() did not " - +"initialize id="+constructorId); - } - constructor.initFunction(obj.getClassName(), - ScriptableObject.getTopLevelScope(obj)); - constructor.markAsConstructor(obj); - return constructor; - } - - final int findId(String name) - { - Object[] array = valueArray; - if (array == null) { - return obj.findPrototypeId(name); - } - int id = lastFoundId; - if (name == array[(id - 1) * SLOT_SPAN + NAME_SLOT]) { - return id; - } - id = obj.findPrototypeId(name); - if (id != 0) { - int nameSlot = (id - 1) * SLOT_SPAN + NAME_SLOT; - // Make cache to work! - array[nameSlot] = name; - lastFoundId = id; - } - return id; - } - - final boolean has(int id) - { - Object[] array = valueArray; - if (array == null) { - // Not yet initialized, assume all exists - return true; - } - int valueSlot = (id - 1) * SLOT_SPAN + VALUE_SLOT; - Object value = array[valueSlot]; - if (value == null) { - // The particular entry has not been yet initialized - return true; - } - return value != NOT_FOUND; - } - - final Object get(int id) - { - Object value = ensureId(id); - if (value == UniqueTag.NULL_VALUE) { - value = null; - } - return value; - } - - final void set(int id, Scriptable start, Object value) - { - if (value == NOT_FOUND) throw new IllegalArgumentException(); - ensureId(id); - int attr = attributeArray[id - 1]; - if ((attr & READONLY) == 0) { - if (start == obj) { - if (value == null) { - value = UniqueTag.NULL_VALUE; - } - int valueSlot = (id - 1) * SLOT_SPAN + VALUE_SLOT; - synchronized (this) { - valueArray[valueSlot] = value; - } - } - else { - int nameSlot = (id - 1) * SLOT_SPAN + NAME_SLOT; - String name = (String)valueArray[nameSlot]; - start.put(name, start, value); - } - } - } - - final void delete(int id) - { - ensureId(id); - int attr = attributeArray[id - 1]; - if ((attr & PERMANENT) == 0) { - int valueSlot = (id - 1) * SLOT_SPAN + VALUE_SLOT; - synchronized (this) { - valueArray[valueSlot] = NOT_FOUND; - attributeArray[id - 1] = EMPTY; - } - } - } - - final int getAttributes(int id) - { - ensureId(id); - return attributeArray[id - 1]; - } - - final void setAttributes(int id, int attributes) - { - ScriptableObject.checkValidAttributes(attributes); - ensureId(id); - synchronized (this) { - attributeArray[id - 1] = (short)attributes; - } - } - - final Object[] getNames(boolean getAll, Object[] extraEntries) - { - Object[] names = null; - int count = 0; - for (int id = 1; id <= maxId; ++id) { - Object value = ensureId(id); - if (getAll || (attributeArray[id - 1] & DONTENUM) == 0) { - if (value != NOT_FOUND) { - int nameSlot = (id - 1) * SLOT_SPAN + NAME_SLOT; - String name = (String)valueArray[nameSlot]; - if (names == null) { - names = new Object[maxId]; - } - names[count++] = name; - } - } - } - if (count == 0) { - return extraEntries; - } else if (extraEntries == null || extraEntries.length == 0) { - if (count != names.length) { - Object[] tmp = new Object[count]; - System.arraycopy(names, 0, tmp, 0, count); - names = tmp; - } - return names; - } else { - int extra = extraEntries.length; - Object[] tmp = new Object[extra + count]; - System.arraycopy(extraEntries, 0, tmp, 0, extra); - System.arraycopy(names, 0, tmp, extra, count); - return tmp; - } - } - - private Object ensureId(int id) - { - Object[] array = valueArray; - if (array == null) { - synchronized (this) { - array = valueArray; - if (array == null) { - array = new Object[maxId * SLOT_SPAN]; - valueArray = array; - attributeArray = new short[maxId]; - } - } - } - int valueSlot = (id - 1) * SLOT_SPAN + VALUE_SLOT; - Object value = array[valueSlot]; - if (value == null) { - if (id == constructorId) { - initSlot(constructorId, "constructor", - constructor, constructorAttrs); - constructor = null; // no need to refer it any longer - } else { - obj.initPrototypeId(id); - } - value = array[valueSlot]; - if (value == null) { - throw new IllegalStateException( - obj.getClass().getName()+".initPrototypeId(int id) " - +"did not initialize id="+id); - } - } - return value; - } - } - - public IdScriptableObject() - { - } - - public IdScriptableObject(Scriptable scope, Scriptable prototype) - { - super(scope, prototype); - } - - protected final Object defaultGet(String name) - { - return super.get(name, this); - } - - protected final void defaultPut(String name, Object value) - { - super.put(name, this, value); - } - - public boolean has(String name, Scriptable start) - { - int info = findInstanceIdInfo(name); - if (info != 0) { - int attr = (info >>> 16); - if ((attr & PERMANENT) != 0) { - return true; - } - int id = (info & 0xFFFF); - return NOT_FOUND != getInstanceIdValue(id); - } - if (prototypeValues != null) { - int id = prototypeValues.findId(name); - if (id != 0) { - return prototypeValues.has(id); - } - } - return super.has(name, start); - } - - public Object get(String name, Scriptable start) - { - int info = findInstanceIdInfo(name); - if (info != 0) { - int id = (info & 0xFFFF); - return getInstanceIdValue(id); - } - if (prototypeValues != null) { - int id = prototypeValues.findId(name); - if (id != 0) { - return prototypeValues.get(id); - } - } - return super.get(name, start); - } - - public void put(String name, Scriptable start, Object value) - { - int info = findInstanceIdInfo(name); - if (info != 0) { - if (start == this && isSealed()) { - throw Context.reportRuntimeError1("msg.modify.sealed", - name); - } - int attr = (info >>> 16); - if ((attr & READONLY) == 0) { - if (start == this) { - int id = (info & 0xFFFF); - setInstanceIdValue(id, value); - } - else { - start.put(name, start, value); - } - } - return; - } - if (prototypeValues != null) { - int id = prototypeValues.findId(name); - if (id != 0) { - if (start == this && isSealed()) { - throw Context.reportRuntimeError1("msg.modify.sealed", - name); - } - prototypeValues.set(id, start, value); - return; - } - } - super.put(name, start, value); - } - - public void delete(String name) - { - int info = findInstanceIdInfo(name); - if (info != 0) { - // Let the super class to throw exceptions for sealed objects - if (!isSealed()) { - int attr = (info >>> 16); - if ((attr & PERMANENT) == 0) { - int id = (info & 0xFFFF); - setInstanceIdValue(id, NOT_FOUND); - } - return; - } - } - if (prototypeValues != null) { - int id = prototypeValues.findId(name); - if (id != 0) { - if (!isSealed()) { - prototypeValues.delete(id); - } - return; - } - } - super.delete(name); - } - - public int getAttributes(String name) - { - int info = findInstanceIdInfo(name); - if (info != 0) { - int attr = (info >>> 16); - return attr; - } - if (prototypeValues != null) { - int id = prototypeValues.findId(name); - if (id != 0) { - return prototypeValues.getAttributes(id); - } - } - return super.getAttributes(name); - } - - public void setAttributes(String name, int attributes) - { - ScriptableObject.checkValidAttributes(attributes); - int info = findInstanceIdInfo(name); - if (info != 0) { - int currentAttributes = (info >>> 16); - if (attributes != currentAttributes) { - throw new RuntimeException( - "Change of attributes for this id is not supported"); - } - return; - } - if (prototypeValues != null) { - int id = prototypeValues.findId(name); - if (id != 0) { - prototypeValues.setAttributes(id, attributes); - return; - } - } - super.setAttributes(name, attributes); - } - - Object[] getIds(boolean getAll) - { - Object[] result = super.getIds(getAll); - - if (prototypeValues != null) { - result = prototypeValues.getNames(getAll, result); - } - - int maxInstanceId = getMaxInstanceId(); - if (maxInstanceId != 0) { - Object[] ids = null; - int count = 0; - - for (int id = maxInstanceId; id != 0; --id) { - String name = getInstanceIdName(id); - int info = findInstanceIdInfo(name); - if (info != 0) { - int attr = (info >>> 16); - if ((attr & PERMANENT) == 0) { - if (NOT_FOUND == getInstanceIdValue(id)) { - continue; - } - } - if (getAll || (attr & DONTENUM) == 0) { - if (count == 0) { - // Need extra room for no more then [1..id] names - ids = new Object[id]; - } - ids[count++] = name; - } - } - } - if (count != 0) { - if (result.length == 0 && ids.length == count) { - result = ids; - } - else { - Object[] tmp = new Object[result.length + count]; - System.arraycopy(result, 0, tmp, 0, result.length); - System.arraycopy(ids, 0, tmp, result.length, count); - result = tmp; - } - } - } - return result; - } - - /** - * Get maximum id findInstanceIdInfo can generate. - */ - protected int getMaxInstanceId() - { - return 0; - } - - protected static int instanceIdInfo(int attributes, int id) - { - return (attributes << 16) | id; - } - - /** - * Map name to id of instance property. - * Should return 0 if not found or the result of - * {@link #instanceIdInfo(int, int)}. - */ - protected int findInstanceIdInfo(String name) - { - return 0; - } - - /** Map id back to property name it defines. - */ - protected String getInstanceIdName(int id) - { - throw new IllegalArgumentException(String.valueOf(id)); - } - - /** Get id value. - ** If id value is constant, descendant can call cacheIdValue to store - ** value in the permanent cache. - ** Default implementation creates IdFunctionObject instance for given id - ** and cache its value - */ - protected Object getInstanceIdValue(int id) - { - throw new IllegalStateException(String.valueOf(id)); - } - - /** - * Set or delete id value. If value == NOT_FOUND , the implementation - * should make sure that the following getInstanceIdValue return NOT_FOUND. - */ - protected void setInstanceIdValue(int id, Object value) - { - throw new IllegalStateException(String.valueOf(id)); - } - - /** 'thisObj' will be null if invoked as constructor, in which case - ** instance of Scriptable should be returned. */ - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - throw f.unknown(); - } - - public final IdFunctionObject exportAsJSClass(int maxPrototypeId, - Scriptable scope, - boolean sealed) - { - // Set scope and prototype unless this is top level scope itself - if (scope != this && scope != null) { - setParentScope(scope); - setPrototype(getObjectPrototype(scope)); - } - - activatePrototypeMap(maxPrototypeId); - IdFunctionObject ctor = prototypeValues.createPrecachedConstructor(); - if (sealed) { - sealObject(); - } - fillConstructorProperties(ctor); - if (sealed) { - ctor.sealObject(); - } - ctor.exportAsScopeProperty(); - return ctor; - } - - public final boolean hasPrototypeMap() - { - return prototypeValues != null; - } - - public final void activatePrototypeMap(int maxPrototypeId) - { - PrototypeValues values = new PrototypeValues(this, maxPrototypeId); - synchronized (this) { - if (prototypeValues != null) - throw new IllegalStateException(); - prototypeValues = values; - } - } - - public final void initPrototypeMethod(Object tag, int id, String name, - int arity) - { - Scriptable scope = ScriptableObject.getTopLevelScope(this); - IdFunctionObject f = newIdFunction(tag, id, name, arity, scope); - prototypeValues.initValue(id, name, f, DONTENUM); - } - - public final void initPrototypeConstructor(IdFunctionObject f) - { - int id = prototypeValues.constructorId; - if (id == 0) - throw new IllegalStateException(); - if (f.methodId() != id) - throw new IllegalArgumentException(); - if (isSealed()) { f.sealObject(); } - prototypeValues.initValue(id, "constructor", f, DONTENUM); - } - - public final void initPrototypeValue(int id, String name, Object value, - int attributes) - { - prototypeValues.initValue(id, name, value, attributes); - } - - protected void initPrototypeId(int id) - { - throw new IllegalStateException(String.valueOf(id)); - } - - protected int findPrototypeId(String name) - { - throw new IllegalStateException(name); - } - - protected void fillConstructorProperties(IdFunctionObject ctor) - { - } - - protected void addIdFunctionProperty(Scriptable obj, Object tag, int id, - String name, int arity) - { - Scriptable scope = ScriptableObject.getTopLevelScope(obj); - IdFunctionObject f = newIdFunction(tag, id, name, arity, scope); - f.addAsProperty(obj); - } - - /** - * Utility method to construct type error to indicate incompatible call - * when converting script thisObj to a particular type is not possible. - * Possible usage would be to have a private function like realThis: - * <pre> - * private static NativeSomething realThis(Scriptable thisObj, - * IdFunctionObject f) - * { - * if (!(thisObj instanceof NativeSomething)) - * throw incompatibleCallError(f); - * return (NativeSomething)thisObj; - * } - * </pre> - * Note that although such function can be implemented universally via - * java.lang.Class.isInstance(), it would be much more slower. - * @param f function that is attempting to convert 'this' - * object. - * @return Scriptable object suitable for a check by the instanceof - * operator. - * @throws RuntimeException if no more instanceof target can be found - */ - protected static EcmaError incompatibleCallError(IdFunctionObject f) - { - throw ScriptRuntime.typeError1("msg.incompat.call", - f.getFunctionName()); - } - - private IdFunctionObject newIdFunction(Object tag, int id, String name, - int arity, Scriptable scope) - { - IdFunctionObject f = new IdFunctionObject(this, tag, id, name, arity, - scope); - if (isSealed()) { f.sealObject(); } - return f; - } - - private void readObject(ObjectInputStream stream) - throws IOException, ClassNotFoundException - { - stream.defaultReadObject(); - int maxPrototypeId = stream.readInt(); - if (maxPrototypeId != 0) { - activatePrototypeMap(maxPrototypeId); - } - } - - private void writeObject(ObjectOutputStream stream) - throws IOException - { - stream.defaultWriteObject(); - int maxPrototypeId = 0; - if (prototypeValues != null) { - maxPrototypeId = prototypeValues.getMaxId(); - } - stream.writeInt(maxPrototypeId); - } - -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ImporterTopLevel.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ImporterTopLevel.java deleted file mode 100644 index 294deab..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ImporterTopLevel.java +++ /dev/null @@ -1,318 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Matthias Radestock - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * Class ImporterTopLevel - * - * This class defines a ScriptableObject that can be instantiated - * as a top-level ("global") object to provide functionality similar - * to Java's "import" statement. - * <p> - * This class can be used to create a top-level scope using the following code: - * <pre> - * Scriptable scope = new ImporterTopLevel(cx); - * </pre> - * Then JavaScript code will have access to the following methods: - * <ul> - * <li>importClass - will "import" a class by making its unqualified name - * available as a property of the top-level scope - * <li>importPackage - will "import" all the classes of the package by - * searching for unqualified names as classes qualified - * by the given package. - * </ul> - * The following code from the shell illustrates this use: - * <pre> - * js> importClass(java.io.File) - * js> f = new File('help.txt') - * help.txt - * js> importPackage(java.util) - * js> v = new Vector() - * [] - * - * @author Norris Boyd - */ -public class ImporterTopLevel extends IdScriptableObject -{ - static final long serialVersionUID = -9095380847465315412L; - - private static final Object IMPORTER_TAG = new Object(); - - public ImporterTopLevel() { } - - public ImporterTopLevel(Context cx) { - this(cx, false); - } - - public ImporterTopLevel(Context cx, boolean sealed) - { - initStandardObjects(cx, sealed); - } - - public String getClassName() - { - return (topScopeFlag) ? "global" : "JavaImporter"; - } - - public static void init(Context cx, Scriptable scope, boolean sealed) - { - ImporterTopLevel obj = new ImporterTopLevel(); - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - public void initStandardObjects(Context cx, boolean sealed) - { - // Assume that Context.initStandardObjects initialize JavaImporter - // property lazily so the above init call is not yet called - cx.initStandardObjects(this, sealed); - topScopeFlag = true; - // If seal is true then exportAsJSClass(cx, seal) would seal - // this obj. Since this is scope as well, it would not allow - // to add variables. - IdFunctionObject ctor = exportAsJSClass(MAX_PROTOTYPE_ID, this, false); - if (sealed) { - ctor.sealObject(); - } - // delete "constructor" defined by exportAsJSClass so "constructor" - // name would refer to Object.constructor - // and not to JavaImporter.prototype.constructor. - delete("constructor"); - } - - public boolean has(String name, Scriptable start) { - return super.has(name, start) - || getPackageProperty(name, start) != NOT_FOUND; - } - - public Object get(String name, Scriptable start) { - Object result = super.get(name, start); - if (result != NOT_FOUND) - return result; - result = getPackageProperty(name, start); - return result; - } - - private Object getPackageProperty(String name, Scriptable start) { - Object result = NOT_FOUND; - Object[] elements; - synchronized (importedPackages) { - elements = importedPackages.toArray(); - } - for (int i=0; i < elements.length; i++) { - NativeJavaPackage p = (NativeJavaPackage) elements[i]; - Object v = p.getPkgProperty(name, start, false); - if (v != null && !(v instanceof NativeJavaPackage)) { - if (result == NOT_FOUND) { - result = v; - } else { - throw Context.reportRuntimeError2( - "msg.ambig.import", result.toString(), v.toString()); - } - } - } - return result; - } - - /** - * @deprecated Kept only for compatibility. - */ - public void importPackage(Context cx, Scriptable thisObj, Object[] args, - Function funObj) - { - js_importPackage(args); - } - - private Object js_construct(Scriptable scope, Object[] args) - { - ImporterTopLevel result = new ImporterTopLevel(); - for (int i = 0; i != args.length; ++i) { - Object arg = args[i]; - if (arg instanceof NativeJavaClass) { - result.importClass((NativeJavaClass)arg); - } else if (arg instanceof NativeJavaPackage) { - result.importPackage((NativeJavaPackage)arg); - } else { - throw Context.reportRuntimeError1( - "msg.not.class.not.pkg", Context.toString(arg)); - } - } - // set explicitly prototype and scope - // as otherwise in top scope mode BaseFunction.construct - // would keep them set to null. It also allow to use - // JavaImporter without new and still get properly - // initialized object. - result.setParentScope(scope); - result.setPrototype(this); - return result; - } - - private Object js_importClass(Object[] args) - { - for (int i = 0; i != args.length; i++) { - Object arg = args[i]; - if (!(arg instanceof NativeJavaClass)) { - throw Context.reportRuntimeError1( - "msg.not.class", Context.toString(arg)); - } - importClass((NativeJavaClass)arg); - } - return Undefined.instance; - } - - private Object js_importPackage(Object[] args) - { - for (int i = 0; i != args.length; i++) { - Object arg = args[i]; - if (!(arg instanceof NativeJavaPackage)) { - throw Context.reportRuntimeError1( - "msg.not.pkg", Context.toString(arg)); - } - importPackage((NativeJavaPackage)arg); - } - return Undefined.instance; - } - - private void importPackage(NativeJavaPackage pkg) - { - if(pkg == null) { - return; - } - synchronized (importedPackages) { - for (int j = 0; j != importedPackages.size(); j++) { - if (pkg.equals(importedPackages.get(j))) { - return; - } - } - importedPackages.add(pkg); - } - } - - private void importClass(NativeJavaClass cl) - { - String s = cl.getClassObject().getName(); - String n = s.substring(s.lastIndexOf('.')+1); - Object val = get(n, this); - if (val != NOT_FOUND && val != cl) { - throw Context.reportRuntimeError1("msg.prop.defined", n); - } - //defineProperty(n, cl, DONTENUM); - put(n, this, cl); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=0; s="constructor"; break; - case Id_importClass: arity=1; s="importClass"; break; - case Id_importPackage: arity=1; s="importPackage"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(IMPORTER_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(IMPORTER_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case Id_constructor: - return js_construct(scope, args); - - case Id_importClass: - return realThis(thisObj, f).js_importClass(args); - - case Id_importPackage: - return realThis(thisObj, f).js_importPackage(args); - } - throw new IllegalArgumentException(String.valueOf(id)); - } - - private ImporterTopLevel realThis(Scriptable thisObj, IdFunctionObject f) - { - if (topScopeFlag) { - // when used as top scope importPackage and importClass are global - // function that ignore thisObj - return this; - } - if (!(thisObj instanceof ImporterTopLevel)) - throw incompatibleCallError(f); - return (ImporterTopLevel)thisObj; - } - -// #string_id_map# - - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:15:24 EDT - L0: { id = 0; String X = null; int c; - int s_length = s.length(); - if (s_length==11) { - c=s.charAt(0); - if (c=='c') { X="constructor";id=Id_constructor; } - else if (c=='i') { X="importClass";id=Id_importClass; } - } - else if (s_length==13) { X="importPackage";id=Id_importPackage; } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_constructor = 1, - Id_importClass = 2, - Id_importPackage = 3, - MAX_PROTOTYPE_ID = 3; - -// #/string_id_map# - - private ObjArray importedPackages = new ObjArray(); - private boolean topScopeFlag; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InformativeParser.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InformativeParser.java deleted file mode 100644 index c73db34..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InformativeParser.java +++ /dev/null @@ -1,225 +0,0 @@ -package org.mozilla.javascript; - -import java.io.IOException; - -/** - * Subclass of Rhino's Parser that saves information about the token stream - * and error message to allow more helpful error messages. - * - * @author David Greenspan for AppJet - */ - -/* - This class is written with speed in mind, to some extent. Rhino's tokenizer - is pretty efficient, and we wouldn't want to slow it down by, for example, - creating a TokenInfo object on the heap for every token seen. - */ - -/*APPJET*/ -public class InformativeParser extends Parser { - - public static class InformativeEvaluatorException extends EvaluatorException { - final ParseErrorInfo pei; - - InformativeEvaluatorException(String errorMessage, - String sourceName, int lineNumber, - String lineSource, int columnNumber, - ParseErrorInfo peInfo) { - super(errorMessage, sourceName, - lineNumber, lineSource, columnNumber); - pei = peInfo; - } - - public ParseErrorInfo getParseErrorInfo() { - return pei; - } - } - - public static class ParseErrorInfo { - ParseErrorInfo() {} - - String messageId = null; - String messageArg = null; - - final int tokenMaxHistory = 10; - // ring buffers - final int[] tokenTypes = new int[tokenMaxHistory]; - final String[] tokenStrings = new String[tokenMaxHistory]; - final double[] tokenNumbers = new double[tokenMaxHistory]; - final int[] tokenLineNumbers = new int[tokenMaxHistory]; - final int[] tokenLineOffsets = new int[tokenMaxHistory]; - int nextBufPos = 0; - int historyLength = 0; - boolean tokenPeeking = false; - int peekSlot; - - void reportPeekToken(int type, String str, double num, int lineno, - int lineOffset) { - if (! tokenPeeking) { - peekSlot = nextBufPos; - tokenTypes[nextBufPos] = type; - tokenStrings[nextBufPos] = str; - tokenNumbers[nextBufPos] = num; - tokenLineNumbers[nextBufPos] = lineno; - tokenLineOffsets[nextBufPos] = lineOffset; - - nextBufPos++; - if (nextBufPos == tokenMaxHistory) nextBufPos = 0; - if (historyLength < tokenMaxHistory) historyLength++; - tokenPeeking = true; - } - } - - void reportConsumeToken() { - tokenPeeking = false; - } - - private TokenInfo backToken(int n) { - // 0 is most recent token added to history - if (n >= historyLength) return null; - int i = (nextBufPos - 1 - n); - while (i < 0) i += tokenMaxHistory; - return new TokenInfo(tokenTypes[i], tokenStrings[i], - tokenNumbers[i], tokenLineNumbers[i], - tokenLineOffsets[i]); - } - - public String getMessageId() { return messageId; } - public String getMessageArg() { return messageArg; } - public TokenInfo getPeekToken() { - if (tokenPeeking) return backToken(0); - return null; - } - public TokenInfo getPrevToken(int n) { - // 1 = last non-peek token seen, 2 = before that, etc. - if (! tokenPeeking) n--; - return backToken(n); - } - public TokenInfo getPrevToken() { - return getPrevToken(1); - } - } - - public static class TokenInfo { - private int type, lineno, lineOffset; - private String str; - private double num; - TokenInfo(int type, String str, double num, int lineno, - int lineOffset) { - this.type = type; this.str = str; this.num = num; - this.lineno = lineno; this.lineOffset = lineOffset; - } - public int getType() { return type; } - public int getLineNumber() { return lineno; } - public int getLineOffset() { return lineOffset; } - public double getNumber() { return num; } - public String getString() { return str; } - } - - ParseErrorInfo info = new ParseErrorInfo(); - - void doErrorReporterError(String message, String sourceURI, int line, - String lineText, int lineOffset) { - - throw new InformativeEvaluatorException(message, sourceURI, line, - lineText, lineOffset, info); - - } - - public InformativeParser(CompilerEnvirons compilerEnv) { - // we override most calls to the parent's ErrorReporter anyway - super(compilerEnv, DefaultErrorReporter.instance); - } - - @Override int peekToken() throws IOException { - int tt = super.peekToken(); - info.reportPeekToken(tt, ts.getString(), ts.getNumber(), - ts.getLineno(), ts.getOffset()); - return tt; - } - @Override void consumeToken() { - super.consumeToken(); - info.reportConsumeToken(); - } - - @Override void addWarning(String messageId, String messageArg) - { - info.messageId = messageId; - info.messageArg = messageArg; - - String message = ScriptRuntime.getMessage1(messageId, messageArg); - if (compilerEnv.reportWarningAsError()) { - ++syntaxErrorCount; - doErrorReporterError(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } - else { /* don't report */ } - } - - @Override void addError(String messageId) - { - info.messageId = messageId; - - ++syntaxErrorCount; - String message = ScriptRuntime.getMessage0(messageId); - doErrorReporterError(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } - - @Override void addError(String messageId, String messageArg) - { - info.messageId = messageId; - info.messageArg = messageArg; - - ++syntaxErrorCount; - String message = ScriptRuntime.getMessage1(messageId, messageArg); - doErrorReporterError(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } - - @Override protected Decompiler createDecompiler(CompilerEnvirons env) { - return new MyDecompiler(); - } - - public static final ErrorReporter THROW_INFORMATIVE_ERRORS - = new ErrorReporter() { - public void warning(String message, String sourceURI, int line, - String lineText, int lineOffset) { - DefaultErrorReporter.instance.warning - (message, sourceURI, line, lineText, lineOffset); - } - public void error(String message, String sourceURI, int line, - String lineText, int lineOffset) { - DefaultErrorReporter.instance.error - (message, sourceURI, line, lineText, lineOffset); - } - public EvaluatorException runtimeError(String message, - String sourceURI, - int line, String lineText, - int lineOffset) { - return DefaultErrorReporter.instance.runtimeError - (message, sourceURI, line, lineText, lineOffset); - } - - }; - - public static Parser makeParser(CompilerEnvirons compilerEnv, - ErrorReporter errorReporter) { - if (errorReporter == THROW_INFORMATIVE_ERRORS) { - return new InformativeParser(compilerEnv); - } - else { - return new Parser(compilerEnv, errorReporter); - } - } - - private class MyDecompiler extends Decompiler { - @Override void addRegexp(String regexp, String flags) { - super.addRegexp(regexp, flags); - String str = '/'+regexp+'/'+flags; - info.reportPeekToken(Token.REGEXP, str, ts.getNumber(), - ts.getLineno(), ts.getOffset()); - info.reportConsumeToken(); - } - } -}
\ No newline at end of file diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterfaceAdapter.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterfaceAdapter.java deleted file mode 100644 index 877e6a2..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterfaceAdapter.java +++ /dev/null @@ -1,156 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.lang.reflect.Method; - -/** - * Adapter to use JS function as implementation of Java interfaces with - * single method or multiple methods with the same signature. - */ -public class InterfaceAdapter -{ - private final Object proxyHelper; - - /** - * Make glue object implementing interface cl that will - * call the supplied JS function when called. - * Only interfaces were all methods have the same signature is supported. - * - * @return The glue object or null if <tt>cl</tt> is not interface or - * has methods with different signatures. - */ - static Object create(Context cx, Class cl, Callable function) - { - if (!cl.isInterface()) throw new IllegalArgumentException(); - - Scriptable topScope = ScriptRuntime.getTopCallScope(cx); - ClassCache cache = ClassCache.get(topScope); - InterfaceAdapter adapter; - adapter = (InterfaceAdapter)cache.getInterfaceAdapter(cl); - ContextFactory cf = cx.getFactory(); - if (adapter == null) { - Method[] methods = cl.getMethods(); - if (methods.length == 0) { - throw Context.reportRuntimeError2( - "msg.no.empty.interface.conversion", - String.valueOf(function), - cl.getClass().getName()); - } - boolean canCallFunction = false; - canCallFunctionChecks: { - Class[] argTypes = methods[0].getParameterTypes(); - // check that the rest of methods has the same signature - for (int i = 1; i != methods.length; ++i) { - Class[] types2 = methods[i].getParameterTypes(); - if (types2.length != argTypes.length) { - break canCallFunctionChecks; - } - for (int j = 0; j != argTypes.length; ++j) { - if (types2[j] != argTypes[j]) { - break canCallFunctionChecks; - } - } - } - canCallFunction= true; - } - if (!canCallFunction) { - throw Context.reportRuntimeError2( - "msg.no.function.interface.conversion", - String.valueOf(function), - cl.getClass().getName()); - } - adapter = new InterfaceAdapter(cf, cl); - cache.cacheInterfaceAdapter(cl, adapter); - } - return VMBridge.instance.newInterfaceProxy( - adapter.proxyHelper, cf, adapter, function, topScope); - } - - private InterfaceAdapter(ContextFactory cf, Class cl) - { - this.proxyHelper - = VMBridge.instance.getInterfaceProxyHelper( - cf, new Class[] { cl }); - } - - public Object invoke(ContextFactory cf, - final Object target, - final Scriptable topScope, - final Method method, - final Object[] args) - { - ContextAction action = new ContextAction() { - public Object run(Context cx) - { - return invokeImpl(cx, target, topScope, method, args); - } - }; - return cf.call(action); - } - - Object invokeImpl(Context cx, - Object target, - Scriptable topScope, - Method method, - Object[] args) - { - int N = (args == null) ? 0 : args.length; - - Callable function = (Callable)target; - Scriptable thisObj = topScope; - Object[] jsargs = new Object[N + 1]; - jsargs[N] = method.getName(); - if (N != 0) { - WrapFactory wf = cx.getWrapFactory(); - for (int i = 0; i != N; ++i) { - jsargs[i] = wf.wrap(cx, topScope, args[i], null); - } - } - - Object result = function.call(cx, topScope, thisObj, jsargs); - Class javaResultType = method.getReturnType(); - if (javaResultType == Void.TYPE) { - result = null; - } else { - result = Context.jsToJava(result, javaResultType); - } - return result; - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterpretedFunction.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterpretedFunction.java deleted file mode 100644 index db84299..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterpretedFunction.java +++ /dev/null @@ -1,221 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * Bob Jervis - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import org.mozilla.javascript.debug.DebuggableScript; - -final class InterpretedFunction extends NativeFunction implements Script -{ - static final long serialVersionUID = 541475680333911468L; - - InterpreterData idata; - SecurityController securityController; - Object securityDomain; - Scriptable[] functionRegExps; - - private InterpretedFunction(InterpreterData idata, - Object staticSecurityDomain) - { - this.idata = idata; - - // Always get Context from the current thread to - // avoid security breaches via passing mangled Context instances - // with bogus SecurityController - Context cx = Context.getContext(); - SecurityController sc = cx.getSecurityController(); - Object dynamicDomain; - if (sc != null) { - dynamicDomain = sc.getDynamicSecurityDomain(staticSecurityDomain); - } else { - if (staticSecurityDomain != null) { - throw new IllegalArgumentException(); - } - dynamicDomain = null; - } - - this.securityController = sc; - this.securityDomain = dynamicDomain; - } - - private InterpretedFunction(InterpretedFunction parent, int index) - { - this.idata = parent.idata.itsNestedFunctions[index]; - this.securityController = parent.securityController; - this.securityDomain = parent.securityDomain; - } - - /** - * Create script from compiled bytecode. - */ - static InterpretedFunction createScript(InterpreterData idata, - Object staticSecurityDomain) - { - InterpretedFunction f; - f = new InterpretedFunction(idata, staticSecurityDomain); - return f; - } - - /** - * Create function compiled from Function(...) constructor. - */ - static InterpretedFunction createFunction(Context cx,Scriptable scope, - InterpreterData idata, - Object staticSecurityDomain) - { - InterpretedFunction f; - f = new InterpretedFunction(idata, staticSecurityDomain); - f.initInterpretedFunction(cx, scope); - return f; - } - - /** - * Create function embedded in script or another function. - */ - static InterpretedFunction createFunction(Context cx, Scriptable scope, - InterpretedFunction parent, - int index) - { - InterpretedFunction f = new InterpretedFunction(parent, index); - f.initInterpretedFunction(cx, scope); - return f; - } - - Scriptable[] createRegExpWraps(Context cx, Scriptable scope) - { - if (idata.itsRegExpLiterals == null) Kit.codeBug(); - - RegExpProxy rep = ScriptRuntime.checkRegExpProxy(cx); - int N = idata.itsRegExpLiterals.length; - Scriptable[] array = new Scriptable[N]; - for (int i = 0; i != N; ++i) { - array[i] = rep.wrapRegExp(cx, scope, idata.itsRegExpLiterals[i]); - } - return array; - } - - private void initInterpretedFunction(Context cx, Scriptable scope) - { - initScriptFunction(cx, scope); - if (idata.itsRegExpLiterals != null) { - functionRegExps = createRegExpWraps(cx, scope); - } - } - - public String getFunctionName() - { - return (idata.itsName == null) ? "" : idata.itsName; - } - - /** - * Calls the function. - * @param cx the current context - * @param scope the scope used for the call - * @param thisObj the value of "this" - * @param args function arguments. Must not be null. You can use - * {@link ScriptRuntime#emptyArgs} to pass empty arguments. - * @return the result of the function call. - */ - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - if (!ScriptRuntime.hasTopCall(cx)) { - return ScriptRuntime.doTopCall(this, cx, scope, thisObj, args); - } - return Interpreter.interpret(this, cx, scope, thisObj, args); - } - - public Object exec(Context cx, Scriptable scope) - { - if (idata.itsFunctionType != 0) { - // Can only be applied to scripts - throw new IllegalStateException(); - } - if (!ScriptRuntime.hasTopCall(cx)) { - // It will go through "call" path. but they are equivalent - return ScriptRuntime.doTopCall( - this, cx, scope, scope, ScriptRuntime.emptyArgs); - } - return Interpreter.interpret( - this, cx, scope, scope, ScriptRuntime.emptyArgs); - } - - public String getEncodedSource() - { - return Interpreter.getEncodedSource(idata); - } - - public DebuggableScript getDebuggableView() - { - return idata; - } - - public Object resumeGenerator(Context cx, Scriptable scope, int operation, - Object state, Object value) - { - return Interpreter.resumeGenerator(cx, scope, operation, state, value); - } - - protected int getLanguageVersion() - { - return idata.languageVersion; - } - - protected int getParamCount() - { - return idata.argCount; - } - - protected int getParamAndVarCount() - { - return idata.argNames.length; - } - - protected String getParamOrVarName(int index) - { - return idata.argNames[index]; - } - - protected boolean getParamOrVarConst(int index) - { - return idata.argIsConst[index]; - } -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Interpreter.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Interpreter.java deleted file mode 100644 index a68c025..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Interpreter.java +++ /dev/null @@ -1,4643 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Patrick Beard - * Norris Boyd - * Igor Bukanov - * Ethan Hugg - * Bob Jervis - * Terry Lucas - * Roger Lawrence - * Milen Nankov - * Hannes Wallnoefer - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.PrintStream; -import java.io.Serializable; -import java.util.List; -import java.util.ArrayList; - -import org.mozilla.javascript.continuations.Continuation; -import org.mozilla.javascript.debug.DebugFrame; - -public class Interpreter implements Evaluator -{ - -// Additional interpreter-specific codes - - private static final int - - // Stack: ... value1 -> ... value1 value1 - Icode_DUP = -1, - - // Stack: ... value2 value1 -> ... value2 value1 value2 value1 - Icode_DUP2 = -2, - - // Stack: ... value2 value1 -> ... value1 value2 - Icode_SWAP = -3, - - // Stack: ... value1 -> ... - Icode_POP = -4, - - // Store stack top into return register and then pop it - Icode_POP_RESULT = -5, - - // To jump conditionally and pop additional stack value - Icode_IFEQ_POP = -6, - - // various types of ++/-- - Icode_VAR_INC_DEC = -7, - Icode_NAME_INC_DEC = -8, - Icode_PROP_INC_DEC = -9, - Icode_ELEM_INC_DEC = -10, - Icode_REF_INC_DEC = -11, - - // load/save scope from/to local - Icode_SCOPE_LOAD = -12, - Icode_SCOPE_SAVE = -13, - - Icode_TYPEOFNAME = -14, - - // helper for function calls - Icode_NAME_AND_THIS = -15, - Icode_PROP_AND_THIS = -16, - Icode_ELEM_AND_THIS = -17, - Icode_VALUE_AND_THIS = -18, - - // Create closure object for nested functions - Icode_CLOSURE_EXPR = -19, - Icode_CLOSURE_STMT = -20, - - // Special calls - Icode_CALLSPECIAL = -21, - - // To return undefined value - Icode_RETUNDEF = -22, - - // Exception handling implementation - Icode_GOSUB = -23, - Icode_STARTSUB = -24, - Icode_RETSUB = -25, - - // To indicating a line number change in icodes. - Icode_LINE = -26, - - // To store shorts and ints inline - Icode_SHORTNUMBER = -27, - Icode_INTNUMBER = -28, - - // To create and populate array to hold values for [] and {} literals - Icode_LITERAL_NEW = -29, - Icode_LITERAL_SET = -30, - - // Array literal with skipped index like [1,,2] - Icode_SPARE_ARRAYLIT = -31, - - // Load index register to prepare for the following index operation - Icode_REG_IND_C0 = -32, - Icode_REG_IND_C1 = -33, - Icode_REG_IND_C2 = -34, - Icode_REG_IND_C3 = -35, - Icode_REG_IND_C4 = -36, - Icode_REG_IND_C5 = -37, - Icode_REG_IND1 = -38, - Icode_REG_IND2 = -39, - Icode_REG_IND4 = -40, - - // Load string register to prepare for the following string operation - Icode_REG_STR_C0 = -41, - Icode_REG_STR_C1 = -42, - Icode_REG_STR_C2 = -43, - Icode_REG_STR_C3 = -44, - Icode_REG_STR1 = -45, - Icode_REG_STR2 = -46, - Icode_REG_STR4 = -47, - - // Version of getvar/setvar that read var index directly from bytecode - Icode_GETVAR1 = -48, - Icode_SETVAR1 = -49, - - // Load unefined - Icode_UNDEF = -50, - Icode_ZERO = -51, - Icode_ONE = -52, - - // entrance and exit from .() - Icode_ENTERDQ = -53, - Icode_LEAVEDQ = -54, - - Icode_TAIL_CALL = -55, - - // Clear local to allow GC its context - Icode_LOCAL_CLEAR = -56, - - // Literal get/set - Icode_LITERAL_GETTER = -57, - Icode_LITERAL_SETTER = -58, - - // const - Icode_SETCONST = -59, - Icode_SETCONSTVAR = -60, - Icode_SETCONSTVAR1 = -61, - - // Generator opcodes (along with Token.YIELD) - Icode_GENERATOR = -62, - Icode_GENERATOR_END = -63, - - Icode_DEBUGGER = -64, - - // Last icode - MIN_ICODE = -64; - - // data for parsing - - private CompilerEnvirons compilerEnv; - - private boolean itsInFunctionFlag; - private boolean itsInTryFlag; - - private InterpreterData itsData; - private ScriptOrFnNode scriptOrFn; - private int itsICodeTop; - private int itsStackDepth; - private int itsLineNumber; - private int itsDoubleTableTop; - private ObjToIntMap itsStrings = new ObjToIntMap(20); - private int itsLocalTop; - - private static final int MIN_LABEL_TABLE_SIZE = 32; - private static final int MIN_FIXUP_TABLE_SIZE = 40; - private int[] itsLabelTable; - private int itsLabelTableTop; -// itsFixupTable[i] = (label_index << 32) | fixup_site - private long[] itsFixupTable; - private int itsFixupTableTop; - private ObjArray itsLiteralIds = new ObjArray(); - - private int itsExceptionTableTop; - private static final int EXCEPTION_TRY_START_SLOT = 0; - private static final int EXCEPTION_TRY_END_SLOT = 1; - private static final int EXCEPTION_HANDLER_SLOT = 2; - private static final int EXCEPTION_TYPE_SLOT = 3; - private static final int EXCEPTION_LOCAL_SLOT = 4; - private static final int EXCEPTION_SCOPE_SLOT = 5; - // SLOT_SIZE: space for try start/end, handler, start, handler type, - // exception local and scope local - private static final int EXCEPTION_SLOT_SIZE = 6; - -// ECF_ or Expression Context Flags constants: for now only TAIL is available - private static final int ECF_TAIL = 1 << 0; - - /** - * Class to hold data corresponding to one interpreted call stack frame. - */ - private static class CallFrame implements Cloneable, Serializable - { - static final long serialVersionUID = -2843792508994958978L; - - CallFrame parentFrame; - // amount of stack frames before this one on the interpretation stack - int frameIndex; - // If true indicates read-only frame that is a part of continuation - boolean frozen; - - InterpretedFunction fnOrScript; - InterpreterData idata; - -// Stack structure -// stack[0 <= i < localShift]: arguments and local variables -// stack[localShift <= i <= emptyStackTop]: used for local temporaries -// stack[emptyStackTop < i < stack.length]: stack data -// sDbl[i]: if stack[i] is UniqueTag.DOUBLE_MARK, sDbl[i] holds the number value - - Object[] stack; - int[] stackAttributes; - double[] sDbl; - CallFrame varSource; // defaults to this unless continuation frame - int localShift; - int emptyStackTop; - - DebugFrame debuggerFrame; - boolean useActivation; - - Scriptable thisObj; - Scriptable[] scriptRegExps; - -// The values that change during interpretation - - Object result; - double resultDbl; - int pc; - int pcPrevBranch; - int pcSourceLineStart; - Scriptable scope; - - int savedStackTop; - int savedCallOp; - Object throwable; - - CallFrame cloneFrozen() - { - if (!frozen) Kit.codeBug(); - - CallFrame copy; - try { - copy = (CallFrame)clone(); - } catch (CloneNotSupportedException ex) { - throw new IllegalStateException(); - } - - // clone stack but keep varSource to point to values - // from this frame to share variables. - - copy.stack = stack.clone(); - copy.stackAttributes = stackAttributes.clone(); - copy.sDbl = sDbl.clone(); - - copy.frozen = false; - return copy; - } - } - - private static final class ContinuationJump implements Serializable - { - static final long serialVersionUID = 7687739156004308247L; - - CallFrame capturedFrame; - CallFrame branchFrame; - Object result; - double resultDbl; - - ContinuationJump(Continuation c, CallFrame current) - { - this.capturedFrame = (CallFrame)c.getImplementation(); - if (this.capturedFrame == null || current == null) { - // Continuation and current execution does not share - // any frames if there is nothing to capture or - // if there is no currently executed frames - this.branchFrame = null; - } else { - // Search for branch frame where parent frame chains starting - // from captured and current meet. - CallFrame chain1 = this.capturedFrame; - CallFrame chain2 = current; - - // First work parents of chain1 or chain2 until the same - // frame depth. - int diff = chain1.frameIndex - chain2.frameIndex; - if (diff != 0) { - if (diff < 0) { - // swap to make sure that - // chain1.frameIndex > chain2.frameIndex and diff > 0 - chain1 = current; - chain2 = this.capturedFrame; - diff = -diff; - } - do { - chain1 = chain1.parentFrame; - } while (--diff != 0); - if (chain1.frameIndex != chain2.frameIndex) Kit.codeBug(); - } - - // Now walk parents in parallel until a shared frame is found - // or until the root is reached. - while (chain1 != chain2 && chain1 != null) { - chain1 = chain1.parentFrame; - chain2 = chain2.parentFrame; - } - - this.branchFrame = chain1; - if (this.branchFrame != null && !this.branchFrame.frozen) - Kit.codeBug(); - } - } - } - - private static CallFrame captureFrameForGenerator(CallFrame frame) { - frame.frozen = true; - CallFrame result = frame.cloneFrozen(); - frame.frozen = false; - - // now isolate this frame from its previous context - result.parentFrame = null; - result.frameIndex = 0; - - return result; - } - - static { - // Checks for byte code consistencies, good compiler can eliminate them - - if (Token.LAST_BYTECODE_TOKEN > 127) { - String str = "Violation of Token.LAST_BYTECODE_TOKEN <= 127"; - System.err.println(str); - throw new IllegalStateException(str); - } - if (MIN_ICODE < -128) { - String str = "Violation of Interpreter.MIN_ICODE >= -128"; - System.err.println(str); - throw new IllegalStateException(str); - } - } - - private static String bytecodeName(int bytecode) - { - if (!validBytecode(bytecode)) { - throw new IllegalArgumentException(String.valueOf(bytecode)); - } - - if (!Token.printICode) { - return String.valueOf(bytecode); - } - - if (validTokenCode(bytecode)) { - return Token.name(bytecode); - } - - switch (bytecode) { - case Icode_DUP: return "DUP"; - case Icode_DUP2: return "DUP2"; - case Icode_SWAP: return "SWAP"; - case Icode_POP: return "POP"; - case Icode_POP_RESULT: return "POP_RESULT"; - case Icode_IFEQ_POP: return "IFEQ_POP"; - case Icode_VAR_INC_DEC: return "VAR_INC_DEC"; - case Icode_NAME_INC_DEC: return "NAME_INC_DEC"; - case Icode_PROP_INC_DEC: return "PROP_INC_DEC"; - case Icode_ELEM_INC_DEC: return "ELEM_INC_DEC"; - case Icode_REF_INC_DEC: return "REF_INC_DEC"; - case Icode_SCOPE_LOAD: return "SCOPE_LOAD"; - case Icode_SCOPE_SAVE: return "SCOPE_SAVE"; - case Icode_TYPEOFNAME: return "TYPEOFNAME"; - case Icode_NAME_AND_THIS: return "NAME_AND_THIS"; - case Icode_PROP_AND_THIS: return "PROP_AND_THIS"; - case Icode_ELEM_AND_THIS: return "ELEM_AND_THIS"; - case Icode_VALUE_AND_THIS: return "VALUE_AND_THIS"; - case Icode_CLOSURE_EXPR: return "CLOSURE_EXPR"; - case Icode_CLOSURE_STMT: return "CLOSURE_STMT"; - case Icode_CALLSPECIAL: return "CALLSPECIAL"; - case Icode_RETUNDEF: return "RETUNDEF"; - case Icode_GOSUB: return "GOSUB"; - case Icode_STARTSUB: return "STARTSUB"; - case Icode_RETSUB: return "RETSUB"; - case Icode_LINE: return "LINE"; - case Icode_SHORTNUMBER: return "SHORTNUMBER"; - case Icode_INTNUMBER: return "INTNUMBER"; - case Icode_LITERAL_NEW: return "LITERAL_NEW"; - case Icode_LITERAL_SET: return "LITERAL_SET"; - case Icode_SPARE_ARRAYLIT: return "SPARE_ARRAYLIT"; - case Icode_REG_IND_C0: return "REG_IND_C0"; - case Icode_REG_IND_C1: return "REG_IND_C1"; - case Icode_REG_IND_C2: return "REG_IND_C2"; - case Icode_REG_IND_C3: return "REG_IND_C3"; - case Icode_REG_IND_C4: return "REG_IND_C4"; - case Icode_REG_IND_C5: return "REG_IND_C5"; - case Icode_REG_IND1: return "LOAD_IND1"; - case Icode_REG_IND2: return "LOAD_IND2"; - case Icode_REG_IND4: return "LOAD_IND4"; - case Icode_REG_STR_C0: return "REG_STR_C0"; - case Icode_REG_STR_C1: return "REG_STR_C1"; - case Icode_REG_STR_C2: return "REG_STR_C2"; - case Icode_REG_STR_C3: return "REG_STR_C3"; - case Icode_REG_STR1: return "LOAD_STR1"; - case Icode_REG_STR2: return "LOAD_STR2"; - case Icode_REG_STR4: return "LOAD_STR4"; - case Icode_GETVAR1: return "GETVAR1"; - case Icode_SETVAR1: return "SETVAR1"; - case Icode_UNDEF: return "UNDEF"; - case Icode_ZERO: return "ZERO"; - case Icode_ONE: return "ONE"; - case Icode_ENTERDQ: return "ENTERDQ"; - case Icode_LEAVEDQ: return "LEAVEDQ"; - case Icode_TAIL_CALL: return "TAIL_CALL"; - case Icode_LOCAL_CLEAR: return "LOCAL_CLEAR"; - case Icode_LITERAL_GETTER: return "LITERAL_GETTER"; - case Icode_LITERAL_SETTER: return "LITERAL_SETTER"; - case Icode_SETCONST: return "SETCONST"; - case Icode_SETCONSTVAR: return "SETCONSTVAR"; - case Icode_SETCONSTVAR1: return "SETCONSTVAR1"; - case Icode_GENERATOR: return "GENERATOR"; - case Icode_GENERATOR_END: return "GENERATOR_END"; - case Icode_DEBUGGER: return "DEBUGGER"; - } - - // icode without name - throw new IllegalStateException(String.valueOf(bytecode)); - } - - private static boolean validIcode(int icode) - { - return MIN_ICODE <= icode && icode <= -1; - } - - private static boolean validTokenCode(int token) - { - return Token.FIRST_BYTECODE_TOKEN <= token - && token <= Token.LAST_BYTECODE_TOKEN; - } - - private static boolean validBytecode(int bytecode) - { - return validIcode(bytecode) || validTokenCode(bytecode); - } - - public Object compile(CompilerEnvirons compilerEnv, - ScriptOrFnNode tree, - String encodedSource, - boolean returnFunction) - { - this.compilerEnv = compilerEnv; - new NodeTransformer().transform(tree); - - if (Token.printTrees) { - /*APPJET*///System.out.println(tree.toStringTree(tree)); - } - - if (returnFunction) { - tree = tree.getFunctionNode(0); - } - - scriptOrFn = tree; - itsData = new InterpreterData(compilerEnv.getLanguageVersion(), - scriptOrFn.getSourceName(), - encodedSource); - itsData.topLevel = true; - - if (returnFunction) { - generateFunctionICode(); - } else { - generateICodeFromTree(scriptOrFn); - } - - return itsData; - } - - public Script createScriptObject(Object bytecode, Object staticSecurityDomain) - { - if(bytecode != itsData) - { - Kit.codeBug(); - } - return InterpretedFunction.createScript(itsData, - staticSecurityDomain); - } - - public void setEvalScriptFlag(Script script) { - ((InterpretedFunction)script).idata.evalScriptFlag = true; - } - - - public Function createFunctionObject(Context cx, Scriptable scope, - Object bytecode, Object staticSecurityDomain) - { - if(bytecode != itsData) - { - Kit.codeBug(); - } - return InterpretedFunction.createFunction(cx, scope, itsData, - staticSecurityDomain); - } - - private void generateFunctionICode() - { - itsInFunctionFlag = true; - - FunctionNode theFunction = (FunctionNode)scriptOrFn; - - itsData.itsFunctionType = theFunction.getFunctionType(); - itsData.itsNeedsActivation = theFunction.requiresActivation(); - itsData.itsName = theFunction.getFunctionName(); - if (!theFunction.getIgnoreDynamicScope()) { - if (compilerEnv.isUseDynamicScope()) { - itsData.useDynamicScope = true; - } - } - if (theFunction.isGenerator()) { - addIcode(Icode_GENERATOR); - addUint16(theFunction.getBaseLineno() & 0xFFFF); - } - - generateICodeFromTree(theFunction.getLastChild()); - } - - private void generateICodeFromTree(Node tree) - { - generateNestedFunctions(); - - generateRegExpLiterals(); - - visitStatement(tree, 0); - fixLabelGotos(); - // add RETURN_RESULT only to scripts as function always ends with RETURN - if (itsData.itsFunctionType == 0) { - addToken(Token.RETURN_RESULT); - } - - if (itsData.itsICode.length != itsICodeTop) { - // Make itsData.itsICode length exactly itsICodeTop to save memory - // and catch bugs with jumps beyond icode as early as possible - byte[] tmp = new byte[itsICodeTop]; - System.arraycopy(itsData.itsICode, 0, tmp, 0, itsICodeTop); - itsData.itsICode = tmp; - } - if (itsStrings.size() == 0) { - itsData.itsStringTable = null; - } else { - itsData.itsStringTable = new String[itsStrings.size()]; - ObjToIntMap.Iterator iter = itsStrings.newIterator(); - for (iter.start(); !iter.done(); iter.next()) { - String str = (String)iter.getKey(); - int index = iter.getValue(); - if (itsData.itsStringTable[index] != null) Kit.codeBug(); - itsData.itsStringTable[index] = str; - } - } - if (itsDoubleTableTop == 0) { - itsData.itsDoubleTable = null; - } else if (itsData.itsDoubleTable.length != itsDoubleTableTop) { - double[] tmp = new double[itsDoubleTableTop]; - System.arraycopy(itsData.itsDoubleTable, 0, tmp, 0, - itsDoubleTableTop); - itsData.itsDoubleTable = tmp; - } - if (itsExceptionTableTop != 0 - && itsData.itsExceptionTable.length != itsExceptionTableTop) - { - int[] tmp = new int[itsExceptionTableTop]; - System.arraycopy(itsData.itsExceptionTable, 0, tmp, 0, - itsExceptionTableTop); - itsData.itsExceptionTable = tmp; - } - - itsData.itsMaxVars = scriptOrFn.getParamAndVarCount(); - // itsMaxFrameArray: interpret method needs this amount for its - // stack and sDbl arrays - itsData.itsMaxFrameArray = itsData.itsMaxVars - + itsData.itsMaxLocals - + itsData.itsMaxStack; - - itsData.argNames = scriptOrFn.getParamAndVarNames(); - itsData.argIsConst = scriptOrFn.getParamAndVarConst(); - itsData.argCount = scriptOrFn.getParamCount(); - - itsData.encodedSourceStart = scriptOrFn.getEncodedSourceStart(); - itsData.encodedSourceEnd = scriptOrFn.getEncodedSourceEnd(); - - if (itsLiteralIds.size() != 0) { - itsData.literalIds = itsLiteralIds.toArray(); - } - - if (Token.printICode) dumpICode(itsData); - } - - private void generateNestedFunctions() - { - int functionCount = scriptOrFn.getFunctionCount(); - if (functionCount == 0) return; - - InterpreterData[] array = new InterpreterData[functionCount]; - for (int i = 0; i != functionCount; i++) { - FunctionNode def = scriptOrFn.getFunctionNode(i); - Interpreter jsi = new Interpreter(); - jsi.compilerEnv = compilerEnv; - jsi.scriptOrFn = def; - jsi.itsData = new InterpreterData(itsData); - jsi.generateFunctionICode(); - array[i] = jsi.itsData; - } - itsData.itsNestedFunctions = array; - } - - private void generateRegExpLiterals() - { - int N = scriptOrFn.getRegexpCount(); - if (N == 0) return; - - Context cx = Context.getContext(); - RegExpProxy rep = ScriptRuntime.checkRegExpProxy(cx); - Object[] array = new Object[N]; - for (int i = 0; i != N; i++) { - String string = scriptOrFn.getRegexpString(i); - String flags = scriptOrFn.getRegexpFlags(i); - array[i] = rep.compileRegExp(cx, string, flags); - } - itsData.itsRegExpLiterals = array; - } - - private void updateLineNumber(Node node) - { - int lineno = node.getLineno(); - if (lineno != itsLineNumber && lineno >= 0) { - if (itsData.firstLinePC < 0) { - itsData.firstLinePC = lineno; - } - itsLineNumber = lineno; - addIcode(Icode_LINE); - addUint16(lineno & 0xFFFF); - } - } - - private RuntimeException badTree(Node node) - { - throw new RuntimeException(node.toString()); - } - - private void visitStatement(Node node, int initialStackDepth) - { - int type = node.getType(); - Node child = node.getFirstChild(); - switch (type) { - - case Token.FUNCTION: - { - int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); - int fnType = scriptOrFn.getFunctionNode(fnIndex). - getFunctionType(); - // Only function expressions or function expression - // statements need closure code creating new function - // object on stack as function statements are initialized - // at script/function start. - // In addition, function expressions can not be present here - // at statement level, they must only be present as expressions. - if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) { - addIndexOp(Icode_CLOSURE_STMT, fnIndex); - } else { - if (fnType != FunctionNode.FUNCTION_STATEMENT) { - throw Kit.codeBug(); - } - } - // For function statements or function expression statements - // in scripts, we need to ensure that the result of the script - // is the function if it is the last statement in the script. - // For example, eval("function () {}") should return a - // function, not undefined. - if (!itsInFunctionFlag) { - addIndexOp(Icode_CLOSURE_EXPR, fnIndex); - stackChange(1); - addIcode(Icode_POP_RESULT); - stackChange(-1); - } - } - break; - - case Token.LABEL: - case Token.LOOP: - case Token.BLOCK: - case Token.EMPTY: - case Token.WITH: - updateLineNumber(node); - case Token.SCRIPT: - // fall through - while (child != null) { - visitStatement(child, initialStackDepth); - child = child.getNext(); - } - break; - - case Token.ENTERWITH: - visitExpression(child, 0); - addToken(Token.ENTERWITH); - stackChange(-1); - break; - - case Token.LEAVEWITH: - addToken(Token.LEAVEWITH); - break; - - case Token.LOCAL_BLOCK: - { - int local = allocLocal(); - node.putIntProp(Node.LOCAL_PROP, local); - updateLineNumber(node); - while (child != null) { - visitStatement(child, initialStackDepth); - child = child.getNext(); - } - addIndexOp(Icode_LOCAL_CLEAR, local); - releaseLocal(local); - } - break; - - case Token.DEBUGGER: - addIcode(Icode_DEBUGGER); - break; - - case Token.SWITCH: - updateLineNumber(node); - // See comments in IRFactory.createSwitch() for description - // of SWITCH node - { - visitExpression(child, 0); - for (Node.Jump caseNode = (Node.Jump)child.getNext(); - caseNode != null; - caseNode = (Node.Jump)caseNode.getNext()) - { - if (caseNode.getType() != Token.CASE) - throw badTree(caseNode); - Node test = caseNode.getFirstChild(); - addIcode(Icode_DUP); - stackChange(1); - visitExpression(test, 0); - addToken(Token.SHEQ); - stackChange(-1); - // If true, Icode_IFEQ_POP will jump and remove case - // value from stack - addGoto(caseNode.target, Icode_IFEQ_POP); - stackChange(-1); - } - addIcode(Icode_POP); - stackChange(-1); - } - break; - - case Token.TARGET: - markTargetLabel(node); - break; - - case Token.IFEQ : - case Token.IFNE : - { - Node target = ((Node.Jump)node).target; - visitExpression(child, 0); - addGoto(target, type); - stackChange(-1); - } - break; - - case Token.GOTO: - { - Node target = ((Node.Jump)node).target; - addGoto(target, type); - } - break; - - case Token.JSR: - { - Node target = ((Node.Jump)node).target; - addGoto(target, Icode_GOSUB); - } - break; - - case Token.FINALLY: - { - // Account for incomming GOTOSUB address - stackChange(1); - int finallyRegister = getLocalBlockRef(node); - addIndexOp(Icode_STARTSUB, finallyRegister); - stackChange(-1); - while (child != null) { - visitStatement(child, initialStackDepth); - child = child.getNext(); - } - addIndexOp(Icode_RETSUB, finallyRegister); - } - break; - - case Token.EXPR_VOID: - case Token.EXPR_RESULT: - updateLineNumber(node); - visitExpression(child, 0); - addIcode((type == Token.EXPR_VOID) ? Icode_POP : Icode_POP_RESULT); - stackChange(-1); - break; - - case Token.TRY: - { - Node.Jump tryNode = (Node.Jump)node; - int exceptionObjectLocal = getLocalBlockRef(tryNode); - int scopeLocal = allocLocal(); - - addIndexOp(Icode_SCOPE_SAVE, scopeLocal); - - int tryStart = itsICodeTop; - boolean savedFlag = itsInTryFlag; - itsInTryFlag = true; - while (child != null) { - visitStatement(child, initialStackDepth); - child = child.getNext(); - } - itsInTryFlag = savedFlag; - - Node catchTarget = tryNode.target; - if (catchTarget != null) { - int catchStartPC - = itsLabelTable[getTargetLabel(catchTarget)]; - addExceptionHandler( - tryStart, catchStartPC, catchStartPC, - false, exceptionObjectLocal, scopeLocal); - } - Node finallyTarget = tryNode.getFinally(); - if (finallyTarget != null) { - int finallyStartPC - = itsLabelTable[getTargetLabel(finallyTarget)]; - addExceptionHandler( - tryStart, finallyStartPC, finallyStartPC, - true, exceptionObjectLocal, scopeLocal); - } - - addIndexOp(Icode_LOCAL_CLEAR, scopeLocal); - releaseLocal(scopeLocal); - } - break; - - case Token.CATCH_SCOPE: - { - int localIndex = getLocalBlockRef(node); - int scopeIndex = node.getExistingIntProp(Node.CATCH_SCOPE_PROP); - String name = child.getString(); - child = child.getNext(); - visitExpression(child, 0); // load expression object - addStringPrefix(name); - addIndexPrefix(localIndex); - addToken(Token.CATCH_SCOPE); - addUint8(scopeIndex != 0 ? 1 : 0); - stackChange(-1); - } - break; - - case Token.THROW: - updateLineNumber(node); - visitExpression(child, 0); - addToken(Token.THROW); - addUint16(itsLineNumber & 0xFFFF); - stackChange(-1); - break; - - case Token.RETHROW: - updateLineNumber(node); - addIndexOp(Token.RETHROW, getLocalBlockRef(node)); - break; - - case Token.RETURN: - updateLineNumber(node); - if (node.getIntProp(Node.GENERATOR_END_PROP, 0) != 0) { - // We're in a generator, so change RETURN to GENERATOR_END - addIcode(Icode_GENERATOR_END); - addUint16(itsLineNumber & 0xFFFF); - } else if (child != null) { - visitExpression(child, ECF_TAIL); - addToken(Token.RETURN); - stackChange(-1); - } else { - addIcode(Icode_RETUNDEF); - } - break; - - case Token.RETURN_RESULT: - updateLineNumber(node); - addToken(Token.RETURN_RESULT); - break; - - case Token.ENUM_INIT_KEYS: - case Token.ENUM_INIT_VALUES: - case Token.ENUM_INIT_ARRAY: - visitExpression(child, 0); - addIndexOp(type, getLocalBlockRef(node)); - stackChange(-1); - break; - - case Icode_GENERATOR: - break; - - default: - throw badTree(node); - } - - if (itsStackDepth != initialStackDepth) { - throw Kit.codeBug(); - } - } - - private void visitExpression(Node node, int contextFlags) - { - int type = node.getType(); - Node child = node.getFirstChild(); - int savedStackDepth = itsStackDepth; - switch (type) { - - case Token.FUNCTION: - { - int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); - FunctionNode fn = scriptOrFn.getFunctionNode(fnIndex); - // See comments in visitStatement for Token.FUNCTION case - if (fn.getFunctionType() != FunctionNode.FUNCTION_EXPRESSION) { - throw Kit.codeBug(); - } - addIndexOp(Icode_CLOSURE_EXPR, fnIndex); - stackChange(1); - } - break; - - case Token.LOCAL_LOAD: - { - int localIndex = getLocalBlockRef(node); - addIndexOp(Token.LOCAL_LOAD, localIndex); - stackChange(1); - } - break; - - case Token.COMMA: - { - Node lastChild = node.getLastChild(); - while (child != lastChild) { - visitExpression(child, 0); - addIcode(Icode_POP); - stackChange(-1); - child = child.getNext(); - } - // Preserve tail context flag if any - visitExpression(child, contextFlags & ECF_TAIL); - } - break; - - case Token.USE_STACK: - // Indicates that stack was modified externally, - // like placed catch object - stackChange(1); - break; - - case Token.REF_CALL: - case Token.CALL: - case Token.NEW: - { - if (type == Token.NEW) { - visitExpression(child, 0); - } else { - generateCallFunAndThis(child); - } - int argCount = 0; - while ((child = child.getNext()) != null) { - visitExpression(child, 0); - ++argCount; - } - int callType = node.getIntProp(Node.SPECIALCALL_PROP, - Node.NON_SPECIALCALL); - if (callType != Node.NON_SPECIALCALL) { - // embed line number and source filename - addIndexOp(Icode_CALLSPECIAL, argCount); - addUint8(callType); - addUint8(type == Token.NEW ? 1 : 0); - addUint16(itsLineNumber & 0xFFFF); - } else { - // Only use the tail call optimization if we're not in a try - // or we're not generating debug info (since the - // optimization will confuse the debugger) - if (type == Token.CALL && (contextFlags & ECF_TAIL) != 0 && - !compilerEnv.isGenerateDebugInfo() && !itsInTryFlag) - { - type = Icode_TAIL_CALL; - } - addIndexOp(type, argCount); - } - // adjust stack - if (type == Token.NEW) { - // new: f, args -> result - stackChange(-argCount); - } else { - // call: f, thisObj, args -> result - // ref_call: f, thisObj, args -> ref - stackChange(-1 - argCount); - } - if (argCount > itsData.itsMaxCalleeArgs) { - itsData.itsMaxCalleeArgs = argCount; - } - } - break; - - case Token.AND: - case Token.OR: - { - visitExpression(child, 0); - addIcode(Icode_DUP); - stackChange(1); - int afterSecondJumpStart = itsICodeTop; - int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ; - addGotoOp(jump); - stackChange(-1); - addIcode(Icode_POP); - stackChange(-1); - child = child.getNext(); - // Preserve tail context flag if any - visitExpression(child, contextFlags & ECF_TAIL); - resolveForwardGoto(afterSecondJumpStart); - } - break; - - case Token.HOOK: - { - Node ifThen = child.getNext(); - Node ifElse = ifThen.getNext(); - visitExpression(child, 0); - int elseJumpStart = itsICodeTop; - addGotoOp(Token.IFNE); - stackChange(-1); - // Preserve tail context flag if any - visitExpression(ifThen, contextFlags & ECF_TAIL); - int afterElseJumpStart = itsICodeTop; - addGotoOp(Token.GOTO); - resolveForwardGoto(elseJumpStart); - itsStackDepth = savedStackDepth; - // Preserve tail context flag if any - visitExpression(ifElse, contextFlags & ECF_TAIL); - resolveForwardGoto(afterElseJumpStart); - } - break; - - case Token.GETPROP: - case Token.GETPROPNOWARN: - visitExpression(child, 0); - child = child.getNext(); - addStringOp(type, child.getString()); - break; - - case Token.GETELEM: - case Token.DELPROP: - case Token.BITAND: - case Token.BITOR: - case Token.BITXOR: - case Token.LSH: - case Token.RSH: - case Token.URSH: - case Token.ADD: - case Token.SUB: - case Token.MOD: - case Token.DIV: - case Token.MUL: - case Token.EQ: - case Token.NE: - case Token.SHEQ: - case Token.SHNE: - case Token.IN: - case Token.INSTANCEOF: - case Token.LE: - case Token.LT: - case Token.GE: - case Token.GT: - visitExpression(child, 0); - child = child.getNext(); - visitExpression(child, 0); - addToken(type); - stackChange(-1); - break; - - case Token.POS: - case Token.NEG: - case Token.NOT: - case Token.BITNOT: - case Token.TYPEOF: - case Token.VOID: - visitExpression(child, 0); - if (type == Token.VOID) { - addIcode(Icode_POP); - addIcode(Icode_UNDEF); - } else { - addToken(type); - } - break; - - case Token.GET_REF: - case Token.DEL_REF: - visitExpression(child, 0); - addToken(type); - break; - - case Token.SETPROP: - case Token.SETPROP_OP: - { - visitExpression(child, 0); - child = child.getNext(); - String property = child.getString(); - child = child.getNext(); - if (type == Token.SETPROP_OP) { - addIcode(Icode_DUP); - stackChange(1); - addStringOp(Token.GETPROP, property); - // Compensate for the following USE_STACK - stackChange(-1); - } - visitExpression(child, 0); - addStringOp(Token.SETPROP, property); - stackChange(-1); - } - break; - - case Token.SETELEM: - case Token.SETELEM_OP: - visitExpression(child, 0); - child = child.getNext(); - visitExpression(child, 0); - child = child.getNext(); - if (type == Token.SETELEM_OP) { - addIcode(Icode_DUP2); - stackChange(2); - addToken(Token.GETELEM); - stackChange(-1); - // Compensate for the following USE_STACK - stackChange(-1); - } - visitExpression(child, 0); - addToken(Token.SETELEM); - stackChange(-2); - break; - - case Token.SET_REF: - case Token.SET_REF_OP: - visitExpression(child, 0); - child = child.getNext(); - if (type == Token.SET_REF_OP) { - addIcode(Icode_DUP); - stackChange(1); - addToken(Token.GET_REF); - // Compensate for the following USE_STACK - stackChange(-1); - } - visitExpression(child, 0); - addToken(Token.SET_REF); - stackChange(-1); - break; - - case Token.SETNAME: - { - String name = child.getString(); - visitExpression(child, 0); - child = child.getNext(); - visitExpression(child, 0); - addStringOp(Token.SETNAME, name); - stackChange(-1); - } - break; - - case Token.SETCONST: - { - String name = child.getString(); - visitExpression(child, 0); - child = child.getNext(); - visitExpression(child, 0); - addStringOp(Icode_SETCONST, name); - stackChange(-1); - } - break; - - case Token.TYPEOFNAME: - { - int index = -1; - // use typeofname if an activation frame exists - // since the vars all exist there instead of in jregs - if (itsInFunctionFlag && !itsData.itsNeedsActivation) - index = scriptOrFn.getIndexForNameNode(node); - if (index == -1) { - addStringOp(Icode_TYPEOFNAME, node.getString()); - stackChange(1); - } else { - addVarOp(Token.GETVAR, index); - stackChange(1); - addToken(Token.TYPEOF); - } - } - break; - - case Token.BINDNAME: - case Token.NAME: - case Token.STRING: - addStringOp(type, node.getString()); - stackChange(1); - break; - - case Token.INC: - case Token.DEC: - visitIncDec(node, child); - break; - - case Token.NUMBER: - { - double num = node.getDouble(); - int inum = (int)num; - if (inum == num) { - if (inum == 0) { - addIcode(Icode_ZERO); - // Check for negative zero - if (1.0 / num < 0.0) { - addToken(Token.NEG); - } - } else if (inum == 1) { - addIcode(Icode_ONE); - } else if ((short)inum == inum) { - addIcode(Icode_SHORTNUMBER); - // write short as uin16 bit pattern - addUint16(inum & 0xFFFF); - } else { - addIcode(Icode_INTNUMBER); - addInt(inum); - } - } else { - int index = getDoubleIndex(num); - addIndexOp(Token.NUMBER, index); - } - stackChange(1); - } - break; - - case Token.GETVAR: - { - if (itsData.itsNeedsActivation) Kit.codeBug(); - int index = scriptOrFn.getIndexForNameNode(node); - addVarOp(Token.GETVAR, index); - stackChange(1); - } - break; - - case Token.SETVAR: - { - if (itsData.itsNeedsActivation) Kit.codeBug(); - int index = scriptOrFn.getIndexForNameNode(child); - child = child.getNext(); - visitExpression(child, 0); - addVarOp(Token.SETVAR, index); - } - break; - - case Token.SETCONSTVAR: - { - if (itsData.itsNeedsActivation) Kit.codeBug(); - int index = scriptOrFn.getIndexForNameNode(child); - child = child.getNext(); - visitExpression(child, 0); - addVarOp(Token.SETCONSTVAR, index); - } - break; - - case Token.NULL: - case Token.THIS: - case Token.THISFN: - case Token.FALSE: - case Token.TRUE: - addToken(type); - stackChange(1); - break; - - case Token.ENUM_NEXT: - case Token.ENUM_ID: - addIndexOp(type, getLocalBlockRef(node)); - stackChange(1); - break; - - case Token.REGEXP: - { - int index = node.getExistingIntProp(Node.REGEXP_PROP); - addIndexOp(Token.REGEXP, index); - stackChange(1); - } - break; - - case Token.ARRAYLIT: - case Token.OBJECTLIT: - visitLiteral(node, child); - break; - - case Token.ARRAYCOMP: - visitArrayComprehension(node, child, child.getNext()); - break; - - case Token.REF_SPECIAL: - visitExpression(child, 0); - addStringOp(type, (String)node.getProp(Node.NAME_PROP)); - break; - - case Token.REF_MEMBER: - case Token.REF_NS_MEMBER: - case Token.REF_NAME: - case Token.REF_NS_NAME: - { - int memberTypeFlags = node.getIntProp(Node.MEMBER_TYPE_PROP, 0); - // generate possible target, possible namespace and member - int childCount = 0; - do { - visitExpression(child, 0); - ++childCount; - child = child.getNext(); - } while (child != null); - addIndexOp(type, memberTypeFlags); - stackChange(1 - childCount); - } - break; - - case Token.DOTQUERY: - { - int queryPC; - updateLineNumber(node); - visitExpression(child, 0); - addIcode(Icode_ENTERDQ); - stackChange(-1); - queryPC = itsICodeTop; - visitExpression(child.getNext(), 0); - addBackwardGoto(Icode_LEAVEDQ, queryPC); - } - break; - - case Token.DEFAULTNAMESPACE : - case Token.ESCXMLATTR : - case Token.ESCXMLTEXT : - visitExpression(child, 0); - addToken(type); - break; - - case Token.YIELD: - if (child != null) { - visitExpression(child, 0); - } else { - addIcode(Icode_UNDEF); - stackChange(1); - } - addToken(Token.YIELD); - addUint16(node.getLineno() & 0xFFFF); - break; - - case Token.WITHEXPR: { - Node enterWith = node.getFirstChild(); - Node with = enterWith.getNext(); - visitExpression(enterWith.getFirstChild(), 0); - addToken(Token.ENTERWITH); - stackChange(-1); - visitExpression(with.getFirstChild(), 0); - addToken(Token.LEAVEWITH); - break; - } - - default: - throw badTree(node); - } - if (savedStackDepth + 1 != itsStackDepth) { - Kit.codeBug(); - } - } - - private void generateCallFunAndThis(Node left) - { - // Generate code to place on stack function and thisObj - int type = left.getType(); - switch (type) { - case Token.NAME: { - String name = left.getString(); - // stack: ... -> ... function thisObj - addStringOp(Icode_NAME_AND_THIS, name); - stackChange(2); - break; - } - case Token.GETPROP: - case Token.GETELEM: { - Node target = left.getFirstChild(); - visitExpression(target, 0); - Node id = target.getNext(); - if (type == Token.GETPROP) { - String property = id.getString(); - // stack: ... target -> ... function thisObj - addStringOp(Icode_PROP_AND_THIS, property); - stackChange(1); - } else { - visitExpression(id, 0); - // stack: ... target id -> ... function thisObj - addIcode(Icode_ELEM_AND_THIS); - } - break; - } - default: - // Including Token.GETVAR - visitExpression(left, 0); - // stack: ... value -> ... function thisObj - addIcode(Icode_VALUE_AND_THIS); - stackChange(1); - break; - } - } - - private void visitIncDec(Node node, Node child) - { - int incrDecrMask = node.getExistingIntProp(Node.INCRDECR_PROP); - int childType = child.getType(); - switch (childType) { - case Token.GETVAR : { - if (itsData.itsNeedsActivation) Kit.codeBug(); - int i = scriptOrFn.getIndexForNameNode(child); - addVarOp(Icode_VAR_INC_DEC, i); - addUint8(incrDecrMask); - stackChange(1); - break; - } - case Token.NAME : { - String name = child.getString(); - addStringOp(Icode_NAME_INC_DEC, name); - addUint8(incrDecrMask); - stackChange(1); - break; - } - case Token.GETPROP : { - Node object = child.getFirstChild(); - visitExpression(object, 0); - String property = object.getNext().getString(); - addStringOp(Icode_PROP_INC_DEC, property); - addUint8(incrDecrMask); - break; - } - case Token.GETELEM : { - Node object = child.getFirstChild(); - visitExpression(object, 0); - Node index = object.getNext(); - visitExpression(index, 0); - addIcode(Icode_ELEM_INC_DEC); - addUint8(incrDecrMask); - stackChange(-1); - break; - } - case Token.GET_REF : { - Node ref = child.getFirstChild(); - visitExpression(ref, 0); - addIcode(Icode_REF_INC_DEC); - addUint8(incrDecrMask); - break; - } - default : { - throw badTree(node); - } - } - } - - private void visitLiteral(Node node, Node child) - { - int type = node.getType(); - int count; - Object[] propertyIds = null; - if (type == Token.ARRAYLIT) { - count = 0; - for (Node n = child; n != null; n = n.getNext()) { - ++count; - } - } else if (type == Token.OBJECTLIT) { - propertyIds = (Object[])node.getProp(Node.OBJECT_IDS_PROP); - count = propertyIds.length; - } else { - throw badTree(node); - } - addIndexOp(Icode_LITERAL_NEW, count); - stackChange(2); - while (child != null) { - int childType = child.getType(); - if (childType == Token.GET) { - visitExpression(child.getFirstChild(), 0); - addIcode(Icode_LITERAL_GETTER); - } else if (childType == Token.SET) { - visitExpression(child.getFirstChild(), 0); - addIcode(Icode_LITERAL_SETTER); - } else { - visitExpression(child, 0); - addIcode(Icode_LITERAL_SET); - } - stackChange(-1); - child = child.getNext(); - } - if (type == Token.ARRAYLIT) { - int[] skipIndexes = (int[])node.getProp(Node.SKIP_INDEXES_PROP); - if (skipIndexes == null) { - addToken(Token.ARRAYLIT); - } else { - int index = itsLiteralIds.size(); - itsLiteralIds.add(skipIndexes); - addIndexOp(Icode_SPARE_ARRAYLIT, index); - } - } else { - int index = itsLiteralIds.size(); - itsLiteralIds.add(propertyIds); - addIndexOp(Token.OBJECTLIT, index); - } - stackChange(-1); - } - - private void visitArrayComprehension(Node node, Node initStmt, Node expr) - { - // A bit of a hack: array comprehensions are implemented using - // statement nodes for the iteration, yet they appear in an - // expression context. So we pass the current stack depth to - // visitStatement so it can check that the depth is not altered - // by statements. - visitStatement(initStmt, itsStackDepth); - visitExpression(expr, 0); - } - - private int getLocalBlockRef(Node node) - { - Node localBlock = (Node)node.getProp(Node.LOCAL_BLOCK_PROP); - return localBlock.getExistingIntProp(Node.LOCAL_PROP); - } - - private int getTargetLabel(Node target) - { - int label = target.labelId(); - if (label != -1) { - return label; - } - label = itsLabelTableTop; - if (itsLabelTable == null || label == itsLabelTable.length) { - if (itsLabelTable == null) { - itsLabelTable = new int[MIN_LABEL_TABLE_SIZE]; - }else { - int[] tmp = new int[itsLabelTable.length * 2]; - System.arraycopy(itsLabelTable, 0, tmp, 0, label); - itsLabelTable = tmp; - } - } - itsLabelTableTop = label + 1; - itsLabelTable[label] = -1; - - target.labelId(label); - return label; - } - - private void markTargetLabel(Node target) - { - int label = getTargetLabel(target); - if (itsLabelTable[label] != -1) { - // Can mark label only once - Kit.codeBug(); - } - itsLabelTable[label] = itsICodeTop; - } - - private void addGoto(Node target, int gotoOp) - { - int label = getTargetLabel(target); - if (!(label < itsLabelTableTop)) Kit.codeBug(); - int targetPC = itsLabelTable[label]; - - if (targetPC != -1) { - addBackwardGoto(gotoOp, targetPC); - } else { - int gotoPC = itsICodeTop; - addGotoOp(gotoOp); - int top = itsFixupTableTop; - if (itsFixupTable == null || top == itsFixupTable.length) { - if (itsFixupTable == null) { - itsFixupTable = new long[MIN_FIXUP_TABLE_SIZE]; - } else { - long[] tmp = new long[itsFixupTable.length * 2]; - System.arraycopy(itsFixupTable, 0, tmp, 0, top); - itsFixupTable = tmp; - } - } - itsFixupTableTop = top + 1; - itsFixupTable[top] = ((long)label << 32) | gotoPC; - } - } - - private void fixLabelGotos() - { - for (int i = 0; i < itsFixupTableTop; i++) { - long fixup = itsFixupTable[i]; - int label = (int)(fixup >> 32); - int jumpSource = (int)fixup; - int pc = itsLabelTable[label]; - if (pc == -1) { - // Unlocated label - throw Kit.codeBug(); - } - resolveGoto(jumpSource, pc); - } - itsFixupTableTop = 0; - } - - private void addBackwardGoto(int gotoOp, int jumpPC) - { - int fromPC = itsICodeTop; - // Ensure that this is a jump backward - if (fromPC <= jumpPC) throw Kit.codeBug(); - addGotoOp(gotoOp); - resolveGoto(fromPC, jumpPC); - } - - private void resolveForwardGoto(int fromPC) - { - // Ensure that forward jump skips at least self bytecode - if (itsICodeTop < fromPC + 3) throw Kit.codeBug(); - resolveGoto(fromPC, itsICodeTop); - } - - private void resolveGoto(int fromPC, int jumpPC) - { - int offset = jumpPC - fromPC; - // Ensure that jumps do not overlap - if (0 <= offset && offset <= 2) throw Kit.codeBug(); - int offsetSite = fromPC + 1; - if (offset != (short)offset) { - if (itsData.longJumps == null) { - itsData.longJumps = new UintMap(); - } - itsData.longJumps.put(offsetSite, jumpPC); - offset = 0; - } - byte[] array = itsData.itsICode; - array[offsetSite] = (byte)(offset >> 8); - array[offsetSite + 1] = (byte)offset; - } - - private void addToken(int token) - { - if (!validTokenCode(token)) throw Kit.codeBug(); - addUint8(token); - } - - private void addIcode(int icode) - { - if (!validIcode(icode)) throw Kit.codeBug(); - // Write negative icode as uint8 bits - addUint8(icode & 0xFF); - } - - private void addUint8(int value) - { - if ((value & ~0xFF) != 0) throw Kit.codeBug(); - byte[] array = itsData.itsICode; - int top = itsICodeTop; - if (top == array.length) { - array = increaseICodeCapacity(1); - } - array[top] = (byte)value; - itsICodeTop = top + 1; - } - - private void addUint16(int value) - { - if ((value & ~0xFFFF) != 0) throw Kit.codeBug(); - byte[] array = itsData.itsICode; - int top = itsICodeTop; - if (top + 2 > array.length) { - array = increaseICodeCapacity(2); - } - array[top] = (byte)(value >>> 8); - array[top + 1] = (byte)value; - itsICodeTop = top + 2; - } - - private void addInt(int i) - { - byte[] array = itsData.itsICode; - int top = itsICodeTop; - if (top + 4 > array.length) { - array = increaseICodeCapacity(4); - } - array[top] = (byte)(i >>> 24); - array[top + 1] = (byte)(i >>> 16); - array[top + 2] = (byte)(i >>> 8); - array[top + 3] = (byte)i; - itsICodeTop = top + 4; - } - - private int getDoubleIndex(double num) - { - int index = itsDoubleTableTop; - if (index == 0) { - itsData.itsDoubleTable = new double[64]; - } else if (itsData.itsDoubleTable.length == index) { - double[] na = new double[index * 2]; - System.arraycopy(itsData.itsDoubleTable, 0, na, 0, index); - itsData.itsDoubleTable = na; - } - itsData.itsDoubleTable[index] = num; - itsDoubleTableTop = index + 1; - return index; - } - - private void addGotoOp(int gotoOp) - { - byte[] array = itsData.itsICode; - int top = itsICodeTop; - if (top + 3 > array.length) { - array = increaseICodeCapacity(3); - } - array[top] = (byte)gotoOp; - // Offset would written later - itsICodeTop = top + 1 + 2; - } - - private void addVarOp(int op, int varIndex) - { - switch (op) { - case Token.SETCONSTVAR: - if (varIndex < 128) { - addIcode(Icode_SETCONSTVAR1); - addUint8(varIndex); - return; - } - addIndexOp(Icode_SETCONSTVAR, varIndex); - return; - case Token.GETVAR: - case Token.SETVAR: - if (varIndex < 128) { - addIcode(op == Token.GETVAR ? Icode_GETVAR1 : Icode_SETVAR1); - addUint8(varIndex); - return; - } - // fallthrough - case Icode_VAR_INC_DEC: - addIndexOp(op, varIndex); - return; - } - throw Kit.codeBug(); - } - - private void addStringOp(int op, String str) - { - addStringPrefix(str); - if (validIcode(op)) { - addIcode(op); - } else { - addToken(op); - } - } - - private void addIndexOp(int op, int index) - { - addIndexPrefix(index); - if (validIcode(op)) { - addIcode(op); - } else { - addToken(op); - } - } - - private void addStringPrefix(String str) - { - int index = itsStrings.get(str, -1); - if (index == -1) { - index = itsStrings.size(); - itsStrings.put(str, index); - } - if (index < 4) { - addIcode(Icode_REG_STR_C0 - index); - } else if (index <= 0xFF) { - addIcode(Icode_REG_STR1); - addUint8(index); - } else if (index <= 0xFFFF) { - addIcode(Icode_REG_STR2); - addUint16(index); - } else { - addIcode(Icode_REG_STR4); - addInt(index); - } - } - - private void addIndexPrefix(int index) - { - if (index < 0) Kit.codeBug(); - if (index < 6) { - addIcode(Icode_REG_IND_C0 - index); - } else if (index <= 0xFF) { - addIcode(Icode_REG_IND1); - addUint8(index); - } else if (index <= 0xFFFF) { - addIcode(Icode_REG_IND2); - addUint16(index); - } else { - addIcode(Icode_REG_IND4); - addInt(index); - } - } - - private void addExceptionHandler(int icodeStart, int icodeEnd, - int handlerStart, boolean isFinally, - int exceptionObjectLocal, int scopeLocal) - { - int top = itsExceptionTableTop; - int[] table = itsData.itsExceptionTable; - if (table == null) { - if (top != 0) Kit.codeBug(); - table = new int[EXCEPTION_SLOT_SIZE * 2]; - itsData.itsExceptionTable = table; - } else if (table.length == top) { - table = new int[table.length * 2]; - System.arraycopy(itsData.itsExceptionTable, 0, table, 0, top); - itsData.itsExceptionTable = table; - } - table[top + EXCEPTION_TRY_START_SLOT] = icodeStart; - table[top + EXCEPTION_TRY_END_SLOT] = icodeEnd; - table[top + EXCEPTION_HANDLER_SLOT] = handlerStart; - table[top + EXCEPTION_TYPE_SLOT] = isFinally ? 1 : 0; - table[top + EXCEPTION_LOCAL_SLOT] = exceptionObjectLocal; - table[top + EXCEPTION_SCOPE_SLOT] = scopeLocal; - - itsExceptionTableTop = top + EXCEPTION_SLOT_SIZE; - } - - private byte[] increaseICodeCapacity(int extraSize) - { - int capacity = itsData.itsICode.length; - int top = itsICodeTop; - if (top + extraSize <= capacity) throw Kit.codeBug(); - capacity *= 2; - if (top + extraSize > capacity) { - capacity = top + extraSize; - } - byte[] array = new byte[capacity]; - System.arraycopy(itsData.itsICode, 0, array, 0, top); - itsData.itsICode = array; - return array; - } - - private void stackChange(int change) - { - if (change <= 0) { - itsStackDepth += change; - } else { - int newDepth = itsStackDepth + change; - if (newDepth > itsData.itsMaxStack) { - itsData.itsMaxStack = newDepth; - } - itsStackDepth = newDepth; - } - } - - private int allocLocal() - { - int localSlot = itsLocalTop; - ++itsLocalTop; - if (itsLocalTop > itsData.itsMaxLocals) { - itsData.itsMaxLocals = itsLocalTop; - } - return localSlot; - } - - private void releaseLocal(int localSlot) - { - --itsLocalTop; - if (localSlot != itsLocalTop) Kit.codeBug(); - } - - private static int getShort(byte[] iCode, int pc) { - return (iCode[pc] << 8) | (iCode[pc + 1] & 0xFF); - } - - private static int getIndex(byte[] iCode, int pc) { - return ((iCode[pc] & 0xFF) << 8) | (iCode[pc + 1] & 0xFF); - } - - private static int getInt(byte[] iCode, int pc) { - return (iCode[pc] << 24) | ((iCode[pc + 1] & 0xFF) << 16) - | ((iCode[pc + 2] & 0xFF) << 8) | (iCode[pc + 3] & 0xFF); - } - - private static int getExceptionHandler(CallFrame frame, - boolean onlyFinally) - { - int[] exceptionTable = frame.idata.itsExceptionTable; - if (exceptionTable == null) { - // No exception handlers - return -1; - } - - // Icode switch in the interpreter increments PC immediately - // and it is necessary to subtract 1 from the saved PC - // to point it before the start of the next instruction. - int pc = frame.pc - 1; - - // OPT: use binary search - int best = -1, bestStart = 0, bestEnd = 0; - for (int i = 0; i != exceptionTable.length; i += EXCEPTION_SLOT_SIZE) { - int start = exceptionTable[i + EXCEPTION_TRY_START_SLOT]; - int end = exceptionTable[i + EXCEPTION_TRY_END_SLOT]; - if (!(start <= pc && pc < end)) { - continue; - } - if (onlyFinally && exceptionTable[i + EXCEPTION_TYPE_SLOT] != 1) { - continue; - } - if (best >= 0) { - // Since handlers always nest and they never have shared end - // although they can share start it is sufficient to compare - // handlers ends - if (bestEnd < end) { - continue; - } - // Check the above assumption - if (bestStart > start) Kit.codeBug(); // should be nested - if (bestEnd == end) Kit.codeBug(); // no ens sharing - } - best = i; - bestStart = start; - bestEnd = end; - } - return best; - } - - private static void dumpICode(InterpreterData idata) - { - if (!Token.printICode) { - return; - } - - byte iCode[] = idata.itsICode; - int iCodeLength = iCode.length; - String[] strings = idata.itsStringTable; - PrintStream out = System.out; - out.println("ICode dump, for " + idata.itsName - + ", length = " + iCodeLength); - out.println("MaxStack = " + idata.itsMaxStack); - - int indexReg = 0; - for (int pc = 0; pc < iCodeLength; ) { - out.flush(); - out.print(" [" + pc + "] "); - int token = iCode[pc]; - int icodeLength = bytecodeSpan(token); - String tname = bytecodeName(token); - int old_pc = pc; - ++pc; - switch (token) { - default: - if (icodeLength != 1) Kit.codeBug(); - out.println(tname); - break; - - case Icode_GOSUB : - case Token.GOTO : - case Token.IFEQ : - case Token.IFNE : - case Icode_IFEQ_POP : - case Icode_LEAVEDQ : { - int newPC = pc + getShort(iCode, pc) - 1; - out.println(tname + " " + newPC); - pc += 2; - break; - } - case Icode_VAR_INC_DEC : - case Icode_NAME_INC_DEC : - case Icode_PROP_INC_DEC : - case Icode_ELEM_INC_DEC : - case Icode_REF_INC_DEC: { - int incrDecrType = iCode[pc]; - out.println(tname + " " + incrDecrType); - ++pc; - break; - } - - case Icode_CALLSPECIAL : { - int callType = iCode[pc] & 0xFF; - boolean isNew = (iCode[pc + 1] != 0); - int line = getIndex(iCode, pc+2); - out.println(tname+" "+callType+" "+isNew+" "+indexReg+" "+line); - pc += 4; - break; - } - - case Token.CATCH_SCOPE: - { - boolean afterFisrtFlag = (iCode[pc] != 0); - out.println(tname+" "+afterFisrtFlag); - ++pc; - } - break; - case Token.REGEXP : - out.println(tname+" "+idata.itsRegExpLiterals[indexReg]); - break; - case Token.OBJECTLIT : - case Icode_SPARE_ARRAYLIT : - out.println(tname+" "+idata.literalIds[indexReg]); - break; - case Icode_CLOSURE_EXPR : - case Icode_CLOSURE_STMT : - out.println(tname+" "+idata.itsNestedFunctions[indexReg]); - break; - case Token.CALL : - case Icode_TAIL_CALL : - case Token.REF_CALL : - case Token.NEW : - out.println(tname+' '+indexReg); - break; - case Token.THROW : - case Token.YIELD : - case Icode_GENERATOR : - case Icode_GENERATOR_END : - { - int line = getIndex(iCode, pc); - out.println(tname + " : " + line); - pc += 2; - break; - } - case Icode_SHORTNUMBER : { - int value = getShort(iCode, pc); - out.println(tname + " " + value); - pc += 2; - break; - } - case Icode_INTNUMBER : { - int value = getInt(iCode, pc); - out.println(tname + " " + value); - pc += 4; - break; - } - case Token.NUMBER : { - double value = idata.itsDoubleTable[indexReg]; - out.println(tname + " " + value); - break; - } - case Icode_LINE : { - int line = getIndex(iCode, pc); - out.println(tname + " : " + line); - pc += 2; - break; - } - case Icode_REG_STR1: { - String str = strings[0xFF & iCode[pc]]; - out.println(tname + " \"" + str + '"'); - ++pc; - break; - } - case Icode_REG_STR2: { - String str = strings[getIndex(iCode, pc)]; - out.println(tname + " \"" + str + '"'); - pc += 2; - break; - } - case Icode_REG_STR4: { - String str = strings[getInt(iCode, pc)]; - out.println(tname + " \"" + str + '"'); - pc += 4; - break; - } - case Icode_REG_IND_C0: - indexReg = 0; - out.println(tname); - break; - case Icode_REG_IND_C1: - indexReg = 1; - out.println(tname); - break; - case Icode_REG_IND_C2: - indexReg = 2; - out.println(tname); - break; - case Icode_REG_IND_C3: - indexReg = 3; - out.println(tname); - break; - case Icode_REG_IND_C4: - indexReg = 4; - out.println(tname); - break; - case Icode_REG_IND_C5: - indexReg = 5; - out.println(tname); - break; - case Icode_REG_IND1: { - indexReg = 0xFF & iCode[pc]; - out.println(tname+" "+indexReg); - ++pc; - break; - } - case Icode_REG_IND2: { - indexReg = getIndex(iCode, pc); - out.println(tname+" "+indexReg); - pc += 2; - break; - } - case Icode_REG_IND4: { - indexReg = getInt(iCode, pc); - out.println(tname+" "+indexReg); - pc += 4; - break; - } - case Icode_GETVAR1: - case Icode_SETVAR1: - case Icode_SETCONSTVAR1: - indexReg = iCode[pc]; - out.println(tname+" "+indexReg); - ++pc; - break; - } - if (old_pc + icodeLength != pc) Kit.codeBug(); - } - - int[] table = idata.itsExceptionTable; - if (table != null) { - out.println("Exception handlers: " - +table.length / EXCEPTION_SLOT_SIZE); - for (int i = 0; i != table.length; - i += EXCEPTION_SLOT_SIZE) - { - int tryStart = table[i + EXCEPTION_TRY_START_SLOT]; - int tryEnd = table[i + EXCEPTION_TRY_END_SLOT]; - int handlerStart = table[i + EXCEPTION_HANDLER_SLOT]; - int type = table[i + EXCEPTION_TYPE_SLOT]; - int exceptionLocal = table[i + EXCEPTION_LOCAL_SLOT]; - int scopeLocal = table[i + EXCEPTION_SCOPE_SLOT]; - - out.println(" tryStart="+tryStart+" tryEnd="+tryEnd - +" handlerStart="+handlerStart - +" type="+(type == 0 ? "catch" : "finally") - +" exceptionLocal="+exceptionLocal); - } - } - out.flush(); - } - - private static int bytecodeSpan(int bytecode) - { - switch (bytecode) { - case Token.THROW : - case Token.YIELD: - case Icode_GENERATOR: - case Icode_GENERATOR_END: - // source line - return 1 + 2; - - case Icode_GOSUB : - case Token.GOTO : - case Token.IFEQ : - case Token.IFNE : - case Icode_IFEQ_POP : - case Icode_LEAVEDQ : - // target pc offset - return 1 + 2; - - case Icode_CALLSPECIAL : - // call type - // is new - // line number - return 1 + 1 + 1 + 2; - - case Token.CATCH_SCOPE: - // scope flag - return 1 + 1; - - case Icode_VAR_INC_DEC: - case Icode_NAME_INC_DEC: - case Icode_PROP_INC_DEC: - case Icode_ELEM_INC_DEC: - case Icode_REF_INC_DEC: - // type of ++/-- - return 1 + 1; - - case Icode_SHORTNUMBER : - // short number - return 1 + 2; - - case Icode_INTNUMBER : - // int number - return 1 + 4; - - case Icode_REG_IND1: - // ubyte index - return 1 + 1; - - case Icode_REG_IND2: - // ushort index - return 1 + 2; - - case Icode_REG_IND4: - // int index - return 1 + 4; - - case Icode_REG_STR1: - // ubyte string index - return 1 + 1; - - case Icode_REG_STR2: - // ushort string index - return 1 + 2; - - case Icode_REG_STR4: - // int string index - return 1 + 4; - - case Icode_GETVAR1: - case Icode_SETVAR1: - case Icode_SETCONSTVAR1: - // byte var index - return 1 + 1; - - case Icode_LINE : - // line number - return 1 + 2; - } - if (!validBytecode(bytecode)) throw Kit.codeBug(); - return 1; - } - - static int[] getLineNumbers(InterpreterData data) - { - UintMap presentLines = new UintMap(); - - byte[] iCode = data.itsICode; - int iCodeLength = iCode.length; - for (int pc = 0; pc != iCodeLength;) { - int bytecode = iCode[pc]; - int span = bytecodeSpan(bytecode); - if (bytecode == Icode_LINE) { - if (span != 3) Kit.codeBug(); - int line = getIndex(iCode, pc + 1); - presentLines.put(line, 0); - } - pc += span; - } - - return presentLines.getKeys(); - } - - public void captureStackInfo(RhinoException ex) - { - Context cx = Context.getCurrentContext(); - if (cx == null || cx.lastInterpreterFrame == null) { - // No interpreter invocations - ex.interpreterStackInfo = null; - ex.interpreterLineData = null; - return; - } - // has interpreter frame on the stack - CallFrame[] array; - if (cx.previousInterpreterInvocations == null - || cx.previousInterpreterInvocations.size() == 0) - { - array = new CallFrame[1]; - } else { - int previousCount = cx.previousInterpreterInvocations.size(); - if (cx.previousInterpreterInvocations.peek() - == cx.lastInterpreterFrame) - { - // It can happen if exception was generated after - // frame was pushed to cx.previousInterpreterInvocations - // but before assignment to cx.lastInterpreterFrame. - // In this case frames has to be ignored. - --previousCount; - } - array = new CallFrame[previousCount + 1]; - cx.previousInterpreterInvocations.toArray(array); - } - array[array.length - 1] = (CallFrame)cx.lastInterpreterFrame; - - int interpreterFrameCount = 0; - for (int i = 0; i != array.length; ++i) { - interpreterFrameCount += 1 + array[i].frameIndex; - } - - int[] linePC = new int[interpreterFrameCount]; - // Fill linePC with pc positions from all interpreter frames. - // Start from the most nested frame - int linePCIndex = interpreterFrameCount; - for (int i = array.length; i != 0;) { - --i; - CallFrame frame = array[i]; - while (frame != null) { - --linePCIndex; - linePC[linePCIndex] = frame.pcSourceLineStart; - frame = frame.parentFrame; - } - } - if (linePCIndex != 0) Kit.codeBug(); - - ex.interpreterStackInfo = array; - ex.interpreterLineData = linePC; - } - - public String getSourcePositionFromStack(Context cx, int[] linep) - { - CallFrame frame = (CallFrame)cx.lastInterpreterFrame; - InterpreterData idata = frame.idata; - if (frame.pcSourceLineStart >= 0) { - linep[0] = getIndex(idata.itsICode, frame.pcSourceLineStart); - } else { - linep[0] = 0; - } - return idata.itsSourceFile; - } - - public String getPatchedStack(RhinoException ex, - String nativeStackTrace) - { - String tag = "org.mozilla.javascript.Interpreter.interpretLoop"; - StringBuffer sb = new StringBuffer(nativeStackTrace.length() + 1000); - String lineSeparator = SecurityUtilities.getSystemProperty("line.separator"); - - CallFrame[] array = (CallFrame[])ex.interpreterStackInfo; - int[] linePC = ex.interpreterLineData; - int arrayIndex = array.length; - int linePCIndex = linePC.length; - int offset = 0; - while (arrayIndex != 0) { - --arrayIndex; - int pos = nativeStackTrace.indexOf(tag, offset); - if (pos < 0) { - break; - } - - // Skip tag length - pos += tag.length(); - // Skip until the end of line - for (; pos != nativeStackTrace.length(); ++pos) { - char c = nativeStackTrace.charAt(pos); - if (c == '\n' || c == '\r') { - break; - } - } - sb.append(nativeStackTrace.substring(offset, pos)); - offset = pos; - - CallFrame frame = array[arrayIndex]; - while (frame != null) { - if (linePCIndex == 0) Kit.codeBug(); - --linePCIndex; - InterpreterData idata = frame.idata; - sb.append(lineSeparator); - sb.append("\tat script"); - if (idata.itsName != null && idata.itsName.length() != 0) { - sb.append('.'); - sb.append(idata.itsName); - } - sb.append('('); - sb.append(idata.itsSourceFile); - int pc = linePC[linePCIndex]; - if (pc >= 0) { - // Include line info only if available - sb.append(':'); - sb.append(getIndex(idata.itsICode, pc)); - } - sb.append(')'); - frame = frame.parentFrame; - } - } - sb.append(nativeStackTrace.substring(offset)); - - return sb.toString(); - } - - public List getScriptStack(RhinoException ex) - { - if (ex.interpreterStackInfo == null) { - return null; - } - - List list = new ArrayList(); - String lineSeparator = - SecurityUtilities.getSystemProperty("line.separator"); - - CallFrame[] array = (CallFrame[])ex.interpreterStackInfo; - int[] linePC = ex.interpreterLineData; - int arrayIndex = array.length; - int linePCIndex = linePC.length; - while (arrayIndex != 0) { - --arrayIndex; - StringBuffer sb = new StringBuffer(); - CallFrame frame = array[arrayIndex]; - while (frame != null) { - if (linePCIndex == 0) Kit.codeBug(); - --linePCIndex; - InterpreterData idata = frame.idata; - sb.append("\tat "); - sb.append(idata.itsSourceFile); - int pc = linePC[linePCIndex]; - if (pc >= 0) { - // Include line info only if available - sb.append(':'); - sb.append(getIndex(idata.itsICode, pc)); - } - if (idata.itsName != null && idata.itsName.length() != 0) { - sb.append(" ("); - sb.append(idata.itsName); - sb.append(')'); - } - sb.append(lineSeparator); - frame = frame.parentFrame; - } - list.add(sb.toString()); - } - return list; - } - - static String getEncodedSource(InterpreterData idata) - { - if (idata.encodedSource == null) { - return null; - } - return idata.encodedSource.substring(idata.encodedSourceStart, - idata.encodedSourceEnd); - } - - private static void initFunction(Context cx, Scriptable scope, - InterpretedFunction parent, int index) - { - InterpretedFunction fn; - fn = InterpretedFunction.createFunction(cx, scope, parent, index); - ScriptRuntime.initFunction(cx, scope, fn, fn.idata.itsFunctionType, - parent.idata.evalScriptFlag); - } - - static Object interpret(InterpretedFunction ifun, - Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!ScriptRuntime.hasTopCall(cx)) Kit.codeBug(); - - if (cx.interpreterSecurityDomain != ifun.securityDomain) { - Object savedDomain = cx.interpreterSecurityDomain; - cx.interpreterSecurityDomain = ifun.securityDomain; - try { - return ifun.securityController.callWithDomain( - ifun.securityDomain, cx, ifun, scope, thisObj, args); - } finally { - cx.interpreterSecurityDomain = savedDomain; - } - } - - CallFrame frame = new CallFrame(); - initFrame(cx, scope, thisObj, args, null, 0, args.length, - ifun, null, frame); - - return interpretLoop(cx, frame, null); - } - - static class GeneratorState { - GeneratorState(int operation, Object value) { - this.operation = operation; - this.value = value; - } - int operation; - Object value; - RuntimeException returnedException; - } - - public static Object resumeGenerator(Context cx, - Scriptable scope, - int operation, - Object savedState, - Object value) - { - CallFrame frame = (CallFrame) savedState; - GeneratorState generatorState = new GeneratorState(operation, value); - if (operation == NativeGenerator.GENERATOR_CLOSE) { - try { - return interpretLoop(cx, frame, generatorState); - } catch (RuntimeException e) { - // Only propagate exceptions other than closingException - if (e != value) - throw e; - } - return Undefined.instance; - } - Object result = interpretLoop(cx, frame, generatorState); - if (generatorState.returnedException != null) - throw generatorState.returnedException; - return result; - } - - public static Object restartContinuation(Continuation c, Context cx, - Scriptable scope, Object[] args) - { - if (!ScriptRuntime.hasTopCall(cx)) { - return ScriptRuntime.doTopCall(c, cx, scope, null, args); - } - - Object arg; - if (args.length == 0) { - arg = Undefined.instance; - } else { - arg = args[0]; - } - - CallFrame capturedFrame = (CallFrame)c.getImplementation(); - if (capturedFrame == null) { - // No frames to restart - return arg; - } - - ContinuationJump cjump = new ContinuationJump(c, null); - - cjump.result = arg; - return interpretLoop(cx, null, cjump); - } - - private static Object interpretLoop(Context cx, CallFrame frame, - Object throwable) - { - // throwable holds exception object to rethrow or catch - // It is also used for continuation restart in which case - // it holds ContinuationJump - - final Object DBL_MRK = UniqueTag.DOUBLE_MARK; - final Object undefined = Undefined.instance; - - final boolean instructionCounting = (cx.instructionThreshold != 0); - // arbitrary number to add to instructionCount when calling - // other functions - final int INVOCATION_COST = 100; - // arbitrary exception cost for instruction counting - final int EXCEPTION_COST = 100; - - String stringReg = null; - int indexReg = -1; - - if (cx.lastInterpreterFrame != null) { - // save the top frame from the previous interpretLoop - // invocation on the stack - if (cx.previousInterpreterInvocations == null) { - cx.previousInterpreterInvocations = new ObjArray(); - } - cx.previousInterpreterInvocations.push(cx.lastInterpreterFrame); - } - - // When restarting continuation throwable is not null and to jump - // to the code that rewind continuation state indexReg should be set - // to -1. - // With the normal call throable == null and indexReg == -1 allows to - // catch bugs with using indeReg to access array eleemnts before - // initializing indexReg. - - GeneratorState generatorState = null; - if (throwable != null) { - if (throwable instanceof GeneratorState) { - generatorState = (GeneratorState) throwable; - - // reestablish this call frame - enterFrame(cx, frame, ScriptRuntime.emptyArgs, true); - throwable = null; - } else if (!(throwable instanceof ContinuationJump)) { - // It should be continuation - Kit.codeBug(); - } - } - - Object interpreterResult = null; - double interpreterResultDbl = 0.0; - - StateLoop: for (;;) { - withoutExceptions: try { - - if (throwable != null) { - // Need to return both 'frame' and 'throwable' from - // 'processThrowable', so just added a 'throwable' - // member in 'frame'. - frame = processThrowable(cx, throwable, frame, indexReg, - instructionCounting); - throwable = frame.throwable; - frame.throwable = null; - } else { - if (generatorState == null && frame.frozen) Kit.codeBug(); - } - - // Use local variables for constant values in frame - // for faster access - Object[] stack = frame.stack; - double[] sDbl = frame.sDbl; - Object[] vars = frame.varSource.stack; - double[] varDbls = frame.varSource.sDbl; - int[] varAttributes = frame.varSource.stackAttributes; - byte[] iCode = frame.idata.itsICode; - String[] strings = frame.idata.itsStringTable; - - // Use local for stackTop as well. Since execption handlers - // can only exist at statement level where stack is empty, - // it is necessary to save/restore stackTop only across - // function calls and normal returns. - int stackTop = frame.savedStackTop; - - // Store new frame in cx which is used for error reporting etc. - cx.lastInterpreterFrame = frame; - - Loop: for (;;) { - - // Exception handler assumes that PC is already incremented - // pass the instruction start when it searches the - // exception handler - int op = iCode[frame.pc++]; - jumplessRun: { - - // Back indent to ease implementation reading -switch (op) { - case Icode_GENERATOR: { - if (!frame.frozen) { - // First time encountering this opcode: create new generator - // object and return - frame.pc--; // we want to come back here when we resume - CallFrame generatorFrame = captureFrameForGenerator(frame); - generatorFrame.frozen = true; - NativeGenerator generator = new NativeGenerator(frame.scope, - generatorFrame.fnOrScript, generatorFrame); - frame.result = generator; - break Loop; - } else { - // We are now resuming execution. Fall through to YIELD case. - } - } - // fall through... - case Token.YIELD: { - if (!frame.frozen) { - return freezeGenerator(cx, frame, stackTop, generatorState); - } else { - Object obj = thawGenerator(frame, stackTop, generatorState, op); - if (obj != Scriptable.NOT_FOUND) { - throwable = obj; - break withoutExceptions; - } - continue Loop; - } - } - case Icode_GENERATOR_END: { - // throw StopIteration - frame.frozen = true; - int sourceLine = getIndex(iCode, frame.pc); - generatorState.returnedException = new JavaScriptException( - NativeIterator.getStopIterationObject(frame.scope), - frame.idata.itsSourceFile, sourceLine); - break Loop; - } - case Token.THROW: { - Object value = stack[stackTop]; - if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - - int sourceLine = getIndex(iCode, frame.pc); - throwable = new JavaScriptException(value, - frame.idata.itsSourceFile, - sourceLine); - break withoutExceptions; - } - case Token.RETHROW: { - indexReg += frame.localShift; - throwable = stack[indexReg]; - break withoutExceptions; - } - case Token.GE : - case Token.LE : - case Token.GT : - case Token.LT : { - --stackTop; - Object rhs = stack[stackTop + 1]; - Object lhs = stack[stackTop]; - boolean valBln; - object_compare: - { - number_compare: - { - double rDbl, lDbl; - if (rhs == DBL_MRK) { - rDbl = sDbl[stackTop + 1]; - lDbl = stack_double(frame, stackTop); - } else if (lhs == DBL_MRK) { - rDbl = ScriptRuntime.toNumber(rhs); - lDbl = sDbl[stackTop]; - } else { - break number_compare; - } - switch (op) { - case Token.GE: - valBln = (lDbl >= rDbl); - break object_compare; - case Token.LE: - valBln = (lDbl <= rDbl); - break object_compare; - case Token.GT: - valBln = (lDbl > rDbl); - break object_compare; - case Token.LT: - valBln = (lDbl < rDbl); - break object_compare; - default: - throw Kit.codeBug(); - } - } - switch (op) { - case Token.GE: - valBln = ScriptRuntime.cmp_LE(rhs, lhs); - break; - case Token.LE: - valBln = ScriptRuntime.cmp_LE(lhs, rhs); - break; - case Token.GT: - valBln = ScriptRuntime.cmp_LT(rhs, lhs); - break; - case Token.LT: - valBln = ScriptRuntime.cmp_LT(lhs, rhs); - break; - default: - throw Kit.codeBug(); - } - } - stack[stackTop] = ScriptRuntime.wrapBoolean(valBln); - continue Loop; - } - case Token.IN : - case Token.INSTANCEOF : { - Object rhs = stack[stackTop]; - if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - boolean valBln; - if (op == Token.IN) { - valBln = ScriptRuntime.in(lhs, rhs, cx); - } else { - valBln = ScriptRuntime.instanceOf(lhs, rhs, cx); - } - stack[stackTop] = ScriptRuntime.wrapBoolean(valBln); - continue Loop; - } - case Token.EQ : - case Token.NE : { - --stackTop; - boolean valBln; - Object rhs = stack[stackTop + 1]; - Object lhs = stack[stackTop]; - if (rhs == DBL_MRK) { - if (lhs == DBL_MRK) { - valBln = (sDbl[stackTop] == sDbl[stackTop + 1]); - } else { - valBln = ScriptRuntime.eqNumber(sDbl[stackTop + 1], lhs); - } - } else { - if (lhs == DBL_MRK) { - valBln = ScriptRuntime.eqNumber(sDbl[stackTop], rhs); - } else { - valBln = ScriptRuntime.eq(lhs, rhs); - } - } - valBln ^= (op == Token.NE); - stack[stackTop] = ScriptRuntime.wrapBoolean(valBln); - continue Loop; - } - case Token.SHEQ : - case Token.SHNE : { - --stackTop; - Object rhs = stack[stackTop + 1]; - Object lhs = stack[stackTop]; - boolean valBln; - shallow_compare: { - double rdbl, ldbl; - if (rhs == DBL_MRK) { - rdbl = sDbl[stackTop + 1]; - if (lhs == DBL_MRK) { - ldbl = sDbl[stackTop]; - } else if (lhs instanceof Number) { - ldbl = ((Number)lhs).doubleValue(); - } else { - valBln = false; - break shallow_compare; - } - } else if (lhs == DBL_MRK) { - ldbl = sDbl[stackTop]; - if (rhs == DBL_MRK) { - rdbl = sDbl[stackTop + 1]; - } else if (rhs instanceof Number) { - rdbl = ((Number)rhs).doubleValue(); - } else { - valBln = false; - break shallow_compare; - } - } else { - valBln = ScriptRuntime.shallowEq(lhs, rhs); - break shallow_compare; - } - valBln = (ldbl == rdbl); - } - valBln ^= (op == Token.SHNE); - stack[stackTop] = ScriptRuntime.wrapBoolean(valBln); - continue Loop; - } - case Token.IFNE : - if (stack_boolean(frame, stackTop--)) { - frame.pc += 2; - continue Loop; - } - break jumplessRun; - case Token.IFEQ : - if (!stack_boolean(frame, stackTop--)) { - frame.pc += 2; - continue Loop; - } - break jumplessRun; - case Icode_IFEQ_POP : - if (!stack_boolean(frame, stackTop--)) { - frame.pc += 2; - continue Loop; - } - stack[stackTop--] = null; - break jumplessRun; - case Token.GOTO : - break jumplessRun; - case Icode_GOSUB : - ++stackTop; - stack[stackTop] = DBL_MRK; - sDbl[stackTop] = frame.pc + 2; - break jumplessRun; - case Icode_STARTSUB : - if (stackTop == frame.emptyStackTop + 1) { - // Call from Icode_GOSUB: store return PC address in the local - indexReg += frame.localShift; - stack[indexReg] = stack[stackTop]; - sDbl[indexReg] = sDbl[stackTop]; - --stackTop; - } else { - // Call from exception handler: exception object is already stored - // in the local - if (stackTop != frame.emptyStackTop) Kit.codeBug(); - } - continue Loop; - case Icode_RETSUB : { - // indexReg: local to store return address - if (instructionCounting) { - addInstructionCount(cx, frame, 0); - } - indexReg += frame.localShift; - Object value = stack[indexReg]; - if (value != DBL_MRK) { - // Invocation from exception handler, restore object to rethrow - throwable = value; - break withoutExceptions; - } - // Normal return from GOSUB - frame.pc = (int)sDbl[indexReg]; - if (instructionCounting) { - frame.pcPrevBranch = frame.pc; - } - continue Loop; - } - case Icode_POP : - stack[stackTop] = null; - stackTop--; - continue Loop; - case Icode_POP_RESULT : - frame.result = stack[stackTop]; - frame.resultDbl = sDbl[stackTop]; - stack[stackTop] = null; - --stackTop; - continue Loop; - case Icode_DUP : - stack[stackTop + 1] = stack[stackTop]; - sDbl[stackTop + 1] = sDbl[stackTop]; - stackTop++; - continue Loop; - case Icode_DUP2 : - stack[stackTop + 1] = stack[stackTop - 1]; - sDbl[stackTop + 1] = sDbl[stackTop - 1]; - stack[stackTop + 2] = stack[stackTop]; - sDbl[stackTop + 2] = sDbl[stackTop]; - stackTop += 2; - continue Loop; - case Icode_SWAP : { - Object o = stack[stackTop]; - stack[stackTop] = stack[stackTop - 1]; - stack[stackTop - 1] = o; - double d = sDbl[stackTop]; - sDbl[stackTop] = sDbl[stackTop - 1]; - sDbl[stackTop - 1] = d; - continue Loop; - } - case Token.RETURN : - frame.result = stack[stackTop]; - frame.resultDbl = sDbl[stackTop]; - --stackTop; - break Loop; - case Token.RETURN_RESULT : - break Loop; - case Icode_RETUNDEF : - frame.result = undefined; - break Loop; - case Token.BITNOT : { - int rIntValue = stack_int32(frame, stackTop); - stack[stackTop] = DBL_MRK; - sDbl[stackTop] = ~rIntValue; - continue Loop; - } - case Token.BITAND : - case Token.BITOR : - case Token.BITXOR : - case Token.LSH : - case Token.RSH : { - int lIntValue = stack_int32(frame, stackTop-1); - int rIntValue = stack_int32(frame, stackTop); - stack[--stackTop] = DBL_MRK; - switch (op) { - case Token.BITAND: - lIntValue &= rIntValue; - break; - case Token.BITOR: - lIntValue |= rIntValue; - break; - case Token.BITXOR: - lIntValue ^= rIntValue; - break; - case Token.LSH: - lIntValue <<= rIntValue; - break; - case Token.RSH: - lIntValue >>= rIntValue; - break; - } - sDbl[stackTop] = lIntValue; - continue Loop; - } - case Token.URSH : { - double lDbl = stack_double(frame, stackTop-1); - int rIntValue = stack_int32(frame, stackTop) & 0x1F; - stack[--stackTop] = DBL_MRK; - sDbl[stackTop] = ScriptRuntime.toUint32(lDbl) >>> rIntValue; - continue Loop; - } - case Token.NEG : - case Token.POS : { - double rDbl = stack_double(frame, stackTop); - stack[stackTop] = DBL_MRK; - if (op == Token.NEG) { - rDbl = -rDbl; - } - sDbl[stackTop] = rDbl; - continue Loop; - } - case Token.ADD : - --stackTop; - do_add(stack, sDbl, stackTop, cx); - continue Loop; - case Token.SUB : - case Token.MUL : - case Token.DIV : - case Token.MOD : { - double rDbl = stack_double(frame, stackTop); - --stackTop; - double lDbl = stack_double(frame, stackTop); - stack[stackTop] = DBL_MRK; - switch (op) { - case Token.SUB: - lDbl -= rDbl; - break; - case Token.MUL: - lDbl *= rDbl; - break; - case Token.DIV: - lDbl /= rDbl; - break; - case Token.MOD: - lDbl %= rDbl; - break; - } - sDbl[stackTop] = lDbl; - continue Loop; - } - case Token.NOT : - stack[stackTop] = ScriptRuntime.wrapBoolean( - !stack_boolean(frame, stackTop)); - continue Loop; - case Token.BINDNAME : - stack[++stackTop] = ScriptRuntime.bind(cx, frame.scope, stringReg); - continue Loop; - case Token.SETNAME : { - Object rhs = stack[stackTop]; - if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Scriptable lhs = (Scriptable)stack[stackTop]; - stack[stackTop] = ScriptRuntime.setName(lhs, rhs, cx, - frame.scope, stringReg); - continue Loop; - } - case Icode_SETCONST: { - Object rhs = stack[stackTop]; - if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Scriptable lhs = (Scriptable)stack[stackTop]; - stack[stackTop] = ScriptRuntime.setConst(lhs, rhs, cx, stringReg); - continue Loop; - } - case Token.DELPROP : { - Object rhs = stack[stackTop]; - if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.delete(lhs, rhs, cx); - continue Loop; - } - case Token.GETPROPNOWARN : { - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.getObjectPropNoWarn(lhs, stringReg, cx); - continue Loop; - } - case Token.GETPROP : { - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.getObjectProp(lhs, stringReg, cx); - continue Loop; - } - case Token.SETPROP : { - Object rhs = stack[stackTop]; - if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.setObjectProp(lhs, stringReg, rhs, - cx); - continue Loop; - } - case Icode_PROP_INC_DEC : { - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.propIncrDecr(lhs, stringReg, - cx, iCode[frame.pc]); - ++frame.pc; - continue Loop; - } - case Token.GETELEM : { - --stackTop; - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) { - lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - } - Object value; - Object id = stack[stackTop + 1]; - if (id != DBL_MRK) { - value = ScriptRuntime.getObjectElem(lhs, id, cx); - } else { - double d = sDbl[stackTop + 1]; - value = ScriptRuntime.getObjectIndex(lhs, d, cx); - } - stack[stackTop] = value; - continue Loop; - } - case Token.SETELEM : { - stackTop -= 2; - Object rhs = stack[stackTop + 2]; - if (rhs == DBL_MRK) { - rhs = ScriptRuntime.wrapNumber(sDbl[stackTop + 2]); - } - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) { - lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - } - Object value; - Object id = stack[stackTop + 1]; - if (id != DBL_MRK) { - value = ScriptRuntime.setObjectElem(lhs, id, rhs, cx); - } else { - double d = sDbl[stackTop + 1]; - value = ScriptRuntime.setObjectIndex(lhs, d, rhs, cx); - } - stack[stackTop] = value; - continue Loop; - } - case Icode_ELEM_INC_DEC: { - Object rhs = stack[stackTop]; - if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.elemIncrDecr(lhs, rhs, cx, - iCode[frame.pc]); - ++frame.pc; - continue Loop; - } - case Token.GET_REF : { - Ref ref = (Ref)stack[stackTop]; - stack[stackTop] = ScriptRuntime.refGet(ref, cx); - continue Loop; - } - case Token.SET_REF : { - Object value = stack[stackTop]; - if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Ref ref = (Ref)stack[stackTop]; - stack[stackTop] = ScriptRuntime.refSet(ref, value, cx); - continue Loop; - } - case Token.DEL_REF : { - Ref ref = (Ref)stack[stackTop]; - stack[stackTop] = ScriptRuntime.refDel(ref, cx); - continue Loop; - } - case Icode_REF_INC_DEC : { - Ref ref = (Ref)stack[stackTop]; - stack[stackTop] = ScriptRuntime.refIncrDecr(ref, cx, iCode[frame.pc]); - ++frame.pc; - continue Loop; - } - case Token.LOCAL_LOAD : - ++stackTop; - indexReg += frame.localShift; - stack[stackTop] = stack[indexReg]; - sDbl[stackTop] = sDbl[indexReg]; - continue Loop; - case Icode_LOCAL_CLEAR : - indexReg += frame.localShift; - stack[indexReg] = null; - continue Loop; - case Icode_NAME_AND_THIS : - // stringReg: name - ++stackTop; - stack[stackTop] = ScriptRuntime.getNameFunctionAndThis(stringReg, - cx, frame.scope); - ++stackTop; - stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx); - continue Loop; - case Icode_PROP_AND_THIS: { - Object obj = stack[stackTop]; - if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); - // stringReg: property - stack[stackTop] = ScriptRuntime.getPropFunctionAndThis(obj, stringReg, - cx); - ++stackTop; - stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx); - continue Loop; - } - case Icode_ELEM_AND_THIS: { - Object obj = stack[stackTop - 1]; - if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop - 1]); - Object id = stack[stackTop]; - if (id == DBL_MRK) id = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop - 1] = ScriptRuntime.getElemFunctionAndThis(obj, id, cx); - stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx); - continue Loop; - } - case Icode_VALUE_AND_THIS : { - Object value = stack[stackTop]; - if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.getValueFunctionAndThis(value, cx); - ++stackTop; - stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx); - continue Loop; - } - case Icode_CALLSPECIAL : { - if (instructionCounting) { - cx.instructionCount += INVOCATION_COST; - } - int callType = iCode[frame.pc] & 0xFF; - boolean isNew = (iCode[frame.pc + 1] != 0); - int sourceLine = getIndex(iCode, frame.pc + 2); - - // indexReg: number of arguments - if (isNew) { - // stack change: function arg0 .. argN -> newResult - stackTop -= indexReg; - - Object function = stack[stackTop]; - if (function == DBL_MRK) - function = ScriptRuntime.wrapNumber(sDbl[stackTop]); - Object[] outArgs = getArgsArray( - stack, sDbl, stackTop + 1, indexReg); - stack[stackTop] = ScriptRuntime.newSpecial( - cx, function, outArgs, frame.scope, callType); - } else { - // stack change: function thisObj arg0 .. argN -> result - stackTop -= 1 + indexReg; - - // Call code generation ensure that stack here - // is ... Callable Scriptable - Scriptable functionThis = (Scriptable)stack[stackTop + 1]; - Callable function = (Callable)stack[stackTop]; - Object[] outArgs = getArgsArray( - stack, sDbl, stackTop + 2, indexReg); - stack[stackTop] = ScriptRuntime.callSpecial( - cx, function, functionThis, outArgs, - frame.scope, frame.thisObj, callType, - frame.idata.itsSourceFile, sourceLine); - } - frame.pc += 4; - continue Loop; - } - case Token.CALL : - case Icode_TAIL_CALL : - case Token.REF_CALL : { - if (instructionCounting) { - cx.instructionCount += INVOCATION_COST; - } - // stack change: function thisObj arg0 .. argN -> result - // indexReg: number of arguments - stackTop -= 1 + indexReg; - - // CALL generation ensures that fun and funThisObj - // are already Scriptable and Callable objects respectively - Callable fun = (Callable)stack[stackTop]; - Scriptable funThisObj = (Scriptable)stack[stackTop + 1]; - if (op == Token.REF_CALL) { - Object[] outArgs = getArgsArray(stack, sDbl, stackTop + 2, - indexReg); - stack[stackTop] = ScriptRuntime.callRef(fun, funThisObj, - outArgs, cx); - continue Loop; - } - Scriptable calleeScope = frame.scope; - if (frame.useActivation) { - calleeScope = ScriptableObject.getTopLevelScope(frame.scope); - } - if (fun instanceof InterpretedFunction) { - InterpretedFunction ifun = (InterpretedFunction)fun; - if (frame.fnOrScript.securityDomain == ifun.securityDomain) { - CallFrame callParentFrame = frame; - CallFrame calleeFrame = new CallFrame(); - if (op == Icode_TAIL_CALL) { - // In principle tail call can re-use the current - // frame and its stack arrays but it is hard to - // do properly. Any exceptions that can legally - // happen during frame re-initialization including - // StackOverflowException during innocent looking - // System.arraycopy may leave the current frame - // data corrupted leading to undefined behaviour - // in the catch code bellow that unwinds JS stack - // on exceptions. Then there is issue about frame release - // end exceptions there. - // To avoid frame allocation a released frame - // can be cached for re-use which would also benefit - // non-tail calls but it is not clear that this caching - // would gain in performance due to potentially - // bad interaction with GC. - callParentFrame = frame.parentFrame; - // Release the current frame. See Bug #344501 to see why - // it is being done here. - exitFrame(cx, frame, null); - } - initFrame(cx, calleeScope, funThisObj, stack, sDbl, - stackTop + 2, indexReg, ifun, callParentFrame, - calleeFrame); - if (op != Icode_TAIL_CALL) { - frame.savedStackTop = stackTop; - frame.savedCallOp = op; - } - frame = calleeFrame; - continue StateLoop; - } - } - - if (fun instanceof Continuation) { - // Jump to the captured continuation - ContinuationJump cjump; - cjump = new ContinuationJump((Continuation)fun, frame); - - // continuation result is the first argument if any - // of contination call - if (indexReg == 0) { - cjump.result = undefined; - } else { - cjump.result = stack[stackTop + 2]; - cjump.resultDbl = sDbl[stackTop + 2]; - } - - // Start the real unwind job - throwable = cjump; - break withoutExceptions; - } - - if (fun instanceof IdFunctionObject) { - IdFunctionObject ifun = (IdFunctionObject)fun; - if (Continuation.isContinuationConstructor(ifun)) { - captureContinuation(cx, frame, stackTop); - continue Loop; - } - // Bug 405654 -- make best effort to keep Function.apply and - // Function.call within this interpreter loop invocation - if(BaseFunction.isApplyOrCall(ifun)) { - Callable applyCallable = ScriptRuntime.getCallable(funThisObj); - if(applyCallable instanceof InterpretedFunction) { - InterpretedFunction iApplyCallable = (InterpretedFunction)applyCallable; - if(frame.fnOrScript.securityDomain == iApplyCallable.securityDomain) { - frame = initFrameForApplyOrCall(cx, frame, indexReg, - stack, sDbl, stackTop, op, calleeScope, ifun, - iApplyCallable); - continue StateLoop; - } - } - } - } - - stack[stackTop] = fun.call(cx, calleeScope, funThisObj, - getArgsArray(stack, sDbl, stackTop + 2, indexReg)); - - continue Loop; - } - case Token.NEW : { - if (instructionCounting) { - cx.instructionCount += INVOCATION_COST; - } - // stack change: function arg0 .. argN -> newResult - // indexReg: number of arguments - stackTop -= indexReg; - - Object lhs = stack[stackTop]; - if (lhs instanceof InterpretedFunction) { - InterpretedFunction f = (InterpretedFunction)lhs; - if (frame.fnOrScript.securityDomain == f.securityDomain) { - Scriptable newInstance = f.createObject(cx, frame.scope); - CallFrame calleeFrame = new CallFrame(); - initFrame(cx, frame.scope, newInstance, stack, sDbl, - stackTop + 1, indexReg, f, frame, - calleeFrame); - - stack[stackTop] = newInstance; - frame.savedStackTop = stackTop; - frame.savedCallOp = op; - frame = calleeFrame; - continue StateLoop; - } - } - if (!(lhs instanceof Function)) { - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - throw ScriptRuntime.notFunctionError(lhs); - } - Function fun = (Function)lhs; - - if (fun instanceof IdFunctionObject) { - IdFunctionObject ifun = (IdFunctionObject)fun; - if (Continuation.isContinuationConstructor(ifun)) { - captureContinuation(cx, frame, stackTop); - continue Loop; - } - } - - Object[] outArgs = getArgsArray(stack, sDbl, stackTop + 1, indexReg); - stack[stackTop] = fun.construct(cx, frame.scope, outArgs); - continue Loop; - } - case Token.TYPEOF : { - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.typeof(lhs); - continue Loop; - } - case Icode_TYPEOFNAME : - stack[++stackTop] = ScriptRuntime.typeofName(frame.scope, stringReg); - continue Loop; - case Token.STRING : - stack[++stackTop] = stringReg; - continue Loop; - case Icode_SHORTNUMBER : - ++stackTop; - stack[stackTop] = DBL_MRK; - sDbl[stackTop] = getShort(iCode, frame.pc); - frame.pc += 2; - continue Loop; - case Icode_INTNUMBER : - ++stackTop; - stack[stackTop] = DBL_MRK; - sDbl[stackTop] = getInt(iCode, frame.pc); - frame.pc += 4; - continue Loop; - case Token.NUMBER : - ++stackTop; - stack[stackTop] = DBL_MRK; - sDbl[stackTop] = frame.idata.itsDoubleTable[indexReg]; - continue Loop; - case Token.NAME : - stack[++stackTop] = ScriptRuntime.name(cx, frame.scope, stringReg); - continue Loop; - case Icode_NAME_INC_DEC : - stack[++stackTop] = ScriptRuntime.nameIncrDecr(frame.scope, stringReg, - cx, iCode[frame.pc]); - ++frame.pc; - continue Loop; - case Icode_SETCONSTVAR1: - indexReg = iCode[frame.pc++]; - // fallthrough - case Token.SETCONSTVAR : - if (!frame.useActivation) { - if ((varAttributes[indexReg] & ScriptableObject.READONLY) == 0) { - throw Context.reportRuntimeError1("msg.var.redecl", - frame.idata.argNames[indexReg]); - } - if ((varAttributes[indexReg] & ScriptableObject.UNINITIALIZED_CONST) - != 0) - { - vars[indexReg] = stack[stackTop]; - varAttributes[indexReg] &= ~ScriptableObject.UNINITIALIZED_CONST; - varDbls[indexReg] = sDbl[stackTop]; - } - } else { - Object val = stack[stackTop]; - if (val == DBL_MRK) val = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stringReg = frame.idata.argNames[indexReg]; - if (frame.scope instanceof ConstProperties) { - ConstProperties cp = (ConstProperties)frame.scope; - cp.putConst(stringReg, frame.scope, val); - } else - throw Kit.codeBug(); - } - continue Loop; - case Icode_SETVAR1: - indexReg = iCode[frame.pc++]; - // fallthrough - case Token.SETVAR : - if (!frame.useActivation) { - if ((varAttributes[indexReg] & ScriptableObject.READONLY) == 0) { - vars[indexReg] = stack[stackTop]; - varDbls[indexReg] = sDbl[stackTop]; - } - } else { - Object val = stack[stackTop]; - if (val == DBL_MRK) val = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stringReg = frame.idata.argNames[indexReg]; - frame.scope.put(stringReg, frame.scope, val); - } - continue Loop; - case Icode_GETVAR1: - indexReg = iCode[frame.pc++]; - // fallthrough - case Token.GETVAR : - ++stackTop; - if (!frame.useActivation) { - stack[stackTop] = vars[indexReg]; - sDbl[stackTop] = varDbls[indexReg]; - } else { - stringReg = frame.idata.argNames[indexReg]; - stack[stackTop] = frame.scope.get(stringReg, frame.scope); - } - continue Loop; - case Icode_VAR_INC_DEC : { - // indexReg : varindex - ++stackTop; - int incrDecrMask = iCode[frame.pc]; - if (!frame.useActivation) { - stack[stackTop] = DBL_MRK; - Object varValue = vars[indexReg]; - double d; - if (varValue == DBL_MRK) { - d = varDbls[indexReg]; - } else { - d = ScriptRuntime.toNumber(varValue); - vars[indexReg] = DBL_MRK; - } - double d2 = ((incrDecrMask & Node.DECR_FLAG) == 0) - ? d + 1.0 : d - 1.0; - varDbls[indexReg] = d2; - sDbl[stackTop] = ((incrDecrMask & Node.POST_FLAG) == 0) ? d2 : d; - } else { - String varName = frame.idata.argNames[indexReg]; - stack[stackTop] = ScriptRuntime.nameIncrDecr(frame.scope, varName, - cx, incrDecrMask); - } - ++frame.pc; - continue Loop; - } - case Icode_ZERO : - ++stackTop; - stack[stackTop] = DBL_MRK; - sDbl[stackTop] = 0; - continue Loop; - case Icode_ONE : - ++stackTop; - stack[stackTop] = DBL_MRK; - sDbl[stackTop] = 1; - continue Loop; - case Token.NULL : - stack[++stackTop] = null; - continue Loop; - case Token.THIS : - stack[++stackTop] = frame.thisObj; - continue Loop; - case Token.THISFN : - stack[++stackTop] = frame.fnOrScript; - continue Loop; - case Token.FALSE : - stack[++stackTop] = Boolean.FALSE; - continue Loop; - case Token.TRUE : - stack[++stackTop] = Boolean.TRUE; - continue Loop; - case Icode_UNDEF : - stack[++stackTop] = undefined; - continue Loop; - case Token.ENTERWITH : { - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - frame.scope = ScriptRuntime.enterWith(lhs, cx, frame.scope); - continue Loop; - } - case Token.LEAVEWITH : - frame.scope = ScriptRuntime.leaveWith(frame.scope); - continue Loop; - case Token.CATCH_SCOPE : { - // stack top: exception object - // stringReg: name of exception variable - // indexReg: local for exception scope - --stackTop; - indexReg += frame.localShift; - - boolean afterFirstScope = (frame.idata.itsICode[frame.pc] != 0); - Throwable caughtException = (Throwable)stack[stackTop + 1]; - Scriptable lastCatchScope; - if (!afterFirstScope) { - lastCatchScope = null; - } else { - lastCatchScope = (Scriptable)stack[indexReg]; - } - stack[indexReg] = ScriptRuntime.newCatchScope(caughtException, - lastCatchScope, stringReg, - cx, frame.scope); - ++frame.pc; - continue Loop; - } - case Token.ENUM_INIT_KEYS : - case Token.ENUM_INIT_VALUES : - case Token.ENUM_INIT_ARRAY : { - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - indexReg += frame.localShift; - int enumType = op == Token.ENUM_INIT_KEYS - ? ScriptRuntime.ENUMERATE_KEYS : - op == Token.ENUM_INIT_VALUES - ? ScriptRuntime.ENUMERATE_VALUES : - ScriptRuntime.ENUMERATE_ARRAY; - stack[indexReg] = ScriptRuntime.enumInit(lhs, cx, enumType); - continue Loop; - } - case Token.ENUM_NEXT : - case Token.ENUM_ID : { - indexReg += frame.localShift; - Object val = stack[indexReg]; - ++stackTop; - stack[stackTop] = (op == Token.ENUM_NEXT) - ? (Object)ScriptRuntime.enumNext(val) - : (Object)ScriptRuntime.enumId(val, cx); - continue Loop; - } - case Token.REF_SPECIAL : { - //stringReg: name of special property - Object obj = stack[stackTop]; - if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.specialRef(obj, stringReg, cx); - continue Loop; - } - case Token.REF_MEMBER: { - //indexReg: flags - Object elem = stack[stackTop]; - if (elem == DBL_MRK) elem = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Object obj = stack[stackTop]; - if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.memberRef(obj, elem, cx, indexReg); - continue Loop; - } - case Token.REF_NS_MEMBER: { - //indexReg: flags - Object elem = stack[stackTop]; - if (elem == DBL_MRK) elem = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Object ns = stack[stackTop]; - if (ns == DBL_MRK) ns = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Object obj = stack[stackTop]; - if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.memberRef(obj, ns, elem, cx, indexReg); - continue Loop; - } - case Token.REF_NAME: { - //indexReg: flags - Object name = stack[stackTop]; - if (name == DBL_MRK) name = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.nameRef(name, cx, frame.scope, - indexReg); - continue Loop; - } - case Token.REF_NS_NAME: { - //indexReg: flags - Object name = stack[stackTop]; - if (name == DBL_MRK) name = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - Object ns = stack[stackTop]; - if (ns == DBL_MRK) ns = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.nameRef(ns, name, cx, frame.scope, - indexReg); - continue Loop; - } - case Icode_SCOPE_LOAD : - indexReg += frame.localShift; - frame.scope = (Scriptable)stack[indexReg]; - continue Loop; - case Icode_SCOPE_SAVE : - indexReg += frame.localShift; - stack[indexReg] = frame.scope; - continue Loop; - case Icode_CLOSURE_EXPR : - stack[++stackTop] = InterpretedFunction.createFunction(cx, frame.scope, - frame.fnOrScript, - indexReg); - continue Loop; - case Icode_CLOSURE_STMT : - initFunction(cx, frame.scope, frame.fnOrScript, indexReg); - continue Loop; - case Token.REGEXP : - stack[++stackTop] = frame.scriptRegExps[indexReg]; - continue Loop; - case Icode_LITERAL_NEW : - // indexReg: number of values in the literal - ++stackTop; - stack[stackTop] = new int[indexReg]; - ++stackTop; - stack[stackTop] = new Object[indexReg]; - sDbl[stackTop] = 0; - continue Loop; - case Icode_LITERAL_SET : { - Object value = stack[stackTop]; - if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - int i = (int)sDbl[stackTop]; - ((Object[])stack[stackTop])[i] = value; - sDbl[stackTop] = i + 1; - continue Loop; - } - case Icode_LITERAL_GETTER : { - Object value = stack[stackTop]; - --stackTop; - int i = (int)sDbl[stackTop]; - ((Object[])stack[stackTop])[i] = value; - ((int[])stack[stackTop - 1])[i] = -1; - sDbl[stackTop] = i + 1; - continue Loop; - } - case Icode_LITERAL_SETTER : { - Object value = stack[stackTop]; - --stackTop; - int i = (int)sDbl[stackTop]; - ((Object[])stack[stackTop])[i] = value; - ((int[])stack[stackTop - 1])[i] = +1; - sDbl[stackTop] = i + 1; - continue Loop; - } - case Token.ARRAYLIT : - case Icode_SPARE_ARRAYLIT : - case Token.OBJECTLIT : { - Object[] data = (Object[])stack[stackTop]; - --stackTop; - int[] getterSetters = (int[])stack[stackTop]; - Object val; - if (op == Token.OBJECTLIT) { - Object[] ids = (Object[])frame.idata.literalIds[indexReg]; - val = ScriptRuntime.newObjectLiteral(ids, data, getterSetters, cx, - frame.scope); - } else { - int[] skipIndexces = null; - if (op == Icode_SPARE_ARRAYLIT) { - skipIndexces = (int[])frame.idata.literalIds[indexReg]; - } - val = ScriptRuntime.newArrayLiteral(data, skipIndexces, cx, - frame.scope); - } - stack[stackTop] = val; - continue Loop; - } - case Icode_ENTERDQ : { - Object lhs = stack[stackTop]; - if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); - --stackTop; - frame.scope = ScriptRuntime.enterDotQuery(lhs, frame.scope); - continue Loop; - } - case Icode_LEAVEDQ : { - boolean valBln = stack_boolean(frame, stackTop); - Object x = ScriptRuntime.updateDotQuery(valBln, frame.scope); - if (x != null) { - stack[stackTop] = x; - frame.scope = ScriptRuntime.leaveDotQuery(frame.scope); - frame.pc += 2; - continue Loop; - } - // reset stack and PC to code after ENTERDQ - --stackTop; - break jumplessRun; - } - case Token.DEFAULTNAMESPACE : { - Object value = stack[stackTop]; - if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]); - stack[stackTop] = ScriptRuntime.setDefaultNamespace(value, cx); - continue Loop; - } - case Token.ESCXMLATTR : { - Object value = stack[stackTop]; - if (value != DBL_MRK) { - stack[stackTop] = ScriptRuntime.escapeAttributeValue(value, cx); - } - continue Loop; - } - case Token.ESCXMLTEXT : { - Object value = stack[stackTop]; - if (value != DBL_MRK) { - stack[stackTop] = ScriptRuntime.escapeTextValue(value, cx); - } - continue Loop; - } - case Icode_DEBUGGER: - if (frame.debuggerFrame != null) { - frame.debuggerFrame.onDebuggerStatement(cx); - } - break Loop; - case Icode_LINE : - frame.pcSourceLineStart = frame.pc; - if (frame.debuggerFrame != null) { - int line = getIndex(iCode, frame.pc); - frame.debuggerFrame.onLineChange(cx, line); - } - frame.pc += 2; - continue Loop; - case Icode_REG_IND_C0: - indexReg = 0; - continue Loop; - case Icode_REG_IND_C1: - indexReg = 1; - continue Loop; - case Icode_REG_IND_C2: - indexReg = 2; - continue Loop; - case Icode_REG_IND_C3: - indexReg = 3; - continue Loop; - case Icode_REG_IND_C4: - indexReg = 4; - continue Loop; - case Icode_REG_IND_C5: - indexReg = 5; - continue Loop; - case Icode_REG_IND1: - indexReg = 0xFF & iCode[frame.pc]; - ++frame.pc; - continue Loop; - case Icode_REG_IND2: - indexReg = getIndex(iCode, frame.pc); - frame.pc += 2; - continue Loop; - case Icode_REG_IND4: - indexReg = getInt(iCode, frame.pc); - frame.pc += 4; - continue Loop; - case Icode_REG_STR_C0: - stringReg = strings[0]; - continue Loop; - case Icode_REG_STR_C1: - stringReg = strings[1]; - continue Loop; - case Icode_REG_STR_C2: - stringReg = strings[2]; - continue Loop; - case Icode_REG_STR_C3: - stringReg = strings[3]; - continue Loop; - case Icode_REG_STR1: - stringReg = strings[0xFF & iCode[frame.pc]]; - ++frame.pc; - continue Loop; - case Icode_REG_STR2: - stringReg = strings[getIndex(iCode, frame.pc)]; - frame.pc += 2; - continue Loop; - case Icode_REG_STR4: - stringReg = strings[getInt(iCode, frame.pc)]; - frame.pc += 4; - continue Loop; - default : - dumpICode(frame.idata); - throw new RuntimeException( - "Unknown icode : "+op+" @ pc : "+(frame.pc-1)); -} // end of interpreter switch - - } // end of jumplessRun label block - - // This should be reachable only for jump implementation - // when pc points to encoded target offset - if (instructionCounting) { - addInstructionCount(cx, frame, 2); - } - int offset = getShort(iCode, frame.pc); - if (offset != 0) { - // -1 accounts for pc pointing to jump opcode + 1 - frame.pc += offset - 1; - } else { - frame.pc = frame.idata.longJumps. - getExistingInt(frame.pc); - } - if (instructionCounting) { - frame.pcPrevBranch = frame.pc; - } - continue Loop; - - } // end of Loop: for - - exitFrame(cx, frame, null); - interpreterResult = frame.result; - interpreterResultDbl = frame.resultDbl; - if (frame.parentFrame != null) { - frame = frame.parentFrame; - if (frame.frozen) { - frame = frame.cloneFrozen(); - } - setCallResult( - frame, interpreterResult, interpreterResultDbl); - interpreterResult = null; // Help GC - continue StateLoop; - } - break StateLoop; - - } // end of interpreter withoutExceptions: try - catch (Throwable ex) { - if (throwable != null) { - // This is serious bug and it is better to track it ASAP - ex.printStackTrace(System.err); - throw new IllegalStateException(); - } - throwable = ex; - } - - // This should be reachable only after above catch or from - // finally when it needs to propagate exception or from - // explicit throw - if (throwable == null) Kit.codeBug(); - - // Exception type - final int EX_CATCH_STATE = 2; // Can execute JS catch - final int EX_FINALLY_STATE = 1; // Can execute JS finally - final int EX_NO_JS_STATE = 0; // Terminate JS execution - - int exState; - ContinuationJump cjump = null; - - if (generatorState != null && - generatorState.operation == NativeGenerator.GENERATOR_CLOSE && - throwable == generatorState.value) - { - exState = EX_FINALLY_STATE; - } else if (throwable instanceof JavaScriptException) { - exState = EX_CATCH_STATE; - } else if (throwable instanceof EcmaError) { - // an offical ECMA error object, - exState = EX_CATCH_STATE; - } else if (throwable instanceof EvaluatorException) { - exState = EX_CATCH_STATE; - } else if (throwable instanceof RuntimeException) { - exState = cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) - ? EX_CATCH_STATE - : EX_FINALLY_STATE; - } else if (throwable instanceof Error) { - exState = cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) - ? EX_CATCH_STATE - : EX_NO_JS_STATE; - } else if (throwable instanceof ContinuationJump) { - // It must be ContinuationJump - exState = EX_FINALLY_STATE; - cjump = (ContinuationJump)throwable; - } else { - exState = cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) - ? EX_CATCH_STATE - : EX_FINALLY_STATE; - } - - if (instructionCounting) { - try { - addInstructionCount(cx, frame, EXCEPTION_COST); - } catch (RuntimeException ex) { - throwable = ex; - exState = EX_FINALLY_STATE; - } catch (Error ex) { - // Error from instruction counting - // => unconditionally terminate JS - throwable = ex; - cjump = null; - exState = EX_NO_JS_STATE; - } - } - if (frame.debuggerFrame != null - && throwable instanceof RuntimeException) - { - // Call debugger only for RuntimeException - RuntimeException rex = (RuntimeException)throwable; - try { - frame.debuggerFrame.onExceptionThrown(cx, rex); - } catch (Throwable ex) { - // Any exception from debugger - // => unconditionally terminate JS - throwable = ex; - cjump = null; - exState = EX_NO_JS_STATE; - } - } - - for (;;) { - if (exState != EX_NO_JS_STATE) { - boolean onlyFinally = (exState != EX_CATCH_STATE); - indexReg = getExceptionHandler(frame, onlyFinally); - if (indexReg >= 0) { - // We caught an exception, restart the loop - // with exception pending the processing at the loop - // start - continue StateLoop; - } - } - // No allowed exception handlers in this frame, unwind - // to parent and try to look there - - exitFrame(cx, frame, throwable); - - frame = frame.parentFrame; - if (frame == null) { break; } - if (cjump != null && cjump.branchFrame == frame) { - // Continuation branch point was hit, - // restart the state loop to reenter continuation - indexReg = -1; - continue StateLoop; - } - } - - // No more frames, rethrow the exception or deal with continuation - if (cjump != null) { - if (cjump.branchFrame != null) { - // The above loop should locate the top frame - Kit.codeBug(); - } - if (cjump.capturedFrame != null) { - // Restarting detached continuation - indexReg = -1; - continue StateLoop; - } - // Return continuation result to the caller - interpreterResult = cjump.result; - interpreterResultDbl = cjump.resultDbl; - throwable = null; - } - break StateLoop; - - } // end of StateLoop: for(;;) - - // Do cleanups/restorations before the final return or throw - - if (cx.previousInterpreterInvocations != null - && cx.previousInterpreterInvocations.size() != 0) - { - cx.lastInterpreterFrame - = cx.previousInterpreterInvocations.pop(); - } else { - // It was the last interpreter frame on the stack - cx.lastInterpreterFrame = null; - // Force GC of the value cx.previousInterpreterInvocations - cx.previousInterpreterInvocations = null; - } - - if (throwable != null) { - if (throwable instanceof RuntimeException) { - throw (RuntimeException)throwable; - } else { - // Must be instance of Error or code bug - throw (Error)throwable; - } - } - - return (interpreterResult != DBL_MRK) - ? interpreterResult - : ScriptRuntime.wrapNumber(interpreterResultDbl); - } - - private static CallFrame processThrowable(Context cx, Object throwable, - CallFrame frame, int indexReg, - boolean instructionCounting) - { - // Recovering from exception, indexReg contains - // the index of handler - - if (indexReg >= 0) { - // Normal exception handler, transfer - // control appropriately - - if (frame.frozen) { - // XXX Deal with exceptios!!! - frame = frame.cloneFrozen(); - } - - int[] table = frame.idata.itsExceptionTable; - - frame.pc = table[indexReg + EXCEPTION_HANDLER_SLOT]; - if (instructionCounting) { - frame.pcPrevBranch = frame.pc; - } - - frame.savedStackTop = frame.emptyStackTop; - int scopeLocal = frame.localShift - + table[indexReg - + EXCEPTION_SCOPE_SLOT]; - int exLocal = frame.localShift - + table[indexReg - + EXCEPTION_LOCAL_SLOT]; - frame.scope = (Scriptable)frame.stack[scopeLocal]; - frame.stack[exLocal] = throwable; - - throwable = null; - } else { - // Continuation restoration - ContinuationJump cjump = (ContinuationJump)throwable; - - // Clear throwable to indicate that exceptions are OK - throwable = null; - - if (cjump.branchFrame != frame) Kit.codeBug(); - - // Check that we have at least one frozen frame - // in the case of detached continuation restoration: - // unwind code ensure that - if (cjump.capturedFrame == null) Kit.codeBug(); - - // Need to rewind branchFrame, capturedFrame - // and all frames in between - int rewindCount = cjump.capturedFrame.frameIndex + 1; - if (cjump.branchFrame != null) { - rewindCount -= cjump.branchFrame.frameIndex; - } - - int enterCount = 0; - CallFrame[] enterFrames = null; - - CallFrame x = cjump.capturedFrame; - for (int i = 0; i != rewindCount; ++i) { - if (!x.frozen) Kit.codeBug(); - if (isFrameEnterExitRequired(x)) { - if (enterFrames == null) { - // Allocate enough space to store the rest - // of rewind frames in case all of them - // would require to enter - enterFrames = new CallFrame[rewindCount - - i]; - } - enterFrames[enterCount] = x; - ++enterCount; - } - x = x.parentFrame; - } - - while (enterCount != 0) { - // execute enter: walk enterFrames in the reverse - // order since they were stored starting from - // the capturedFrame, not branchFrame - --enterCount; - x = enterFrames[enterCount]; - enterFrame(cx, x, ScriptRuntime.emptyArgs, true); - } - - // Continuation jump is almost done: capturedFrame - // points to the call to the function that captured - // continuation, so clone capturedFrame and - // emulate return that function with the suplied result - frame = cjump.capturedFrame.cloneFrozen(); - setCallResult(frame, cjump.result, cjump.resultDbl); - // restart the execution - } - frame.throwable = throwable; - return frame; - } - - private static Object freezeGenerator(Context cx, CallFrame frame, - int stackTop, - GeneratorState generatorState) - { - if (generatorState.operation == NativeGenerator.GENERATOR_CLOSE) { - // Error: no yields when generator is closing - throw ScriptRuntime.typeError0("msg.yield.closing"); - } - // return to our caller (which should be a method of NativeGenerator) - frame.frozen = true; - frame.result = frame.stack[stackTop]; - frame.resultDbl = frame.sDbl[stackTop]; - frame.savedStackTop = stackTop; - frame.pc--; // we want to come back here when we resume - ScriptRuntime.exitActivationFunction(cx); - return (frame.result != UniqueTag.DOUBLE_MARK) - ? frame.result - : ScriptRuntime.wrapNumber(frame.resultDbl); - } - - private static Object thawGenerator(CallFrame frame, int stackTop, - GeneratorState generatorState, int op) - { - // we are resuming execution - frame.frozen = false; - int sourceLine = getIndex(frame.idata.itsICode, frame.pc); - frame.pc += 2; // skip line number data - if (generatorState.operation == NativeGenerator.GENERATOR_THROW) { - // processing a call to <generator>.throw(exception): must - // act as if exception was thrown from resumption point - return new JavaScriptException(generatorState.value, - frame.idata.itsSourceFile, - sourceLine); - } - if (generatorState.operation == NativeGenerator.GENERATOR_CLOSE) { - return generatorState.value; - } - if (generatorState.operation != NativeGenerator.GENERATOR_SEND) - throw Kit.codeBug(); - if (op == Token.YIELD) - frame.stack[stackTop] = generatorState.value; - return Scriptable.NOT_FOUND; - } - - private static CallFrame initFrameForApplyOrCall(Context cx, CallFrame frame, - int indexReg, Object[] stack, double[] sDbl, int stackTop, int op, - Scriptable calleeScope, IdFunctionObject ifun, - InterpretedFunction iApplyCallable) - { - Scriptable applyThis; - if (indexReg != 0) { - applyThis = ScriptRuntime.toObjectOrNull(cx, stack[stackTop + 2]); - } - else { - applyThis = null; - } - if (applyThis == null) { - // This covers the case of args[0] == (null|undefined) as well. - applyThis = ScriptRuntime.getTopCallScope(cx); - } - if(op == Icode_TAIL_CALL) { - exitFrame(cx, frame, null); - frame = frame.parentFrame; - } - else { - frame.savedStackTop = stackTop; - frame.savedCallOp = op; - } - CallFrame calleeFrame = new CallFrame(); - if(BaseFunction.isApply(ifun)) { - Object[] callArgs = indexReg < 2 ? ScriptRuntime.emptyArgs : - ScriptRuntime.getApplyArguments(cx, stack[stackTop + 3]); - initFrame(cx, calleeScope, applyThis, callArgs, null, 0, - callArgs.length, iApplyCallable, frame, calleeFrame); - } - else { - // Shift args left - for(int i = 1; i < indexReg; ++i) { - stack[stackTop + 1 + i] = stack[stackTop + 2 + i]; - sDbl[stackTop + 1 + i] = sDbl[stackTop + 2 + i]; - } - int argCount = indexReg < 2 ? 0 : indexReg - 1; - initFrame(cx, calleeScope, applyThis, stack, sDbl, stackTop + 2, - argCount, iApplyCallable, frame, calleeFrame); - } - - frame = calleeFrame; - return frame; - } - - private static void initFrame(Context cx, Scriptable callerScope, - Scriptable thisObj, - Object[] args, double[] argsDbl, - int argShift, int argCount, - InterpretedFunction fnOrScript, - CallFrame parentFrame, CallFrame frame) - { - InterpreterData idata = fnOrScript.idata; - - boolean useActivation = idata.itsNeedsActivation; - DebugFrame debuggerFrame = null; - if (cx.debugger != null) { - debuggerFrame = cx.debugger.getFrame(cx, idata); - if (debuggerFrame != null) { - useActivation = true; - } - } - - if (useActivation) { - // Copy args to new array to pass to enterActivationFunction - // or debuggerFrame.onEnter - if (argsDbl != null) { - args = getArgsArray(args, argsDbl, argShift, argCount); - } - argShift = 0; - argsDbl = null; - } - - Scriptable scope; - if (idata.itsFunctionType != 0) { - if (!idata.useDynamicScope) { - scope = fnOrScript.getParentScope(); - } else { - scope = callerScope; - } - - if (useActivation) { - scope = ScriptRuntime.createFunctionActivation( - fnOrScript, scope, args); - } - } else { - scope = callerScope; - ScriptRuntime.initScript(fnOrScript, thisObj, cx, scope, - fnOrScript.idata.evalScriptFlag); - } - - if (idata.itsNestedFunctions != null) { - if (idata.itsFunctionType != 0 && !idata.itsNeedsActivation) - Kit.codeBug(); - for (int i = 0; i < idata.itsNestedFunctions.length; i++) { - InterpreterData fdata = idata.itsNestedFunctions[i]; - if (fdata.itsFunctionType == FunctionNode.FUNCTION_STATEMENT) { - initFunction(cx, scope, fnOrScript, i); - } - } - } - - Scriptable[] scriptRegExps = null; - if (idata.itsRegExpLiterals != null) { - // Wrapped regexps for functions are stored in - // InterpretedFunction - // but for script which should not contain references to scope - // the regexps re-wrapped during each script execution - if (idata.itsFunctionType != 0) { - scriptRegExps = fnOrScript.functionRegExps; - } else { - scriptRegExps = fnOrScript.createRegExpWraps(cx, scope); - } - } - - // Initialize args, vars, locals and stack - - int emptyStackTop = idata.itsMaxVars + idata.itsMaxLocals - 1; - int maxFrameArray = idata.itsMaxFrameArray; - if (maxFrameArray != emptyStackTop + idata.itsMaxStack + 1) - Kit.codeBug(); - - Object[] stack; - int[] stackAttributes; - double[] sDbl; - boolean stackReuse; - if (frame.stack != null && maxFrameArray <= frame.stack.length) { - // Reuse stacks from old frame - stackReuse = true; - stack = frame.stack; - stackAttributes = frame.stackAttributes; - sDbl = frame.sDbl; - } else { - stackReuse = false; - stack = new Object[maxFrameArray]; - stackAttributes = new int[maxFrameArray]; - sDbl = new double[maxFrameArray]; - } - - int varCount = idata.getParamAndVarCount(); - for (int i = 0; i < varCount; i++) { - if (idata.getParamOrVarConst(i)) - stackAttributes[i] = ScriptableObject.CONST; - } - int definedArgs = idata.argCount; - if (definedArgs > argCount) { definedArgs = argCount; } - - // Fill the frame structure - - frame.parentFrame = parentFrame; - frame.frameIndex = (parentFrame == null) - ? 0 : parentFrame.frameIndex + 1; - if(frame.frameIndex > cx.getMaximumInterpreterStackDepth()) - { - throw Context.reportRuntimeError("Exceeded maximum stack depth"); - } - frame.frozen = false; - - frame.fnOrScript = fnOrScript; - frame.idata = idata; - - frame.stack = stack; - frame.stackAttributes = stackAttributes; - frame.sDbl = sDbl; - frame.varSource = frame; - frame.localShift = idata.itsMaxVars; - frame.emptyStackTop = emptyStackTop; - - frame.debuggerFrame = debuggerFrame; - frame.useActivation = useActivation; - - frame.thisObj = thisObj; - frame.scriptRegExps = scriptRegExps; - - // Initialize initial values of variables that change during - // interpretation. - frame.result = Undefined.instance; - frame.pc = 0; - frame.pcPrevBranch = 0; - frame.pcSourceLineStart = idata.firstLinePC; - frame.scope = scope; - - frame.savedStackTop = emptyStackTop; - frame.savedCallOp = 0; - - System.arraycopy(args, argShift, stack, 0, definedArgs); - if (argsDbl != null) { - System.arraycopy(argsDbl, argShift, sDbl, 0, definedArgs); - } - for (int i = definedArgs; i != idata.itsMaxVars; ++i) { - stack[i] = Undefined.instance; - } - if (stackReuse) { - // Clean the stack part and space beyond stack if any - // of the old array to allow to GC objects there - for (int i = emptyStackTop + 1; i != stack.length; ++i) { - stack[i] = null; - } - } - - enterFrame(cx, frame, args, false); - } - - private static boolean isFrameEnterExitRequired(CallFrame frame) - { - return frame.debuggerFrame != null || frame.idata.itsNeedsActivation; - } - - private static void enterFrame(Context cx, CallFrame frame, Object[] args, - boolean continuationRestart) - { - boolean usesActivation = frame.idata.itsNeedsActivation; - boolean isDebugged = frame.debuggerFrame != null; - if(usesActivation || isDebugged) { - Scriptable scope = frame.scope; - if(scope == null) { - Kit.codeBug(); - } else if (continuationRestart) { - // Walk the parent chain of frame.scope until a NativeCall is - // found. Normally, frame.scope is a NativeCall when called - // from initFrame() for a debugged or activatable function. - // However, when called from interpretLoop() as part of - // restarting a continuation, it can also be a NativeWith if - // the continuation was captured within a "with" or "catch" - // block ("catch" implicitly uses NativeWith to create a scope - // to expose the exception variable). - for(;;) { - if(scope instanceof NativeWith) { - scope = scope.getParentScope(); - if (scope == null || (frame.parentFrame != null && - frame.parentFrame.scope == scope)) - { - // If we get here, we didn't find a NativeCall in - // the call chain before reaching parent frame's - // scope. This should not be possible. - Kit.codeBug(); - break; // Never reached, but keeps the static analyzer happy about "scope" not being null 5 lines above. - } - } - else { - break; - } - } - } - if (isDebugged) { - frame.debuggerFrame.onEnter(cx, scope, frame.thisObj, args); - } - // Enter activation only when itsNeedsActivation true, - // since debugger should not interfere with activation - // chaining - if (usesActivation) { - ScriptRuntime.enterActivationFunction(cx, scope); - } - } - } - - private static void exitFrame(Context cx, CallFrame frame, - Object throwable) - { - if (frame.idata.itsNeedsActivation) { - ScriptRuntime.exitActivationFunction(cx); - } - - if (frame.debuggerFrame != null) { - try { - if (throwable instanceof Throwable) { - frame.debuggerFrame.onExit(cx, true, throwable); - } else { - Object result; - ContinuationJump cjump = (ContinuationJump)throwable; - if (cjump == null) { - result = frame.result; - } else { - result = cjump.result; - } - if (result == UniqueTag.DOUBLE_MARK) { - double resultDbl; - if (cjump == null) { - resultDbl = frame.resultDbl; - } else { - resultDbl = cjump.resultDbl; - } - result = ScriptRuntime.wrapNumber(resultDbl); - } - frame.debuggerFrame.onExit(cx, false, result); - } - } catch (Throwable ex) { - System.err.println( -"RHINO USAGE WARNING: onExit terminated with exception"); - ex.printStackTrace(System.err); - } - } - } - - private static void setCallResult(CallFrame frame, - Object callResult, - double callResultDbl) - { - if (frame.savedCallOp == Token.CALL) { - frame.stack[frame.savedStackTop] = callResult; - frame.sDbl[frame.savedStackTop] = callResultDbl; - } else if (frame.savedCallOp == Token.NEW) { - // If construct returns scriptable, - // then it replaces on stack top saved original instance - // of the object. - if (callResult instanceof Scriptable) { - frame.stack[frame.savedStackTop] = callResult; - } - } else { - Kit.codeBug(); - } - frame.savedCallOp = 0; - } - - private static void captureContinuation(Context cx, CallFrame frame, - int stackTop) - { - Continuation c = new Continuation(); - ScriptRuntime.setObjectProtoAndParent( - c, ScriptRuntime.getTopCallScope(cx)); - - // Make sure that all frames upstack frames are frozen - CallFrame x = frame.parentFrame; - while (x != null && !x.frozen) { - x.frozen = true; - // Allow to GC unused stack space - for (int i = x.savedStackTop + 1; i != x.stack.length; ++i) { - // Allow to GC unused stack space - x.stack[i] = null; - x.stackAttributes[i] = ScriptableObject.EMPTY; - } - if (x.savedCallOp == Token.CALL) { - // the call will always overwrite the stack top with the result - x.stack[x.savedStackTop] = null; - } else { - if (x.savedCallOp != Token.NEW) Kit.codeBug(); - // the new operator uses stack top to store the constructed - // object so it shall not be cleared: see comments in - // setCallResult - } - x = x.parentFrame; - } - - c.initImplementation(frame.parentFrame); - frame.stack[stackTop] = c; - } - - private static int stack_int32(CallFrame frame, int i) - { - Object x = frame.stack[i]; - double value; - if (x == UniqueTag.DOUBLE_MARK) { - value = frame.sDbl[i]; - } else { - value = ScriptRuntime.toNumber(x); - } - return ScriptRuntime.toInt32(value); - } - - private static double stack_double(CallFrame frame, int i) - { - Object x = frame.stack[i]; - if (x != UniqueTag.DOUBLE_MARK) { - return ScriptRuntime.toNumber(x); - } else { - return frame.sDbl[i]; - } - } - - private static boolean stack_boolean(CallFrame frame, int i) - { - Object x = frame.stack[i]; - if (x == Boolean.TRUE) { - return true; - } else if (x == Boolean.FALSE) { - return false; - } else if (x == UniqueTag.DOUBLE_MARK) { - double d = frame.sDbl[i]; - return d == d && d != 0.0; - } else if (x == null || x == Undefined.instance) { - return false; - } else if (x instanceof Number) { - double d = ((Number)x).doubleValue(); - return (d == d && d != 0.0); - } else if (x instanceof Boolean) { - return ((Boolean)x).booleanValue(); - } else { - return ScriptRuntime.toBoolean(x); - } - } - - private static void do_add(Object[] stack, double[] sDbl, int stackTop, - Context cx) - { - Object rhs = stack[stackTop + 1]; - Object lhs = stack[stackTop]; - double d; - boolean leftRightOrder; - if (rhs == UniqueTag.DOUBLE_MARK) { - d = sDbl[stackTop + 1]; - if (lhs == UniqueTag.DOUBLE_MARK) { - sDbl[stackTop] += d; - return; - } - leftRightOrder = true; - // fallthrough to object + number code - } else if (lhs == UniqueTag.DOUBLE_MARK) { - d = sDbl[stackTop]; - lhs = rhs; - leftRightOrder = false; - // fallthrough to object + number code - } else { - if (lhs instanceof Scriptable || rhs instanceof Scriptable) { - stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx); - } else if (lhs instanceof String) { - String lstr = (String)lhs; - String rstr = ScriptRuntime.toString(rhs); - stack[stackTop] = lstr.concat(rstr); - } else if (rhs instanceof String) { - String lstr = ScriptRuntime.toString(lhs); - String rstr = (String)rhs; - stack[stackTop] = lstr.concat(rstr); - } else { - double lDbl = (lhs instanceof Number) - ? ((Number)lhs).doubleValue() : ScriptRuntime.toNumber(lhs); - double rDbl = (rhs instanceof Number) - ? ((Number)rhs).doubleValue() : ScriptRuntime.toNumber(rhs); - stack[stackTop] = UniqueTag.DOUBLE_MARK; - sDbl[stackTop] = lDbl + rDbl; - } - return; - } - - // handle object(lhs) + number(d) code - if (lhs instanceof Scriptable) { - rhs = ScriptRuntime.wrapNumber(d); - if (!leftRightOrder) { - Object tmp = lhs; - lhs = rhs; - rhs = tmp; - } - stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx); - } else if (lhs instanceof String) { - String lstr = (String)lhs; - String rstr = ScriptRuntime.toString(d); - if (leftRightOrder) { - stack[stackTop] = lstr.concat(rstr); - } else { - stack[stackTop] = rstr.concat(lstr); - } - } else { - double lDbl = (lhs instanceof Number) - ? ((Number)lhs).doubleValue() : ScriptRuntime.toNumber(lhs); - stack[stackTop] = UniqueTag.DOUBLE_MARK; - sDbl[stackTop] = lDbl + d; - } - } - - private static Object[] getArgsArray(Object[] stack, double[] sDbl, - int shift, int count) - { - if (count == 0) { - return ScriptRuntime.emptyArgs; - } - Object[] args = new Object[count]; - for (int i = 0; i != count; ++i, ++shift) { - Object val = stack[shift]; - if (val == UniqueTag.DOUBLE_MARK) { - val = ScriptRuntime.wrapNumber(sDbl[shift]); - } - args[i] = val; - } - return args; - } - - private static void addInstructionCount(Context cx, CallFrame frame, - int extra) - { - cx.instructionCount += frame.pc - frame.pcPrevBranch + extra; - if (cx.instructionCount > cx.instructionThreshold) { - cx.observeInstructionCount(cx.instructionCount); - cx.instructionCount = 0; - } - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterpreterData.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterpreterData.java deleted file mode 100644 index 7435b10..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/InterpreterData.java +++ /dev/null @@ -1,192 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Bob Jervis - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Serializable; - -import org.mozilla.javascript.debug.DebuggableScript; - -final class InterpreterData implements Serializable, DebuggableScript -{ - static final long serialVersionUID = 5067677351589230234L; - - static final int INITIAL_MAX_ICODE_LENGTH = 1024; - static final int INITIAL_STRINGTABLE_SIZE = 64; - static final int INITIAL_NUMBERTABLE_SIZE = 64; - - InterpreterData(int languageVersion, - String sourceFile, String encodedSource) - { - this.languageVersion = languageVersion; - this.itsSourceFile = sourceFile; - this.encodedSource = encodedSource; - - init(); - } - - InterpreterData(InterpreterData parent) - { - this.parentData = parent; - this.languageVersion = parent.languageVersion; - this.itsSourceFile = parent.itsSourceFile; - this.encodedSource = parent.encodedSource; - - init(); - } - - private void init() - { - itsICode = new byte[INITIAL_MAX_ICODE_LENGTH]; - itsStringTable = new String[INITIAL_STRINGTABLE_SIZE]; - } - - String itsName; - String itsSourceFile; - boolean itsNeedsActivation; - int itsFunctionType; - - String[] itsStringTable; - double[] itsDoubleTable; - InterpreterData[] itsNestedFunctions; - Object[] itsRegExpLiterals; - - byte[] itsICode; - - int[] itsExceptionTable; - - int itsMaxVars; - int itsMaxLocals; - int itsMaxStack; - int itsMaxFrameArray; - - // see comments in NativeFuncion for definition of argNames and argCount - String[] argNames; - boolean[] argIsConst; - int argCount; - - int itsMaxCalleeArgs; - - String encodedSource; - int encodedSourceStart; - int encodedSourceEnd; - - int languageVersion; - - boolean useDynamicScope; - - boolean topLevel; - - Object[] literalIds; - - UintMap longJumps; - - int firstLinePC = -1; // PC for the first LINE icode - - InterpreterData parentData; - - boolean evalScriptFlag; // true if script corresponds to eval() code - - public boolean isTopLevel() - { - return topLevel; - } - - public boolean isFunction() - { - return itsFunctionType != 0; - } - - public String getFunctionName() - { - return itsName; - } - - public int getParamCount() - { - return argCount; - } - - public int getParamAndVarCount() - { - return argNames.length; - } - - public String getParamOrVarName(int index) - { - return argNames[index]; - } - - public boolean getParamOrVarConst(int index) - { - return argIsConst[index]; - } - - public String getSourceName() - { - return itsSourceFile; - } - - public boolean isGeneratedScript() - { - return ScriptRuntime.isGeneratedScript(itsSourceFile); - } - - public int[] getLineNumbers() - { - return Interpreter.getLineNumbers(this); - } - - public int getFunctionCount() - { - return (itsNestedFunctions == null) ? 0 : itsNestedFunctions.length; - } - - public DebuggableScript getFunction(int index) - { - return itsNestedFunctions[index]; - } - - public DebuggableScript getParent() - { - return parentData; - } - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/JavaAdapter.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/JavaAdapter.java deleted file mode 100644 index 6e0a827..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/JavaAdapter.java +++ /dev/null @@ -1,1129 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Patrick Beard - * Norris Boyd - * Igor Bukanov - * Mike McCabe - * Matthias Radestock - * Andi Vajda - * Andrew Wason - * Kemal Bayram - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import org.mozilla.classfile.*; -import java.lang.reflect.*; -import java.io.*; -import java.security.*; -import java.util.*; - -public final class JavaAdapter implements IdFunctionCall -{ - /** - * Provides a key with which to distinguish previously generated - * adapter classes stored in a hash table. - */ - static class JavaAdapterSignature - { - Class superClass; - Class[] interfaces; - ObjToIntMap names; - - JavaAdapterSignature(Class superClass, Class[] interfaces, - ObjToIntMap names) - { - this.superClass = superClass; - this.interfaces = interfaces; - this.names = names; - } - - public boolean equals(Object obj) - { - if (!(obj instanceof JavaAdapterSignature)) - return false; - JavaAdapterSignature sig = (JavaAdapterSignature) obj; - if (superClass != sig.superClass) - return false; - if (interfaces != sig.interfaces) { - if (interfaces.length != sig.interfaces.length) - return false; - for (int i=0; i < interfaces.length; i++) - if (interfaces[i] != sig.interfaces[i]) - return false; - } - if (names.size() != sig.names.size()) - return false; - ObjToIntMap.Iterator iter = new ObjToIntMap.Iterator(names); - for (iter.start(); !iter.done(); iter.next()) { - String name = (String)iter.getKey(); - int arity = iter.getValue(); - if (arity != names.get(name, arity + 1)) - return false; - } - return true; - } - - public int hashCode() - { - return superClass.hashCode() - | (0x9e3779b9 * (names.size() | (interfaces.length << 16))); - } - } - - public static void init(Context cx, Scriptable scope, boolean sealed) - { - JavaAdapter obj = new JavaAdapter(); - IdFunctionObject ctor = new IdFunctionObject(obj, FTAG, Id_JavaAdapter, - "JavaAdapter", 1, scope); - ctor.markAsConstructor(null); - if (sealed) { - ctor.sealObject(); - } - ctor.exportAsScopeProperty(); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (f.hasTag(FTAG)) { - if (f.methodId() == Id_JavaAdapter) { - return js_createAdapter(cx, scope, args); - } - } - throw f.unknown(); - } - - public static Object convertResult(Object result, Class c) - { - if (result == Undefined.instance && - (c != ScriptRuntime.ObjectClass && - c != ScriptRuntime.StringClass)) - { - // Avoid an error for an undefined value; return null instead. - return null; - } - return Context.jsToJava(result, c); - } - - public static Scriptable createAdapterWrapper(Scriptable obj, - Object adapter) - { - Scriptable scope = ScriptableObject.getTopLevelScope(obj); - NativeJavaObject res = new NativeJavaObject(scope, adapter, null, true); - res.setPrototype(obj); - return res; - } - - public static Object getAdapterSelf(Class adapterClass, Object adapter) - throws NoSuchFieldException, IllegalAccessException - { - Field self = adapterClass.getDeclaredField("self"); - return self.get(adapter); - } - - static Object js_createAdapter(Context cx, Scriptable scope, Object[] args) - { - int N = args.length; - if (N == 0) { - throw ScriptRuntime.typeError0("msg.adapter.zero.args"); - } - - Class superClass = null; - Class[] intfs = new Class[N - 1]; - int interfaceCount = 0; - for (int i = 0; i != N - 1; ++i) { - Object arg = args[i]; - if (!(arg instanceof NativeJavaClass)) { - throw ScriptRuntime.typeError2("msg.not.java.class.arg", - String.valueOf(i), - ScriptRuntime.toString(arg)); - } - Class c = ((NativeJavaClass) arg).getClassObject(); - if (!c.isInterface()) { - if (superClass != null) { - throw ScriptRuntime.typeError2("msg.only.one.super", - superClass.getName(), c.getName()); - } - superClass = c; - } else { - intfs[interfaceCount++] = c; - } - } - - if (superClass == null) - superClass = ScriptRuntime.ObjectClass; - - Class[] interfaces = new Class[interfaceCount]; - System.arraycopy(intfs, 0, interfaces, 0, interfaceCount); - Scriptable obj = ScriptRuntime.toObject(cx, scope, args[N - 1]); - - Class adapterClass = getAdapterClass(scope, superClass, interfaces, - obj); - - Class[] ctorParms = { - ScriptRuntime.ContextFactoryClass, - ScriptRuntime.ScriptableClass - }; - Object[] ctorArgs = { cx.getFactory(), obj }; - try { - Object adapter = adapterClass.getConstructor(ctorParms). - newInstance(ctorArgs); - return getAdapterSelf(adapterClass, adapter); - } catch (Exception ex) { - throw Context.throwAsScriptRuntimeEx(ex); - } - } - - // Needed by NativeJavaObject serializer - public static void writeAdapterObject(Object javaObject, - ObjectOutputStream out) - throws IOException - { - Class cl = javaObject.getClass(); - out.writeObject(cl.getSuperclass().getName()); - - Class[] interfaces = cl.getInterfaces(); - String[] interfaceNames = new String[interfaces.length]; - - for (int i=0; i < interfaces.length; i++) - interfaceNames[i] = interfaces[i].getName(); - - out.writeObject(interfaceNames); - - try { - Object delegee = cl.getField("delegee").get(javaObject); - out.writeObject(delegee); - return; - } catch (IllegalAccessException e) { - } catch (NoSuchFieldException e) { - } - throw new IOException(); - } - - // Needed by NativeJavaObject de-serializer - public static Object readAdapterObject(Scriptable self, - ObjectInputStream in) - throws IOException, ClassNotFoundException - { - ContextFactory factory; - Context cx = Context.getCurrentContext(); - if (cx != null) { - factory = cx.getFactory(); - } else { - factory = null; - } - - Class superClass = Class.forName((String)in.readObject()); - - String[] interfaceNames = (String[])in.readObject(); - Class[] interfaces = new Class[interfaceNames.length]; - - for (int i=0; i < interfaceNames.length; i++) - interfaces[i] = Class.forName(interfaceNames[i]); - - Scriptable delegee = (Scriptable)in.readObject(); - - Class adapterClass = getAdapterClass(self, superClass, interfaces, - delegee); - - Class[] ctorParms = { - ScriptRuntime.ContextFactoryClass, - ScriptRuntime.ScriptableClass, - ScriptRuntime.ScriptableClass - }; - Object[] ctorArgs = { factory, delegee, self }; - try { - return adapterClass.getConstructor(ctorParms).newInstance(ctorArgs); - } catch(InstantiationException e) { - } catch(IllegalAccessException e) { - } catch(InvocationTargetException e) { - } catch(NoSuchMethodException e) { - } - - throw new ClassNotFoundException("adapter"); - } - - private static ObjToIntMap getObjectFunctionNames(Scriptable obj) - { - Object[] ids = ScriptableObject.getPropertyIds(obj); - ObjToIntMap map = new ObjToIntMap(ids.length); - for (int i = 0; i != ids.length; ++i) { - if (!(ids[i] instanceof String)) - continue; - String id = (String) ids[i]; - Object value = ScriptableObject.getProperty(obj, id); - if (value instanceof Function) { - Function f = (Function)value; - int length = ScriptRuntime.toInt32( - ScriptableObject.getProperty(f, "length")); - if (length < 0) { - length = 0; - } - map.put(id, length); - } - } - return map; - } - - private static Class getAdapterClass(Scriptable scope, Class superClass, - Class[] interfaces, Scriptable obj) - { - ClassCache cache = ClassCache.get(scope); - Map<JavaAdapterSignature,Class<?>> generated - = cache.getInterfaceAdapterCacheMap(); - - ObjToIntMap names = getObjectFunctionNames(obj); - JavaAdapterSignature sig; - sig = new JavaAdapterSignature(superClass, interfaces, names); - Class<?> adapterClass = generated.get(sig); - if (adapterClass == null) { - String adapterName = "adapter" - + cache.newClassSerialNumber(); - byte[] code = createAdapterCode(names, adapterName, - superClass, interfaces, null); - - adapterClass = loadAdapterClass(adapterName, code); - if (cache.isCachingEnabled()) { - generated.put(sig, adapterClass); - } - } - return adapterClass; - } - - public static byte[] createAdapterCode(ObjToIntMap functionNames, - String adapterName, - Class superClass, - Class[] interfaces, - String scriptClassName) - { - ClassFileWriter cfw = new ClassFileWriter(adapterName, - superClass.getName(), - "<adapter>"); - cfw.addField("factory", "Lorg/mozilla/javascript/ContextFactory;", - (short) (ClassFileWriter.ACC_PUBLIC | - ClassFileWriter.ACC_FINAL)); - cfw.addField("delegee", "Lorg/mozilla/javascript/Scriptable;", - (short) (ClassFileWriter.ACC_PUBLIC | - ClassFileWriter.ACC_FINAL)); - cfw.addField("self", "Lorg/mozilla/javascript/Scriptable;", - (short) (ClassFileWriter.ACC_PUBLIC | - ClassFileWriter.ACC_FINAL)); - int interfacesCount = interfaces == null ? 0 : interfaces.length; - for (int i=0; i < interfacesCount; i++) { - if (interfaces[i] != null) - cfw.addInterface(interfaces[i].getName()); - } - - String superName = superClass.getName().replace('.', '/'); - generateCtor(cfw, adapterName, superName); - generateSerialCtor(cfw, adapterName, superName); - if (scriptClassName != null) - generateEmptyCtor(cfw, adapterName, superName, scriptClassName); - - ObjToIntMap generatedOverrides = new ObjToIntMap(); - ObjToIntMap generatedMethods = new ObjToIntMap(); - - // generate methods to satisfy all specified interfaces. - for (int i = 0; i < interfacesCount; i++) { - Method[] methods = interfaces[i].getMethods(); - for (int j = 0; j < methods.length; j++) { - Method method = methods[j]; - int mods = method.getModifiers(); - if (Modifier.isStatic(mods) || Modifier.isFinal(mods)) { - continue; - } - String methodName = method.getName(); - Class[] argTypes = method.getParameterTypes(); - if (!functionNames.has(methodName)) { - try { - superClass.getMethod(methodName, argTypes); - // The class we're extending implements this method and - // the JavaScript object doesn't have an override. See - // bug 61226. - continue; - } catch (NoSuchMethodException e) { - // Not implemented by superclass; fall through - } - } - // make sure to generate only one instance of a particular - // method/signature. - String methodSignature = getMethodSignature(method, argTypes); - String methodKey = methodName + methodSignature; - if (! generatedOverrides.has(methodKey)) { - generateMethod(cfw, adapterName, methodName, - argTypes, method.getReturnType()); - generatedOverrides.put(methodKey, 0); - generatedMethods.put(methodName, 0); - } - } - } - - // Now, go through the superclass's methods, checking for abstract - // methods or additional methods to override. - - // generate any additional overrides that the object might contain. - Method[] methods = getOverridableMethods(superClass); - for (int j = 0; j < methods.length; j++) { - Method method = methods[j]; - int mods = method.getModifiers(); - // if a method is marked abstract, must implement it or the - // resulting class won't be instantiable. otherwise, if the object - // has a property of the same name, then an override is intended. - boolean isAbstractMethod = Modifier.isAbstract(mods); - String methodName = method.getName(); - if (isAbstractMethod || functionNames.has(methodName)) { - // make sure to generate only one instance of a particular - // method/signature. - Class[] argTypes = method.getParameterTypes(); - String methodSignature = getMethodSignature(method, argTypes); - String methodKey = methodName + methodSignature; - if (! generatedOverrides.has(methodKey)) { - generateMethod(cfw, adapterName, methodName, - argTypes, method.getReturnType()); - generatedOverrides.put(methodKey, 0); - generatedMethods.put(methodName, 0); - - // if a method was overridden, generate a "super$method" - // which lets the delegate call the superclass' version. - if (!isAbstractMethod) { - generateSuper(cfw, adapterName, superName, - methodName, methodSignature, - argTypes, method.getReturnType()); - } - } - } - } - - // Generate Java methods for remaining properties that are not - // overrides. - ObjToIntMap.Iterator iter = new ObjToIntMap.Iterator(functionNames); - for (iter.start(); !iter.done(); iter.next()) { - String functionName = (String)iter.getKey(); - if (generatedMethods.has(functionName)) - continue; - int length = iter.getValue(); - Class[] parms = new Class[length]; - for (int k=0; k < length; k++) - parms[k] = ScriptRuntime.ObjectClass; - generateMethod(cfw, adapterName, functionName, parms, - ScriptRuntime.ObjectClass); - } - return cfw.toByteArray(); - } - - static Method[] getOverridableMethods(Class c) - { - ArrayList<Method> list = new ArrayList<Method>(); - HashSet<String> skip = new HashSet<String>(); - while (c != null) { - Method[] methods = c.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - String methodKey = methods[i].getName() + - getMethodSignature(methods[i], - methods[i].getParameterTypes()); - if (skip.contains(methodKey)) - continue; // skip this method - int mods = methods[i].getModifiers(); - if (Modifier.isStatic(mods)) - continue; - if (Modifier.isFinal(mods)) { - // Make sure we don't add a final method to the list - // of overridable methods. - skip.add(methodKey); - continue; - } - if (Modifier.isPublic(mods) || Modifier.isProtected(mods)) { - list.add(methods[i]); - skip.add(methodKey); - } - } - c = c.getSuperclass(); - } - return list.toArray(new Method[list.size()]); - } - - static Class loadAdapterClass(String className, byte[] classBytes) - { - Object staticDomain; - Class domainClass = SecurityController.getStaticSecurityDomainClass(); - if(domainClass == CodeSource.class || domainClass == ProtectionDomain.class) { - ProtectionDomain protectionDomain = JavaAdapter.class.getProtectionDomain(); - if(domainClass == CodeSource.class) { - staticDomain = protectionDomain == null ? null : protectionDomain.getCodeSource(); - } - else { - staticDomain = protectionDomain; - } - } - else { - staticDomain = null; - } - GeneratedClassLoader loader = SecurityController.createLoader(null, - staticDomain); - Class result = loader.defineClass(className, classBytes); - loader.linkClass(result); - return result; - } - - public static Function getFunction(Scriptable obj, String functionName) - { - Object x = ScriptableObject.getProperty(obj, functionName); - if (x == Scriptable.NOT_FOUND) { - // This method used to swallow the exception from calling - // an undefined method. People have come to depend on this - // somewhat dubious behavior. It allows people to avoid - // implementing listener methods that they don't care about, - // for instance. - return null; - } - if (!(x instanceof Function)) - throw ScriptRuntime.notFunctionError(x, functionName); - - return (Function)x; - } - - /** - * Utility method which dynamically binds a Context to the current thread, - * if none already exists. - */ - public static Object callMethod(ContextFactory factory, - final Scriptable thisObj, - final Function f, final Object[] args, - final long argsToWrap) - { - if (f == null) { - // See comments in getFunction - return Undefined.instance; - } - if (factory == null) { - factory = ContextFactory.getGlobal(); - } - - final Scriptable scope = f.getParentScope(); - if (argsToWrap == 0) { - return Context.call(factory, f, scope, thisObj, args); - } - - Context cx = Context.getCurrentContext(); - if (cx != null) { - return doCall(cx, scope, thisObj, f, args, argsToWrap); - } else { - return factory.call(new ContextAction() { - public Object run(Context cx) - { - return doCall(cx, scope, thisObj, f, args, argsToWrap); - } - }); - } - } - - private static Object doCall(Context cx, Scriptable scope, - Scriptable thisObj, Function f, - Object[] args, long argsToWrap) - { - // Wrap the rest of objects - for (int i = 0; i != args.length; ++i) { - if (0 != (argsToWrap & (1 << i))) { - Object arg = args[i]; - if (!(arg instanceof Scriptable)) { - args[i] = cx.getWrapFactory().wrap(cx, scope, arg, - null); - } - } - } - return f.call(cx, scope, thisObj, args); - } - - public static Scriptable runScript(final Script script) - { - return (Scriptable)Context.call(new ContextAction() { - public Object run(Context cx) - { - ScriptableObject global = ScriptRuntime.getGlobal(cx); - script.exec(cx, global); - return global; - } - }); - } - - private static void generateCtor(ClassFileWriter cfw, String adapterName, - String superName) - { - cfw.startMethod("<init>", - "(Lorg/mozilla/javascript/ContextFactory;" - +"Lorg/mozilla/javascript/Scriptable;)V", - ClassFileWriter.ACC_PUBLIC); - - // Invoke base class constructor - cfw.add(ByteCode.ALOAD_0); // this - cfw.addInvoke(ByteCode.INVOKESPECIAL, superName, "<init>", "()V"); - - // Save parameter in instance variable "factory" - cfw.add(ByteCode.ALOAD_0); // this - cfw.add(ByteCode.ALOAD_1); // first arg: ContextFactory instance - cfw.add(ByteCode.PUTFIELD, adapterName, "factory", - "Lorg/mozilla/javascript/ContextFactory;"); - - // Save parameter in instance variable "delegee" - cfw.add(ByteCode.ALOAD_0); // this - cfw.add(ByteCode.ALOAD_2); // second arg: Scriptable delegee - cfw.add(ByteCode.PUTFIELD, adapterName, "delegee", - "Lorg/mozilla/javascript/Scriptable;"); - - cfw.add(ByteCode.ALOAD_0); // this for the following PUTFIELD for self - // create a wrapper object to be used as "this" in method calls - cfw.add(ByteCode.ALOAD_2); // the Scriptable delegee - cfw.add(ByteCode.ALOAD_0); // this - cfw.addInvoke(ByteCode.INVOKESTATIC, - "org/mozilla/javascript/JavaAdapter", - "createAdapterWrapper", - "(Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/Object;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.add(ByteCode.PUTFIELD, adapterName, "self", - "Lorg/mozilla/javascript/Scriptable;"); - - cfw.add(ByteCode.RETURN); - cfw.stopMethod((short)3); // 3: this + factory + delegee - } - - private static void generateSerialCtor(ClassFileWriter cfw, - String adapterName, - String superName) - { - cfw.startMethod("<init>", - "(Lorg/mozilla/javascript/ContextFactory;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Scriptable;" - +")V", - ClassFileWriter.ACC_PUBLIC); - - // Invoke base class constructor - cfw.add(ByteCode.ALOAD_0); // this - cfw.addInvoke(ByteCode.INVOKESPECIAL, superName, "<init>", "()V"); - - // Save parameter in instance variable "factory" - cfw.add(ByteCode.ALOAD_0); // this - cfw.add(ByteCode.ALOAD_1); // first arg: ContextFactory instance - cfw.add(ByteCode.PUTFIELD, adapterName, "factory", - "Lorg/mozilla/javascript/ContextFactory;"); - - // Save parameter in instance variable "delegee" - cfw.add(ByteCode.ALOAD_0); // this - cfw.add(ByteCode.ALOAD_2); // second arg: Scriptable delegee - cfw.add(ByteCode.PUTFIELD, adapterName, "delegee", - "Lorg/mozilla/javascript/Scriptable;"); - // save self - cfw.add(ByteCode.ALOAD_0); // this - cfw.add(ByteCode.ALOAD_3); // second arg: Scriptable self - cfw.add(ByteCode.PUTFIELD, adapterName, "self", - "Lorg/mozilla/javascript/Scriptable;"); - - cfw.add(ByteCode.RETURN); - cfw.stopMethod((short)4); // 4: this + factory + delegee + self - } - - private static void generateEmptyCtor(ClassFileWriter cfw, - String adapterName, - String superName, - String scriptClassName) - { - cfw.startMethod("<init>", "()V", ClassFileWriter.ACC_PUBLIC); - - // Invoke base class constructor - cfw.add(ByteCode.ALOAD_0); // this - cfw.addInvoke(ByteCode.INVOKESPECIAL, superName, "<init>", "()V"); - - // Set factory to null to use current global when necessary - cfw.add(ByteCode.ALOAD_0); - cfw.add(ByteCode.ACONST_NULL); - cfw.add(ByteCode.PUTFIELD, adapterName, "factory", - "Lorg/mozilla/javascript/ContextFactory;"); - - // Load script class - cfw.add(ByteCode.NEW, scriptClassName); - cfw.add(ByteCode.DUP); - cfw.addInvoke(ByteCode.INVOKESPECIAL, scriptClassName, "<init>", "()V"); - - // Run script and save resulting scope - cfw.addInvoke(ByteCode.INVOKESTATIC, - "org/mozilla/javascript/JavaAdapter", - "runScript", - "(Lorg/mozilla/javascript/Script;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.add(ByteCode.ASTORE_1); - - // Save the Scriptable in instance variable "delegee" - cfw.add(ByteCode.ALOAD_0); // this - cfw.add(ByteCode.ALOAD_1); // the Scriptable - cfw.add(ByteCode.PUTFIELD, adapterName, "delegee", - "Lorg/mozilla/javascript/Scriptable;"); - - cfw.add(ByteCode.ALOAD_0); // this for the following PUTFIELD for self - // create a wrapper object to be used as "this" in method calls - cfw.add(ByteCode.ALOAD_1); // the Scriptable - cfw.add(ByteCode.ALOAD_0); // this - cfw.addInvoke(ByteCode.INVOKESTATIC, - "org/mozilla/javascript/JavaAdapter", - "createAdapterWrapper", - "(Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/Object;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.add(ByteCode.PUTFIELD, adapterName, "self", - "Lorg/mozilla/javascript/Scriptable;"); - - cfw.add(ByteCode.RETURN); - cfw.stopMethod((short)2); // this + delegee - } - - /** - * Generates code to wrap Java arguments into Object[]. - * Non-primitive Java types are left as-is pending conversion - * in the helper method. Leaves the array object on the top of the stack. - */ - static void generatePushWrappedArgs(ClassFileWriter cfw, - Class[] argTypes, - int arrayLength) - { - // push arguments - cfw.addPush(arrayLength); - cfw.add(ByteCode.ANEWARRAY, "java/lang/Object"); - int paramOffset = 1; - for (int i = 0; i != argTypes.length; ++i) { - cfw.add(ByteCode.DUP); // duplicate array reference - cfw.addPush(i); - paramOffset += generateWrapArg(cfw, paramOffset, argTypes[i]); - cfw.add(ByteCode.AASTORE); - } - } - - /** - * Generates code to wrap Java argument into Object. - * Non-primitive Java types are left unconverted pending conversion - * in the helper method. Leaves the wrapper object on the top of the stack. - */ - private static int generateWrapArg(ClassFileWriter cfw, int paramOffset, - Class argType) - { - int size = 1; - if (!argType.isPrimitive()) { - cfw.add(ByteCode.ALOAD, paramOffset); - - } else if (argType == Boolean.TYPE) { - // wrap boolean values with java.lang.Boolean. - cfw.add(ByteCode.NEW, "java/lang/Boolean"); - cfw.add(ByteCode.DUP); - cfw.add(ByteCode.ILOAD, paramOffset); - cfw.addInvoke(ByteCode.INVOKESPECIAL, "java/lang/Boolean", - "<init>", "(Z)V"); - - } else if (argType == Character.TYPE) { - // 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; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/JavaMembers.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/JavaMembers.java deleted file mode 100644 index 84ef2d4..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/JavaMembers.java +++ /dev/null @@ -1,935 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Cameron McCormack - * Frank Mitchell - * Mike Shaver - * Kurt Westerfeld - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.lang.reflect.*; -import java.util.*; - -/** - * - * @author Mike Shaver - * @author Norris Boyd - * @see NativeJavaObject - * @see NativeJavaClass - */ -class JavaMembers -{ - JavaMembers(Scriptable scope, Class cl) - { - this(scope, cl, false); - } - - JavaMembers(Scriptable scope, Class cl, boolean includeProtected) - { - try { - Context cx = ContextFactory.getGlobal().enterContext(); - ClassShutter shutter = cx.getClassShutter(); - if (shutter != null && !shutter.visibleToScripts(cl.getName())) { - throw Context.reportRuntimeError1("msg.access.prohibited", - cl.getName()); - } - this.includePrivate = cx.hasFeature( - Context.FEATURE_ENHANCED_JAVA_ACCESS); - this.members = new Hashtable(23); - this.staticMembers = new Hashtable(7); - this.cl = cl; - reflect(scope, includeProtected); - } finally { - Context.exit(); - } - } - - boolean has(String name, boolean isStatic) - { - Hashtable ht = isStatic ? staticMembers : members; - Object obj = ht.get(name); - if (obj != null) { - return true; - } - return findExplicitFunction(name, isStatic) != null; - } - - Object get(Scriptable scope, String name, Object javaObject, - boolean isStatic) - { - Hashtable ht = isStatic ? staticMembers : members; - Object member = ht.get(name); - if (!isStatic && member == null) { - // Try to get static member from instance (LC3) - member = staticMembers.get(name); - } - if (member == null) { - member = this.getExplicitFunction(scope, name, - javaObject, isStatic); - if (member == null) - return Scriptable.NOT_FOUND; - } - if (member instanceof Scriptable) { - return member; - } - Context cx = Context.getContext(); - Object rval; - Class type; - try { - if (member instanceof BeanProperty) { - BeanProperty bp = (BeanProperty) member; - if (bp.getter == null) - return Scriptable.NOT_FOUND; - rval = bp.getter.invoke(javaObject, Context.emptyArgs); - type = bp.getter.method().getReturnType(); - } else { - Field field = (Field) member; - rval = field.get(isStatic ? null : javaObject); - type = field.getType(); - } - } catch (Exception ex) { - throw Context.throwAsScriptRuntimeEx(ex); - } - // Need to wrap the object before we return it. - scope = ScriptableObject.getTopLevelScope(scope); - return cx.getWrapFactory().wrap(cx, scope, rval, type); - } - - void put(Scriptable scope, String name, Object javaObject, - Object value, boolean isStatic) - { - Hashtable ht = isStatic ? staticMembers : members; - Object member = ht.get(name); - if (!isStatic && member == null) { - // Try to get static member from instance (LC3) - member = staticMembers.get(name); - } - if (member == null) - throw reportMemberNotFound(name); - if (member instanceof FieldAndMethods) { - FieldAndMethods fam = (FieldAndMethods) ht.get(name); - member = fam.field; - } - - // Is this a bean property "set"? - if (member instanceof BeanProperty) { - BeanProperty bp = (BeanProperty)member; - if (bp.setter == null) { - throw reportMemberNotFound(name); - } - // If there's only one setter or if the value is null, use the - // main setter. Otherwise, let the NativeJavaMethod decide which - // setter to use: - if (bp.setters == null || value == null) { - Class setType = bp.setter.argTypes[0]; - Object[] args = { Context.jsToJava(value, setType) }; - try { - bp.setter.invoke(javaObject, args); - } catch (Exception ex) { - throw Context.throwAsScriptRuntimeEx(ex); - } - } else { - Object[] args = { value }; - bp.setters.call(Context.getContext(), - ScriptableObject.getTopLevelScope(scope), - scope, args); - } - } - else { - if (!(member instanceof Field)) { - String str = (member == null) ? "msg.java.internal.private" - : "msg.java.method.assign"; - throw Context.reportRuntimeError1(str, name); - } - Field field = (Field)member; - Object javaValue = Context.jsToJava(value, field.getType()); - try { - field.set(javaObject, javaValue); - } catch (IllegalAccessException accessEx) { - if ((field.getModifiers() & Modifier.FINAL) != 0) { - // treat Java final the same as JavaScript [[READONLY]] - return; - } - throw Context.throwAsScriptRuntimeEx(accessEx); - } catch (IllegalArgumentException argEx) { - throw Context.reportRuntimeError3( - "msg.java.internal.field.type", - value.getClass().getName(), field, - javaObject.getClass().getName()); - } - } - } - - Object[] getIds(boolean isStatic) - { - Hashtable ht = isStatic ? staticMembers : members; - int len = ht.size(); - Object[] result = new Object[len]; - Enumeration keys = ht.keys(); - for (int i=0; i < len; i++) - result[i] = keys.nextElement(); - return result; - } - - static String javaSignature(Class type) - { - if (!type.isArray()) { - return type.getName(); - } else { - int arrayDimension = 0; - do { - ++arrayDimension; - type = type.getComponentType(); - } while (type.isArray()); - String name = type.getName(); - String suffix = "[]"; - if (arrayDimension == 1) { - return name.concat(suffix); - } else { - int length = name.length() + arrayDimension * suffix.length(); - StringBuffer sb = new StringBuffer(length); - sb.append(name); - while (arrayDimension != 0) { - --arrayDimension; - sb.append(suffix); - } - return sb.toString(); - } - } - } - - static String liveConnectSignature(Class[] argTypes) - { - int N = argTypes.length; - if (N == 0) { return "()"; } - StringBuffer sb = new StringBuffer(); - sb.append('('); - for (int i = 0; i != N; ++i) { - if (i != 0) { - sb.append(','); - } - sb.append(javaSignature(argTypes[i])); - } - sb.append(')'); - return sb.toString(); - } - - private MemberBox findExplicitFunction(String name, boolean isStatic) - { - int sigStart = name.indexOf('('); - if (sigStart < 0) { return null; } - - Hashtable ht = isStatic ? staticMembers : members; - MemberBox[] methodsOrCtors = null; - boolean isCtor = (isStatic && sigStart == 0); - - if (isCtor) { - // Explicit request for an overloaded constructor - methodsOrCtors = ctors; - } else { - // Explicit request for an overloaded method - String trueName = name.substring(0,sigStart); - Object obj = ht.get(trueName); - if (!isStatic && obj == null) { - // Try to get static member from instance (LC3) - obj = staticMembers.get(trueName); - } - if (obj instanceof NativeJavaMethod) { - NativeJavaMethod njm = (NativeJavaMethod)obj; - methodsOrCtors = njm.methods; - } - } - - if (methodsOrCtors != null) { - for (int i = 0; i < methodsOrCtors.length; i++) { - Class[] type = methodsOrCtors[i].argTypes; - String sig = liveConnectSignature(type); - if (sigStart + sig.length() == name.length() - && name.regionMatches(sigStart, sig, 0, sig.length())) - { - return methodsOrCtors[i]; - } - } - } - - return null; - } - - private Object getExplicitFunction(Scriptable scope, String name, - Object javaObject, boolean isStatic) - { - Hashtable ht = isStatic ? staticMembers : members; - Object member = null; - MemberBox methodOrCtor = findExplicitFunction(name, isStatic); - - if (methodOrCtor != null) { - Scriptable prototype = - ScriptableObject.getFunctionPrototype(scope); - - if (methodOrCtor.isCtor()) { - NativeJavaConstructor fun = - new NativeJavaConstructor(methodOrCtor); - fun.setPrototype(prototype); - member = fun; - ht.put(name, fun); - } else { - String trueName = methodOrCtor.getName(); - member = ht.get(trueName); - - if (member instanceof NativeJavaMethod && - ((NativeJavaMethod)member).methods.length > 1 ) { - NativeJavaMethod fun = - new NativeJavaMethod(methodOrCtor, name); - fun.setPrototype(prototype); - ht.put(name, fun); - member = fun; - } - } - } - - return member; - } - - /** - * Retrieves mapping of methods to accessible methods for a class. - * In case the class is not public, retrieves methods with same - * signature as its public methods from public superclasses and - * interfaces (if they exist). Basically upcasts every method to the - * nearest accessible method. - */ - private static Method[] discoverAccessibleMethods(Class clazz, - boolean includeProtected, - boolean includePrivate) - { - Map map = new HashMap(); - discoverAccessibleMethods(clazz, map, includeProtected, includePrivate); - return (Method[])map.values().toArray(new Method[map.size()]); - } - - private static void discoverAccessibleMethods(Class clazz, Map map, - boolean includeProtected, - boolean includePrivate) - { - if (Modifier.isPublic(clazz.getModifiers()) || includePrivate) { - try { - if (includeProtected || includePrivate) { - while (clazz != null) { - try { - Method[] methods = clazz.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - Method method = methods[i]; - int mods = method.getModifiers(); - - if (Modifier.isPublic(mods) || - Modifier.isProtected(mods) || - includePrivate) - { - if (includePrivate) - method.setAccessible(true); - map.put(new MethodSignature(method), method); - } - } - clazz = clazz.getSuperclass(); - } catch (SecurityException e) { - // Some security settings (i.e., applets) disallow - // access to Class.getDeclaredMethods. Fall back to - // Class.getMethods. - Method[] methods = clazz.getMethods(); - for (int i = 0; i < methods.length; i++) { - Method method = methods[i]; - MethodSignature sig - = new MethodSignature(method); - if (map.get(sig) == null) - map.put(sig, method); - } - break; // getMethods gets superclass methods, no - // need to loop any more - } - } - } else { - Method[] methods = clazz.getMethods(); - for (int i = 0; i < methods.length; i++) { - Method method = methods[i]; - MethodSignature sig = new MethodSignature(method); - map.put(sig, method); - } - } - return; - } catch (SecurityException e) { - Context.reportWarning( - "Could not discover accessible methods of class " + - clazz.getName() + " due to lack of privileges, " + - "attemping superclasses/interfaces."); - // Fall through and attempt to discover superclass/interface - // methods - } - } - - Class[] interfaces = clazz.getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - discoverAccessibleMethods(interfaces[i], map, includeProtected, - includePrivate); - } - Class superclass = clazz.getSuperclass(); - if (superclass != null) { - discoverAccessibleMethods(superclass, map, includeProtected, - includePrivate); - } - } - - private static final class MethodSignature - { - private final String name; - private final Class[] args; - - private MethodSignature(String name, Class[] args) - { - this.name = name; - this.args = args; - } - - MethodSignature(Method method) - { - this(method.getName(), method.getParameterTypes()); - } - - public boolean equals(Object o) - { - if(o instanceof MethodSignature) - { - MethodSignature ms = (MethodSignature)o; - return ms.name.equals(name) && Arrays.equals(args, ms.args); - } - return false; - } - - public int hashCode() - { - return name.hashCode() ^ args.length; - } - } - - private void reflect(Scriptable scope, boolean includeProtected) - { - // We reflect methods first, because we want overloaded field/method - // names to be allocated to the NativeJavaMethod before the field - // gets in the way. - - Method[] methods = discoverAccessibleMethods(cl, includeProtected, - includePrivate); - for (int i = 0; i < methods.length; i++) { - Method method = methods[i]; - int mods = method.getModifiers(); - boolean isStatic = Modifier.isStatic(mods); - Hashtable ht = isStatic ? staticMembers : members; - String name = method.getName(); - Object value = ht.get(name); - if (value == null) { - ht.put(name, method); - } else { - ObjArray overloadedMethods; - if (value instanceof ObjArray) { - overloadedMethods = (ObjArray)value; - } else { - if (!(value instanceof Method)) Kit.codeBug(); - // value should be instance of Method as at this stage - // staticMembers and members can only contain methods - overloadedMethods = new ObjArray(); - overloadedMethods.add(value); - ht.put(name, overloadedMethods); - } - overloadedMethods.add(method); - } - } - - // replace Method instances by wrapped NativeJavaMethod objects - // first in staticMembers and then in members - for (int tableCursor = 0; tableCursor != 2; ++tableCursor) { - boolean isStatic = (tableCursor == 0); - Hashtable ht = (isStatic) ? staticMembers : members; - Enumeration e = ht.keys(); - while (e.hasMoreElements()) { - String name = (String)e.nextElement(); - MemberBox[] methodBoxes; - Object value = ht.get(name); - if (value instanceof Method) { - methodBoxes = new MemberBox[1]; - methodBoxes[0] = new MemberBox((Method)value); - } else { - ObjArray overloadedMethods = (ObjArray)value; - int N = overloadedMethods.size(); - if (N < 2) Kit.codeBug(); - methodBoxes = new MemberBox[N]; - for (int i = 0; i != N; ++i) { - Method method = (Method)overloadedMethods.get(i); - methodBoxes[i] = new MemberBox(method); - } - } - NativeJavaMethod fun = new NativeJavaMethod(methodBoxes); - if (scope != null) { - ScriptRuntime.setFunctionProtoAndParent(fun, scope); - } - ht.put(name, fun); - } - } - - // Reflect fields. - Field[] fields = getAccessibleFields(); - for (int i = 0; i < fields.length; i++) { - Field field = fields[i]; - String name = field.getName(); - int mods = field.getModifiers(); - if (!includePrivate && !Modifier.isPublic(mods)) { - continue; - } - try { - boolean isStatic = Modifier.isStatic(mods); - Hashtable ht = isStatic ? staticMembers : members; - Object member = ht.get(name); - if (member == null) { - ht.put(name, field); - } else if (member instanceof NativeJavaMethod) { - NativeJavaMethod method = (NativeJavaMethod) member; - FieldAndMethods fam - = new FieldAndMethods(scope, method.methods, field); - Hashtable fmht = isStatic ? staticFieldAndMethods - : fieldAndMethods; - if (fmht == null) { - fmht = new Hashtable(4); - if (isStatic) { - staticFieldAndMethods = fmht; - } else { - fieldAndMethods = fmht; - } - } - fmht.put(name, fam); - ht.put(name, fam); - } else if (member instanceof Field) { - Field oldField = (Field) member; - // If this newly reflected field shadows an inherited field, - // then replace it. Otherwise, since access to the field - // would be ambiguous from Java, no field should be - // reflected. - // For now, the first field found wins, unless another field - // explicitly shadows it. - if (oldField.getDeclaringClass(). - isAssignableFrom(field.getDeclaringClass())) - { - ht.put(name, field); - } - } else { - // "unknown member type" - Kit.codeBug(); - } - } catch (SecurityException e) { - // skip this field - Context.reportWarning("Could not access field " - + name + " of class " + cl.getName() + - " due to lack of privileges."); - } - } - - // Create bean propeties from corresponding get/set methods first for - // static members and then for instance members - for (int tableCursor = 0; tableCursor != 2; ++tableCursor) { - boolean isStatic = (tableCursor == 0); - Hashtable ht = (isStatic) ? staticMembers : members; - - Hashtable toAdd = new Hashtable(); - - // Now, For each member, make "bean" properties. - for (Enumeration e = ht.keys(); e.hasMoreElements(); ) { - - // Is this a getter? - String name = (String) e.nextElement(); - boolean memberIsGetMethod = name.startsWith("get"); - boolean memberIsSetMethod = name.startsWith("set"); - boolean memberIsIsMethod = name.startsWith("is"); - if (memberIsGetMethod || memberIsIsMethod - || memberIsSetMethod) { - // Double check name component. - String nameComponent - = name.substring(memberIsIsMethod ? 2 : 3); - if (nameComponent.length() == 0) - continue; - - // Make the bean property name. - String beanPropertyName = nameComponent; - char ch0 = nameComponent.charAt(0); - if (Character.isUpperCase(ch0)) { - if (nameComponent.length() == 1) { - beanPropertyName = nameComponent.toLowerCase(); - } else { - char ch1 = nameComponent.charAt(1); - if (!Character.isUpperCase(ch1)) { - beanPropertyName = Character.toLowerCase(ch0) - +nameComponent.substring(1); - } - } - } - - // If we already have a member by this name, don't do this - // property. - if (ht.containsKey(beanPropertyName) - || toAdd.containsKey(beanPropertyName)) { - continue; - } - - // Find the getter method, or if there is none, the is- - // method. - MemberBox getter = null; - getter = findGetter(isStatic, ht, "get", nameComponent); - // If there was no valid getter, check for an is- method. - if (getter == null) { - getter = findGetter(isStatic, ht, "is", nameComponent); - } - - // setter - MemberBox setter = null; - NativeJavaMethod setters = null; - String setterName = "set".concat(nameComponent); - - if (ht.containsKey(setterName)) { - // Is this value a method? - Object member = ht.get(setterName); - if (member instanceof NativeJavaMethod) { - NativeJavaMethod njmSet = (NativeJavaMethod)member; - if (getter != null) { - // We have a getter. Now, do we have a matching - // setter? - Class type = getter.method().getReturnType(); - setter = extractSetMethod(type, njmSet.methods, - isStatic); - } else { - // No getter, find any set method - setter = extractSetMethod(njmSet.methods, - isStatic); - } - if (njmSet.methods.length > 1) { - setters = njmSet; - } - } - } - // Make the property. - BeanProperty bp = new BeanProperty(getter, setter, - setters); - toAdd.put(beanPropertyName, bp); - } - } - - // Add the new bean properties. - for (Enumeration e = toAdd.keys(); e.hasMoreElements();) { - Object key = e.nextElement(); - Object value = toAdd.get(key); - ht.put(key, value); - } - } - - // Reflect constructors - Constructor[] constructors = getAccessibleConstructors(); - ctors = new MemberBox[constructors.length]; - for (int i = 0; i != constructors.length; ++i) { - ctors[i] = new MemberBox(constructors[i]); - } - } - - private Constructor[] getAccessibleConstructors() - { - // The JVM currently doesn't allow changing access on java.lang.Class - // constructors, so don't try - if (includePrivate && cl != ScriptRuntime.ClassClass) { - try { - Constructor[] cons = cl.getDeclaredConstructors(); - Constructor.setAccessible(cons, true); - - return cons; - } catch (SecurityException e) { - // Fall through to !includePrivate case - Context.reportWarning("Could not access constructor " + - " of class " + cl.getName() + - " due to lack of privileges."); - } - } - return cl.getConstructors(); - } - - private Field[] getAccessibleFields() { - if (includePrivate) { - try { - ArrayList fieldsList = new ArrayList(); - Class currentClass = cl; - - while (currentClass != null) { - // get all declared fields in this class, make them - // accessible, and save - Field[] declared = currentClass.getDeclaredFields(); - for (int i = 0; i < declared.length; i++) { - declared[i].setAccessible(true); - fieldsList.add(declared[i]); - } - // walk up superclass chain. no need to deal specially with - // interfaces, since they can't have fields - currentClass = currentClass.getSuperclass(); - } - - return (Field[]) fieldsList.toArray( - new Field[fieldsList.size()]); - } catch (SecurityException e) { - // fall through to !includePrivate case - } - } - return cl.getFields(); - } - - private MemberBox findGetter(boolean isStatic, Hashtable ht, String prefix, - String propertyName) - { - String getterName = prefix.concat(propertyName); - if (ht.containsKey(getterName)) { - // Check that the getter is a method. - Object member = ht.get(getterName); - if (member instanceof NativeJavaMethod) { - NativeJavaMethod njmGet = (NativeJavaMethod) member; - return extractGetMethod(njmGet.methods, isStatic); - } - } - return null; - } - - private static MemberBox extractGetMethod(MemberBox[] methods, - boolean isStatic) - { - // Inspect the list of all MemberBox for the only one having no - // parameters - for (int methodIdx = 0; methodIdx < methods.length; methodIdx++) { - MemberBox method = methods[methodIdx]; - // Does getter method have an empty parameter list with a return - // value (eg. a getSomething() or isSomething())? - if (method.argTypes.length == 0 - && (!isStatic || method.isStatic())) - { - Class type = method.method().getReturnType(); - if (type != Void.TYPE) { - return method; - } - break; - } - } - return null; - } - - private static MemberBox extractSetMethod(Class type, MemberBox[] methods, - boolean isStatic) - { - // - // Note: it may be preferable to allow NativeJavaMethod.findFunction() - // to find the appropriate setter; unfortunately, it requires an - // instance of the target arg to determine that. - // - - // Make two passes: one to find a method with direct type assignment, - // and one to find a widening conversion. - for (int pass = 1; pass <= 2; ++pass) { - for (int i = 0; i < methods.length; ++i) { - MemberBox method = methods[i]; - if (!isStatic || method.isStatic()) { - Class[] params = method.argTypes; - if (params.length == 1) { - if (pass == 1) { - if (params[0] == type) { - return method; - } - } else { - if (pass != 2) Kit.codeBug(); - if (params[0].isAssignableFrom(type)) { - return method; - } - } - } - } - } - } - return null; - } - - private static MemberBox extractSetMethod(MemberBox[] methods, - boolean isStatic) - { - - for (int i = 0; i < methods.length; ++i) { - MemberBox method = methods[i]; - if (!isStatic || method.isStatic()) { - if (method.method().getReturnType() == Void.TYPE) { - if (method.argTypes.length == 1) { - return method; - } - } - } - } - return null; - } - - Hashtable getFieldAndMethodsObjects(Scriptable scope, Object javaObject, - boolean isStatic) - { - Hashtable ht = isStatic ? staticFieldAndMethods : fieldAndMethods; - if (ht == null) - return null; - int len = ht.size(); - Hashtable result = new Hashtable(len); - Enumeration e = ht.elements(); - while (len-- > 0) { - FieldAndMethods fam = (FieldAndMethods) e.nextElement(); - FieldAndMethods famNew = new FieldAndMethods(scope, fam.methods, - fam.field); - famNew.javaObject = javaObject; - result.put(fam.field.getName(), famNew); - } - return result; - } - - static JavaMembers lookupClass(Scriptable scope, Class dynamicType, - Class staticType, boolean includeProtected) - { - JavaMembers members; - scope = ScriptableObject.getTopLevelScope(scope); - ClassCache cache = ClassCache.get(scope); - Map<Class<?>,JavaMembers> ct = cache.getClassCacheMap(); - - Class cl = dynamicType; - for (;;) { - members = ct.get(cl); - if (members != null) { - return members; - } - try { - members = new JavaMembers(scope, cl, includeProtected); - break; - } catch (SecurityException e) { - // Reflection may fail for objects that are in a restricted - // access package (e.g. sun.*). If we get a security - // exception, try again with the static type if it is interface. - // Otherwise, try superclass - if (staticType != null && staticType.isInterface()) { - cl = staticType; - staticType = null; // try staticType only once - } else { - Class parent = cl.getSuperclass(); - if (parent == null) { - if (cl.isInterface()) { - // last resort after failed staticType interface - parent = ScriptRuntime.ObjectClass; - } else { - throw e; - } - } - cl = parent; - } - } - } - - if (cache.isCachingEnabled()) - ct.put(cl, members); - return members; - } - - RuntimeException reportMemberNotFound(String memberName) - { - return Context.reportRuntimeError2( - "msg.java.member.not.found", cl.getName(), memberName); - } - - private Class cl; - private Hashtable members; - private Hashtable fieldAndMethods; - private Hashtable staticMembers; - private Hashtable staticFieldAndMethods; - MemberBox[] ctors; - private boolean includePrivate; -} - -class BeanProperty -{ - BeanProperty(MemberBox getter, MemberBox setter, NativeJavaMethod setters) - { - this.getter = getter; - this.setter = setter; - this.setters = setters; - } - - MemberBox getter; - MemberBox setter; - NativeJavaMethod setters; -} - -class FieldAndMethods extends NativeJavaMethod -{ - static final long serialVersionUID = -9222428244284796755L; - - FieldAndMethods(Scriptable scope, MemberBox[] methods, Field field) - { - super(methods); - this.field = field; - setParentScope(scope); - setPrototype(ScriptableObject.getFunctionPrototype(scope)); - } - - public Object getDefaultValue(Class hint) - { - if (hint == ScriptRuntime.FunctionClass) - return this; - Object rval; - Class type; - try { - rval = field.get(javaObject); - type = field.getType(); - } catch (IllegalAccessException accEx) { - throw Context.reportRuntimeError1( - "msg.java.internal.private", field.getName()); - } - Context cx = Context.getContext(); - rval = cx.getWrapFactory().wrap(cx, this, rval, type); - if (rval instanceof Scriptable) { - rval = ((Scriptable) rval).getDefaultValue(hint); - } - return rval; - } - - Field field; - Object javaObject; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/JavaScriptException.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/JavaScriptException.java deleted file mode 100644 index 11ebedf..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/JavaScriptException.java +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Bojan Cekrlic - * Hannes Wallnoefer - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * Java reflection of JavaScript exceptions. - * Instances of this class are thrown by the JavaScript 'throw' keyword. - * - * @author Mike McCabe - */ -public class JavaScriptException extends RhinoException -{ - static final long serialVersionUID = -7666130513694669293L; - - /** - * @deprecated - * Use {@link WrappedException#WrappedException(Throwable)} to report - * exceptions in Java code. - */ - public JavaScriptException(Object value) - { - this(value, "", 0); - } - - /** - * Create a JavaScript exception wrapping the given JavaScript value - * - * @param value the JavaScript value thrown. - */ - public JavaScriptException(Object value, String sourceName, int lineNumber) - { - recordErrorOrigin(sourceName, lineNumber, null, 0); - this.value = value; - } - - public String details() - { - try { - return ScriptRuntime.toString(value); - } catch (RuntimeException rte) { - // ScriptRuntime.toString may throw a RuntimeException - if (value == null) { - return "null"; - } else if (value instanceof Scriptable) { - return ScriptRuntime.defaultObjectToString((Scriptable)value); - } else { - return value.toString(); - } - } - } - - /** - * @return the value wrapped by this exception - */ - public Object getValue() - { - return value; - } - - /** - * @deprecated Use {@link RhinoException#sourceName()} from the super class. - */ - public String getSourceName() - { - return sourceName(); - } - - /** - * @deprecated Use {@link RhinoException#lineNumber()} from the super class. - */ - public int getLineNumber() - { - return lineNumber(); - } - - private Object value; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Kit.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Kit.java deleted file mode 100644 index f7b4cad..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Kit.java +++ /dev/null @@ -1,486 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov, igor@fastmail.fm - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.lang.reflect.Method; -import java.util.Hashtable; - -/** - * Collection of utilities - */ - -public class Kit -{ - /** - * Reflection of Throwable.initCause(Throwable) from JDK 1.4 - * or nul if it is not available. - */ - private static Method Throwable_initCause = null; - - static { - // Are we running on a JDK 1.4 or later system? - try { - Class ThrowableClass = Kit.classOrNull("java.lang.Throwable"); - Class[] signature = { ThrowableClass }; - Throwable_initCause - = ThrowableClass.getMethod("initCause", signature); - } catch (Exception ex) { - // Assume any exceptions means the method does not exist. - } - } - - public static Class classOrNull(String className) - { - try { - return Class.forName(className); - } catch (ClassNotFoundException ex) { - } catch (SecurityException ex) { - } catch (LinkageError ex) { - } catch (IllegalArgumentException e) { - // Can be thrown if name has characters that a class name - // can not contain - } - return null; - } - - public static Class classOrNull(ClassLoader loader, String className) - { - try { - return loader.loadClass(className); - } catch (ClassNotFoundException ex) { - } catch (SecurityException ex) { - } catch (LinkageError ex) { - } catch (IllegalArgumentException e) { - // Can be thrown if name has characters that a class name - // can not contain - } - return null; - } - - static Object newInstanceOrNull(Class cl) - { - try { - return cl.newInstance(); - } catch (SecurityException x) { - } catch (LinkageError ex) { - } catch (InstantiationException x) { - } catch (IllegalAccessException x) { - } - return null; - } - - /** - * Check that testClass is accesible from the given loader. - */ - static boolean testIfCanLoadRhinoClasses(ClassLoader loader) - { - Class testClass = ScriptRuntime.ContextFactoryClass; - Class x = Kit.classOrNull(loader, testClass.getName()); - if (x != testClass) { - // The check covers the case when x == null => - // loader does not know about testClass or the case - // when x != null && x != testClass => - // loader loads a class unrelated to testClass - return false; - } - return true; - } - - /** - * If initCause methods exists in Throwable, call - * <tt>ex.initCause(cause)</tt> or otherwise do nothing. - * @return The <tt>ex</tt> argument. - */ - public static RuntimeException initCause(RuntimeException ex, - Throwable cause) - { - if (Throwable_initCause != null) { - Object[] args = { cause }; - try { - Throwable_initCause.invoke(ex, args); - } catch (Exception e) { - // Ignore any exceptions - } - } - return ex; - } - - /** - * Split string into array of strings using semicolon as string terminator - * (; after the last string is required). - */ - public static String[] semicolonSplit(String s) - { - String[] array = null; - for (;;) { - // loop 2 times: first to count semicolons and then to fill array - int count = 0; - int cursor = 0; - for (;;) { - int next = s.indexOf(';', cursor); - if (next < 0) { - break; - } - if (array != null) { - array[count] = s.substring(cursor, next); - } - ++count; - cursor = next + 1; - } - // after the last semicolon - if (array == null) { - // array size counting state: - // check for required terminating ';' - if (cursor != s.length()) - throw new IllegalArgumentException(); - array = new String[count]; - } else { - // array filling state: stop the loop - break; - } - } - return array; - } - - /** - * If character <tt>c</tt> is a hexadecimal digit, return - * <tt>accumulator</tt> * 16 plus corresponding - * number. Otherise return -1. - */ - public static int xDigitToInt(int c, int accumulator) - { - check: { - // Use 0..9 < A..Z < a..z - if (c <= '9') { - c -= '0'; - if (0 <= c) { break check; } - } else if (c <= 'F') { - if ('A' <= c) { - c -= ('A' - 10); - break check; - } - } else if (c <= 'f') { - if ('a' <= c) { - c -= ('a' - 10); - break check; - } - } - return -1; - } - return (accumulator << 4) | c; - } - - /** - * Add <i>listener</i> to <i>bag</i> of listeners. - * The function does not modify <i>bag</i> and return a new collection - * containing <i>listener</i> and all listeners from <i>bag</i>. - * Bag without listeners always represented as the null value. - * <p> - * Usage example: - * <pre> - * private volatile Object changeListeners; - * - * public void addMyListener(PropertyChangeListener l) - * { - * synchronized (this) { - * changeListeners = Kit.addListener(changeListeners, l); - * } - * } - * - * public void removeTextListener(PropertyChangeListener l) - * { - * synchronized (this) { - * changeListeners = Kit.removeListener(changeListeners, l); - * } - * } - * - * public void fireChangeEvent(Object oldValue, Object newValue) - * { - * // Get immune local copy - * Object listeners = changeListeners; - * if (listeners != null) { - * PropertyChangeEvent e = new PropertyChangeEvent( - * this, "someProperty" oldValue, newValue); - * for (int i = 0; ; ++i) { - * Object l = Kit.getListener(listeners, i); - * if (l == null) - * break; - * ((PropertyChangeListener)l).propertyChange(e); - * } - * } - * } - * </pre> - * - * @param listener Listener to add to <i>bag</i> - * @param bag Current collection of listeners. - * @return A new bag containing all listeners from <i>bag</i> and - * <i>listener</i>. - * @see #removeListener(Object bag, Object listener) - * @see #getListener(Object bag, int index) - */ - public static Object addListener(Object bag, Object listener) - { - if (listener == null) throw new IllegalArgumentException(); - if (listener instanceof Object[]) throw new IllegalArgumentException(); - - if (bag == null) { - bag = listener; - } else if (!(bag instanceof Object[])) { - bag = new Object[] { bag, listener }; - } else { - Object[] array = (Object[])bag; - int L = array.length; - // bag has at least 2 elements if it is array - if (L < 2) throw new IllegalArgumentException(); - Object[] tmp = new Object[L + 1]; - System.arraycopy(array, 0, tmp, 0, L); - tmp[L] = listener; - bag = tmp; - } - - return bag; - } - - /** - * Remove <i>listener</i> from <i>bag</i> of listeners. - * The function does not modify <i>bag</i> and return a new collection - * containing all listeners from <i>bag</i> except <i>listener</i>. - * If <i>bag</i> does not contain <i>listener</i>, the function returns - * <i>bag</i>. - * <p> - * For usage example, see {@link #addListener(Object bag, Object listener)}. - * - * @param listener Listener to remove from <i>bag</i> - * @param bag Current collection of listeners. - * @return A new bag containing all listeners from <i>bag</i> except - * <i>listener</i>. - * @see #addListener(Object bag, Object listener) - * @see #getListener(Object bag, int index) - */ - public static Object removeListener(Object bag, Object listener) - { - if (listener == null) throw new IllegalArgumentException(); - if (listener instanceof Object[]) throw new IllegalArgumentException(); - - if (bag == listener) { - bag = null; - } else if (bag instanceof Object[]) { - Object[] array = (Object[])bag; - int L = array.length; - // bag has at least 2 elements if it is array - if (L < 2) throw new IllegalArgumentException(); - if (L == 2) { - if (array[1] == listener) { - bag = array[0]; - } else if (array[0] == listener) { - bag = array[1]; - } - } else { - int i = L; - do { - --i; - if (array[i] == listener) { - Object[] tmp = new Object[L - 1]; - System.arraycopy(array, 0, tmp, 0, i); - System.arraycopy(array, i + 1, tmp, i, L - (i + 1)); - bag = tmp; - break; - } - } while (i != 0); - } - } - - return bag; - } - - /** - * Get listener at <i>index</i> position in <i>bag</i> or null if - * <i>index</i> equals to number of listeners in <i>bag</i>. - * <p> - * For usage example, see {@link #addListener(Object bag, Object listener)}. - * - * @param bag Current collection of listeners. - * @param index Index of the listener to access. - * @return Listener at the given index or null. - * @see #addListener(Object bag, Object listener) - * @see #removeListener(Object bag, Object listener) - */ - public static Object getListener(Object bag, int index) - { - if (index == 0) { - if (bag == null) - return null; - if (!(bag instanceof Object[])) - return bag; - Object[] array = (Object[])bag; - // bag has at least 2 elements if it is array - if (array.length < 2) throw new IllegalArgumentException(); - return array[0]; - } else if (index == 1) { - if (!(bag instanceof Object[])) { - if (bag == null) throw new IllegalArgumentException(); - return null; - } - Object[] array = (Object[])bag; - // the array access will check for index on its own - return array[1]; - } else { - // bag has to array - Object[] array = (Object[])bag; - int L = array.length; - if (L < 2) throw new IllegalArgumentException(); - if (index == L) - return null; - return array[index]; - } - } - - static Object initHash(Hashtable h, Object key, Object initialValue) - { - synchronized (h) { - Object current = h.get(key); - if (current == null) { - h.put(key, initialValue); - } else { - initialValue = current; - } - } - return initialValue; - } - - private final static class ComplexKey - { - private Object key1; - private Object key2; - private int hash; - - ComplexKey(Object key1, Object key2) - { - this.key1 = key1; - this.key2 = key2; - } - - public boolean equals(Object anotherObj) - { - if (!(anotherObj instanceof ComplexKey)) - return false; - ComplexKey another = (ComplexKey)anotherObj; - return key1.equals(another.key1) && key2.equals(another.key2); - } - - public int hashCode() - { - if (hash == 0) { - hash = key1.hashCode() ^ key2.hashCode(); - } - return hash; - } - } - - public static Object makeHashKeyFromPair(Object key1, Object key2) - { - if (key1 == null) throw new IllegalArgumentException(); - if (key2 == null) throw new IllegalArgumentException(); - return new ComplexKey(key1, key2); - } - - public static String readReader(Reader r) - throws IOException - { - char[] buffer = new char[512]; - int cursor = 0; - for (;;) { - int n = r.read(buffer, cursor, buffer.length - cursor); - if (n < 0) { break; } - cursor += n; - if (cursor == buffer.length) { - char[] tmp = new char[buffer.length * 2]; - System.arraycopy(buffer, 0, tmp, 0, cursor); - buffer = tmp; - } - } - return new String(buffer, 0, cursor); - } - - public static byte[] readStream(InputStream is, int initialBufferCapacity) - throws IOException - { - if (initialBufferCapacity <= 0) { - throw new IllegalArgumentException( - "Bad initialBufferCapacity: "+initialBufferCapacity); - } - byte[] buffer = new byte[initialBufferCapacity]; - int cursor = 0; - for (;;) { - int n = is.read(buffer, cursor, buffer.length - cursor); - if (n < 0) { break; } - cursor += n; - if (cursor == buffer.length) { - byte[] tmp = new byte[buffer.length * 2]; - System.arraycopy(buffer, 0, tmp, 0, cursor); - buffer = tmp; - } - } - if (cursor != buffer.length) { - byte[] tmp = new byte[cursor]; - System.arraycopy(buffer, 0, tmp, 0, cursor); - buffer = tmp; - } - return buffer; - } - - /** - * Throws RuntimeException to indicate failed assertion. - * The function never returns and its return type is RuntimeException - * only to be able to write <tt>throw Kit.codeBug()</tt> if plain - * <tt>Kit.codeBug()</tt> triggers unreachable code error. - */ - public static RuntimeException codeBug() - throws RuntimeException - { - RuntimeException ex = new IllegalStateException("FAILED ASSERTION"); - // Print stack trace ASAP - ex.printStackTrace(System.err); - throw ex; - } -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/LazilyLoadedCtor.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/LazilyLoadedCtor.java deleted file mode 100644 index 4153372..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/LazilyLoadedCtor.java +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.lang.reflect.*; - -/** - * Avoid loading classes unless they are used. - * - * <p> This improves startup time and average memory usage. - */ -public final class LazilyLoadedCtor implements java.io.Serializable { - private static final long serialVersionUID = 1L; - - private static final int STATE_BEFORE_INIT = 0; - private static final int STATE_INITIALIZING = 1; - private static final int STATE_WITH_VALUE = 2; - - private final ScriptableObject scope; - private final String propertyName; - private final String className; - private final boolean sealed; - private Object initializedValue; - private int state; - - public LazilyLoadedCtor(ScriptableObject scope, String propertyName, - String className, boolean sealed) - { - - this.scope = scope; - this.propertyName = propertyName; - this.className = className; - this.sealed = sealed; - this.state = STATE_BEFORE_INIT; - - scope.addLazilyInitializedValue(propertyName, 0, this, - ScriptableObject.DONTENUM); - } - - void init() - { - synchronized (this) { - if (state == STATE_INITIALIZING) - throw new IllegalStateException( - "Recursive initialization for "+propertyName); - if (state == STATE_BEFORE_INIT) { - state = STATE_INITIALIZING; - // Set value now to have something to set in finally block if - // buildValue throws. - Object value = Scriptable.NOT_FOUND; - try { - value = buildValue(); - } finally { - initializedValue = value; - state = STATE_WITH_VALUE; - } - } - } - } - - Object getValue() - { - if (state != STATE_WITH_VALUE) - throw new IllegalStateException(propertyName); - return initializedValue; - } - - private Object buildValue() - { - Class cl = Kit.classOrNull(className); - if (cl != null) { - try { - Object value = ScriptableObject.buildClassCtor(scope, cl, - sealed, false); - if (value != null) { - return value; - } - else { - // cl has own static initializer which is expected - // to set the property on its own. - value = scope.get(propertyName, scope); - if (value != Scriptable.NOT_FOUND) - return value; - } - } catch (InvocationTargetException ex) { - Throwable target = ex.getTargetException(); - if (target instanceof RuntimeException) { - throw (RuntimeException)target; - } - } catch (RhinoException ex) { - } catch (InstantiationException ex) { - } catch (IllegalAccessException ex) { - } catch (SecurityException ex) { - } - } - return Scriptable.NOT_FOUND; - } - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/MemberBox.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/MemberBox.java deleted file mode 100644 index 2d3553f..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/MemberBox.java +++ /dev/null @@ -1,362 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * Felix Meschberger - * Norris Boyd - * Ulrike Mueller <umueller@demandware.com> - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.lang.reflect.*; -import java.io.*; - -/** - * Wrappper class for Method and Constructor instances to cache - * getParameterTypes() results, recover from IllegalAccessException - * in some cases and provide serialization support. - * - * @author Igor Bukanov - */ - -final class MemberBox implements Serializable -{ - static final long serialVersionUID = 6358550398665688245L; - - private transient Member memberObject; - transient Class[] argTypes; - transient Object delegateTo; - transient boolean vararg; - - - MemberBox(Method method) - { - init(method); - } - - MemberBox(Constructor constructor) - { - init(constructor); - } - - private void init(Method method) - { - this.memberObject = method; - this.argTypes = method.getParameterTypes(); - this.vararg = VMBridge.instance.isVarArgs(method); - } - - private void init(Constructor constructor) - { - this.memberObject = constructor; - this.argTypes = constructor.getParameterTypes(); - this.vararg = VMBridge.instance.isVarArgs(constructor); - } - - Method method() - { - return (Method)memberObject; - } - - Constructor ctor() - { - return (Constructor)memberObject; - } - - Member member() - { - return memberObject; - } - - boolean isMethod() - { - return memberObject instanceof Method; - } - - boolean isCtor() - { - return memberObject instanceof Constructor; - } - - boolean isStatic() - { - return Modifier.isStatic(memberObject.getModifiers()); - } - - String getName() - { - return memberObject.getName(); - } - - Class getDeclaringClass() - { - return memberObject.getDeclaringClass(); - } - - String toJavaDeclaration() - { - StringBuffer sb = new StringBuffer(); - if (isMethod()) { - Method method = method(); - sb.append(method.getReturnType()); - sb.append(' '); - sb.append(method.getName()); - } else { - Constructor ctor = ctor(); - String name = ctor.getDeclaringClass().getName(); - int lastDot = name.lastIndexOf('.'); - if (lastDot >= 0) { - name = name.substring(lastDot + 1); - } - sb.append(name); - } - sb.append(JavaMembers.liveConnectSignature(argTypes)); - return sb.toString(); - } - - public String toString() - { - return memberObject.toString(); - } - - Object invoke(Object target, Object[] args) - { - Method method = method(); - try { - try { - return method.invoke(target, args); - } catch (IllegalAccessException ex) { - Method accessible = searchAccessibleMethod(method, argTypes); - if (accessible != null) { - memberObject = accessible; - method = accessible; - } else { - if (!VMBridge.instance.tryToMakeAccessible(method)) { - throw Context.throwAsScriptRuntimeEx(ex); - } - } - // Retry after recovery - return method.invoke(target, args); - } - } catch (Exception ex) { - throw Context.throwAsScriptRuntimeEx(ex); - } - } - - Object newInstance(Object[] args) - { - Constructor ctor = ctor(); - try { - try { - return ctor.newInstance(args); - } catch (IllegalAccessException ex) { - if (!VMBridge.instance.tryToMakeAccessible(ctor)) { - throw Context.throwAsScriptRuntimeEx(ex); - } - } - return ctor.newInstance(args); - } catch (Exception ex) { - throw Context.throwAsScriptRuntimeEx(ex); - } - } - - private static Method searchAccessibleMethod(Method method, Class[] params) - { - int modifiers = method.getModifiers(); - if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) { - Class c = method.getDeclaringClass(); - if (!Modifier.isPublic(c.getModifiers())) { - String name = method.getName(); - Class[] intfs = c.getInterfaces(); - for (int i = 0, N = intfs.length; i != N; ++i) { - Class intf = intfs[i]; - if (Modifier.isPublic(intf.getModifiers())) { - try { - return intf.getMethod(name, params); - } catch (NoSuchMethodException ex) { - } catch (SecurityException ex) { } - } - } - for (;;) { - c = c.getSuperclass(); - if (c == null) { break; } - if (Modifier.isPublic(c.getModifiers())) { - try { - Method m = c.getMethod(name, params); - int mModifiers = m.getModifiers(); - if (Modifier.isPublic(mModifiers) - && !Modifier.isStatic(mModifiers)) - { - return m; - } - } catch (NoSuchMethodException ex) { - } catch (SecurityException ex) { } - } - } - } - } - return null; - } - - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - Member member = readMember(in); - if (member instanceof Method) { - init((Method)member); - } else { - init((Constructor)member); - } - } - - private void writeObject(ObjectOutputStream out) - throws IOException - { - out.defaultWriteObject(); - writeMember(out, memberObject); - } - - /** - * Writes a Constructor or Method object. - * - * Methods and Constructors are not serializable, so we must serialize - * information about the class, the name, and the parameters and - * recreate upon deserialization. - */ - private static void writeMember(ObjectOutputStream out, Member member) - throws IOException - { - if (member == null) { - out.writeBoolean(false); - return; - } - out.writeBoolean(true); - if (!(member instanceof Method || member instanceof Constructor)) - throw new IllegalArgumentException("not Method or Constructor"); - out.writeBoolean(member instanceof Method); - out.writeObject(member.getName()); - out.writeObject(member.getDeclaringClass()); - if (member instanceof Method) { - writeParameters(out, ((Method) member).getParameterTypes()); - } else { - writeParameters(out, ((Constructor) member).getParameterTypes()); - } - } - - /** - * Reads a Method or a Constructor from the stream. - */ - private static Member readMember(ObjectInputStream in) - throws IOException, ClassNotFoundException - { - if (!in.readBoolean()) - return null; - boolean isMethod = in.readBoolean(); - String name = (String) in.readObject(); - Class declaring = (Class) in.readObject(); - Class[] parms = readParameters(in); - try { - if (isMethod) { - return declaring.getMethod(name, parms); - } else { - return declaring.getConstructor(parms); - } - } catch (NoSuchMethodException e) { - throw new IOException("Cannot find member: " + e); - } - } - - private static final Class[] primitives = { - Boolean.TYPE, - Byte.TYPE, - Character.TYPE, - Double.TYPE, - Float.TYPE, - Integer.TYPE, - Long.TYPE, - Short.TYPE, - Void.TYPE - }; - - /** - * Writes an array of parameter types to the stream. - * - * Requires special handling because primitive types cannot be - * found upon deserialization by the default Java implementation. - */ - private static void writeParameters(ObjectOutputStream out, Class[] parms) - throws IOException - { - out.writeShort(parms.length); - outer: - for (int i=0; i < parms.length; i++) { - Class parm = parms[i]; - boolean primitive = parm.isPrimitive(); - out.writeBoolean(primitive); - if (!primitive) { - out.writeObject(parm); - continue; - } - for (int j=0; j < primitives.length; j++) { - if (parm.equals(primitives[j])) { - out.writeByte(j); - continue outer; - } - } - throw new IllegalArgumentException("Primitive " + parm + - " not found"); - } - } - - /** - * Reads an array of parameter types from the stream. - */ - private static Class[] readParameters(ObjectInputStream in) - throws IOException, ClassNotFoundException - { - Class[] result = new Class[in.readShort()]; - for (int i=0; i < result.length; i++) { - if (!in.readBoolean()) { - result[i] = (Class) in.readObject(); - continue; - } - result[i] = primitives[in.readByte()]; - } - return result; - } -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeArray.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeArray.java deleted file mode 100644 index b170ff4..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeArray.java +++ /dev/null @@ -1,1727 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Mike McCabe - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.util.Arrays; - -/** - * This class implements the Array native object. - * @author Norris Boyd - * @author Mike McCabe - */ -public class NativeArray extends IdScriptableObject -{ - static final long serialVersionUID = 7331366857676127338L; - - /* - * Optimization possibilities and open issues: - * - Long vs. double schizophrenia. I suspect it might be better - * to use double throughout. - * - * - Functions that need a new Array call "new Array" in the - * current scope rather than using a hardwired constructor; - * "Array" could be redefined. It turns out that js calls the - * equivalent of "new Array" in the current scope, except that it - * always gets at least an object back, even when Array == null. - */ - - private static final Object ARRAY_TAG = new Object(); - private static final Integer NEGATIVE_ONE = new Integer(-1); - - static void init(Scriptable scope, boolean sealed) - { - NativeArray obj = new NativeArray(0); - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - static int getMaximumInitialCapacity() { - return maximumInitialCapacity; - } - - static void setMaximumInitialCapacity(int maximumInitialCapacity) { - NativeArray.maximumInitialCapacity = maximumInitialCapacity; - } - - public NativeArray(long lengthArg) - { - denseOnly = lengthArg <= maximumInitialCapacity; - if (denseOnly) { - int intLength = (int) lengthArg; - if (intLength < DEFAULT_INITIAL_CAPACITY) - intLength = DEFAULT_INITIAL_CAPACITY; - dense = new Object[intLength]; - Arrays.fill(dense, Scriptable.NOT_FOUND); - } - length = lengthArg; - } - - public NativeArray(Object[] array) - { - denseOnly = true; - dense = array; - length = array.length; - } - - public String getClassName() - { - return "Array"; - } - - private static final int - Id_length = 1, - MAX_INSTANCE_ID = 1; - - protected int getMaxInstanceId() - { - return MAX_INSTANCE_ID; - } - - protected int findInstanceIdInfo(String s) - { - if (s.equals("length")) { - return instanceIdInfo(DONTENUM | PERMANENT, Id_length); - } - return super.findInstanceIdInfo(s); - } - - protected String getInstanceIdName(int id) - { - if (id == Id_length) { return "length"; } - return super.getInstanceIdName(id); - } - - protected Object getInstanceIdValue(int id) - { - if (id == Id_length) { - return ScriptRuntime.wrapNumber(length); - } - return super.getInstanceIdValue(id); - } - - protected void setInstanceIdValue(int id, Object value) - { - if (id == Id_length) { - setLength(value); return; - } - super.setInstanceIdValue(id, value); - } - - protected void fillConstructorProperties(IdFunctionObject ctor) - { - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_join, - "join", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_reverse, - "reverse", 1); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_sort, - "sort", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_push, - "push", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_pop, - "pop", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_shift, - "shift", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_unshift, - "unshift", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_splice, - "splice", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_concat, - "concat", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_slice, - "slice", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_indexOf, - "indexOf", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_lastIndexOf, - "lastIndexOf", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_every, - "every", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_filter, - "filter", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_forEach, - "forEach", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_map, - "map", 2); - addIdFunctionProperty(ctor, ARRAY_TAG, ConstructorId_some, - "some", 2); - super.fillConstructorProperties(ctor); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=1; s="constructor"; break; - case Id_toString: arity=0; s="toString"; break; - case Id_toLocaleString: arity=1; s="toLocaleString"; break; - case Id_toSource: arity=0; s="toSource"; break; - case Id_join: arity=1; s="join"; break; - case Id_reverse: arity=0; s="reverse"; break; - case Id_sort: arity=1; s="sort"; break; - case Id_push: arity=1; s="push"; break; - case Id_pop: arity=1; s="pop"; break; - case Id_shift: arity=1; s="shift"; break; - case Id_unshift: arity=1; s="unshift"; break; - case Id_splice: arity=1; s="splice"; break; - case Id_concat: arity=1; s="concat"; break; - case Id_slice: arity=1; s="slice"; break; - case Id_indexOf: arity=1; s="indexOf"; break; - case Id_lastIndexOf: arity=1; s="lastIndexOf"; break; - case Id_every: arity=1; s="every"; break; - case Id_filter: arity=1; s="filter"; break; - case Id_forEach: arity=1; s="forEach"; break; - case Id_map: arity=1; s="map"; break; - case Id_some: arity=1; s="some"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(ARRAY_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(ARRAY_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - again: - for (;;) { - switch (id) { - case ConstructorId_join: - case ConstructorId_reverse: - case ConstructorId_sort: - case ConstructorId_push: - case ConstructorId_pop: - case ConstructorId_shift: - case ConstructorId_unshift: - case ConstructorId_splice: - case ConstructorId_concat: - case ConstructorId_slice: - case ConstructorId_indexOf: - case ConstructorId_lastIndexOf: - case ConstructorId_every: - case ConstructorId_filter: - case ConstructorId_forEach: - case ConstructorId_map: - case ConstructorId_some: { - thisObj = ScriptRuntime.toObject(scope, args[0]); - Object[] newArgs = new Object[args.length-1]; - for (int i=0; i < newArgs.length; i++) - newArgs[i] = args[i+1]; - args = newArgs; - id = -id; - continue again; - } - - case Id_constructor: { - boolean inNewExpr = (thisObj == null); - if (!inNewExpr) { - // IdFunctionObject.construct will set up parent, proto - return f.construct(cx, scope, args); - } - return jsConstructor(cx, scope, args); - } - - case Id_toString: - return toStringHelper(cx, scope, thisObj, - cx.hasFeature(Context.FEATURE_TO_STRING_AS_SOURCE), false); - - case Id_toLocaleString: - return toStringHelper(cx, scope, thisObj, false, true); - - case Id_toSource: - return toStringHelper(cx, scope, thisObj, true, false); - - case Id_join: - return js_join(cx, thisObj, args); - - case Id_reverse: - return js_reverse(cx, thisObj, args); - - case Id_sort: - return js_sort(cx, scope, thisObj, args); - - case Id_push: - return js_push(cx, thisObj, args); - - case Id_pop: - return js_pop(cx, thisObj, args); - - case Id_shift: - return js_shift(cx, thisObj, args); - - case Id_unshift: - return js_unshift(cx, thisObj, args); - - case Id_splice: - return js_splice(cx, scope, thisObj, args); - - case Id_concat: - return js_concat(cx, scope, thisObj, args); - - case Id_slice: - return js_slice(cx, thisObj, args); - - case Id_indexOf: - return indexOfHelper(cx, thisObj, args, false); - - case Id_lastIndexOf: - return indexOfHelper(cx, thisObj, args, true); - - case Id_every: - case Id_filter: - case Id_forEach: - case Id_map: - case Id_some: - return iterativeMethod(cx, id, scope, thisObj, args); - } - throw new IllegalArgumentException(String.valueOf(id)); - } - } - - public Object get(int index, Scriptable start) - { - if (!denseOnly && isGetterOrSetter(null, index, false)) - return super.get(index, start); - if (dense != null && 0 <= index && index < dense.length) - return dense[index]; - return super.get(index, start); - } - - public boolean has(int index, Scriptable start) - { - if (!denseOnly && isGetterOrSetter(null, index, false)) - return super.has(index, start); - if (dense != null && 0 <= index && index < dense.length) - return dense[index] != NOT_FOUND; - return super.has(index, start); - } - - // if id is an array index (ECMA 15.4.0), return the number, - // otherwise return -1L - private static long toArrayIndex(String id) - { - double d = ScriptRuntime.toNumber(id); - if (d == d) { - long index = ScriptRuntime.toUint32(d); - if (index == d && index != 4294967295L) { - // Assume that ScriptRuntime.toString(index) is the same - // as java.lang.Long.toString(index) for long - if (Long.toString(index).equals(id)) { - return index; - } - } - } - return -1; - } - - public void put(String id, Scriptable start, Object value) - { - super.put(id, start, value); - if (start == this) { - // If the object is sealed, super will throw exception - long index = toArrayIndex(id); - if (index >= length) { - length = index + 1; - denseOnly = false; - } - } - } - - private boolean ensureCapacity(int capacity) - { - if (capacity > dense.length) { - if (capacity > MAX_PRE_GROW_SIZE) { - denseOnly = false; - return false; - } - capacity = Math.max(capacity, (int)(dense.length * GROW_FACTOR)); - Object[] newDense = new Object[capacity]; - System.arraycopy(dense, 0, newDense, 0, dense.length); - Arrays.fill(newDense, dense.length, newDense.length, - Scriptable.NOT_FOUND); - dense = newDense; - } - return true; - } - - public void put(int index, Scriptable start, Object value) - { - if (start == this && !isSealed() && dense != null && 0 <= index && - (denseOnly || !isGetterOrSetter(null, index, true))) - { - if (index < dense.length) { - dense[index] = value; - if (this.length <= index) - this.length = (long)index + 1; - return; - } else if (denseOnly && index < dense.length * GROW_FACTOR && - ensureCapacity(index+1)) - { - dense[index] = value; - this.length = (long)index + 1; - return; - } else { - denseOnly = false; - } - } - super.put(index, start, value); - if (start == this) { - // only set the array length if given an array index (ECMA 15.4.0) - if (this.length <= index) { - // avoid overflowing index! - this.length = (long)index + 1; - } - } - } - - public void delete(int index) - { - if (dense != null && 0 <= index && index < dense.length && - !isSealed() && (denseOnly || !isGetterOrSetter(null, index, true))) - { - dense[index] = NOT_FOUND; - } else { - super.delete(index); - } - } - - public Object[] getIds() - { - Object[] superIds = super.getIds(); - if (dense == null) { return superIds; } - int N = dense.length; - long currentLength = length; - if (N > currentLength) { - N = (int)currentLength; - } - if (N == 0) { return superIds; } - int superLength = superIds.length; - Object[] ids = new Object[N + superLength]; - - int presentCount = 0; - for (int i = 0; i != N; ++i) { - // Replace existing elements by their indexes - if (dense[i] != NOT_FOUND) { - ids[presentCount] = new Integer(i); - ++presentCount; - } - } - if (presentCount != N) { - // dense contains deleted elems, need to shrink the result - Object[] tmp = new Object[presentCount + superLength]; - System.arraycopy(ids, 0, tmp, 0, presentCount); - ids = tmp; - } - System.arraycopy(superIds, 0, ids, presentCount, superLength); - return ids; - } - - public Object getDefaultValue(Class hint) - { - if (hint == ScriptRuntime.NumberClass) { - Context cx = Context.getContext(); - if (cx.getLanguageVersion() == Context.VERSION_1_2) - return new Long(length); - } - return super.getDefaultValue(hint); - } - - /** - * See ECMA 15.4.1,2 - */ - private static Object jsConstructor(Context cx, Scriptable scope, - Object[] args) - { - if (args.length == 0) - return new NativeArray(0); - - // Only use 1 arg as first element for version 1.2; for - // any other version (including 1.3) follow ECMA and use it as - // a length. - if (cx.getLanguageVersion() == Context.VERSION_1_2) { - return new NativeArray(args); - } else { - Object arg0 = args[0]; - if (args.length > 1 || !(arg0 instanceof Number)) { - return new NativeArray(args); - } else { - long len = ScriptRuntime.toUint32(arg0); - if (len != ((Number)arg0).doubleValue()) - throw Context.reportRuntimeError0("msg.arraylength.bad"); - return new NativeArray(len); - } - } - } - - public long getLength() { - return length; - } - - /** @deprecated Use {@link #getLength()} instead. */ - public long jsGet_length() { - return getLength(); - } - - /** - * Change the value of the internal flag that determines whether all - * storage is handed by a dense backing array rather than an associative - * store. - * @param denseOnly new value for denseOnly flag - * @throws IllegalArgumentException if an attempt is made to enable - * denseOnly after it was disabled; NativeArray code is not written - * to handle switching back to a dense representation - */ - void setDenseOnly(boolean denseOnly) { - if (denseOnly && !this.denseOnly) - throw new IllegalArgumentException(); - this.denseOnly = denseOnly; - } - - private void setLength(Object val) { - /* XXX do we satisfy this? - * 15.4.5.1 [[Put]](P, V): - * 1. Call the [[CanPut]] method of A with name P. - * 2. If Result(1) is false, return. - * ? - */ - - double d = ScriptRuntime.toNumber(val); - long longVal = ScriptRuntime.toUint32(d); - if (longVal != d) - throw Context.reportRuntimeError0("msg.arraylength.bad"); - - if (denseOnly) { - if (longVal < length) { - // downcast okay because denseOnly - Arrays.fill(dense, (int) longVal, dense.length, NOT_FOUND); - length = longVal; - return; - } else if (longVal < MAX_PRE_GROW_SIZE && - longVal < (length * GROW_FACTOR) && - ensureCapacity((int)longVal)) - { - length = longVal; - return; - } else { - denseOnly = false; - } - } - if (longVal < length) { - // remove all properties between longVal and length - if (length - longVal > 0x1000) { - // assume that the representation is sparse - Object[] e = getIds(); // will only find in object itself - for (int i=0; i < e.length; i++) { - Object id = e[i]; - if (id instanceof String) { - // > MAXINT will appear as string - String strId = (String)id; - long index = toArrayIndex(strId); - if (index >= longVal) - delete(strId); - } else { - int index = ((Integer)id).intValue(); - if (index >= longVal) - delete(index); - } - } - } else { - // assume a dense representation - for (long i = longVal; i < length; i++) { - deleteElem(this, i); - } - } - } - length = longVal; - } - - /* Support for generic Array-ish objects. Most of the Array - * functions try to be generic; anything that has a length - * property is assumed to be an array. - * getLengthProperty returns 0 if obj does not have the length property - * or its value is not convertible to a number. - */ - static long getLengthProperty(Context cx, Scriptable obj) { - // These will both give numeric lengths within Uint32 range. - if (obj instanceof NativeString) { - return ((NativeString)obj).getLength(); - } else if (obj instanceof NativeArray) { - return ((NativeArray)obj).getLength(); - } - return ScriptRuntime.toUint32( - ScriptRuntime.getObjectProp(obj, "length", cx)); - } - - private static Object setLengthProperty(Context cx, Scriptable target, - long length) - { - return ScriptRuntime.setObjectProp( - target, "length", ScriptRuntime.wrapNumber(length), cx); - } - - /* Utility functions to encapsulate index > Integer.MAX_VALUE - * handling. Also avoids unnecessary object creation that would - * be necessary to use the general ScriptRuntime.get/setElem - * functions... though this is probably premature optimization. - */ - private static void deleteElem(Scriptable target, long index) { - int i = (int)index; - if (i == index) { target.delete(i); } - else { target.delete(Long.toString(index)); } - } - - private static Object getElem(Context cx, Scriptable target, long index) - { - if (index > Integer.MAX_VALUE) { - String id = Long.toString(index); - return ScriptRuntime.getObjectProp(target, id, cx); - } else { - return ScriptRuntime.getObjectIndex(target, (int)index, cx); - } - } - - private static void setElem(Context cx, Scriptable target, long index, - Object value) - { - if (index > Integer.MAX_VALUE) { - String id = Long.toString(index); - ScriptRuntime.setObjectProp(target, id, value, cx); - } else { - ScriptRuntime.setObjectIndex(target, (int)index, value, cx); - } - } - - private static String toStringHelper(Context cx, Scriptable scope, - Scriptable thisObj, - boolean toSource, boolean toLocale) - { - /* It's probably redundant to handle long lengths in this - * function; StringBuffers are limited to 2^31 in java. - */ - - long length = getLengthProperty(cx, thisObj); - - StringBuffer result = new StringBuffer(256); - - // whether to return '4,unquoted,5' or '[4, "quoted", 5]' - String separator; - - if (toSource) { - result.append('['); - separator = ", "; - } else { - separator = ","; - } - - boolean haslast = false; - long i = 0; - - boolean toplevel, iterating; - if (cx.iterating == null) { - toplevel = true; - iterating = false; - cx.iterating = new ObjToIntMap(31); - } else { - toplevel = false; - iterating = cx.iterating.has(thisObj); - } - - // Make sure cx.iterating is set to null when done - // so we don't leak memory - try { - if (!iterating) { - cx.iterating.put(thisObj, 0); // stop recursion. - for (i = 0; i < length; i++) { - if (i > 0) result.append(separator); - Object elem = getElem(cx, thisObj, i); - if (elem == null || elem == Undefined.instance) { - haslast = false; - continue; - } - haslast = true; - - if (toSource) { - result.append(ScriptRuntime.uneval(cx, scope, elem)); - - } else if (elem instanceof String) { - String s = (String)elem; - if (toSource) { - result.append('\"'); - result.append(ScriptRuntime.escapeString(s)); - result.append('\"'); - } else { - result.append(s); - } - - } else { - if (toLocale) - { - Callable fun; - Scriptable funThis; - fun = ScriptRuntime.getPropFunctionAndThis( - elem, "toLocaleString", cx); - funThis = ScriptRuntime.lastStoredScriptable(cx); - elem = fun.call(cx, scope, funThis, - ScriptRuntime.emptyArgs); - } - result.append(ScriptRuntime.toString(elem)); - } - } - } - } finally { - if (toplevel) { - cx.iterating = null; - } - } - - if (toSource) { - //for [,,].length behavior; we want toString to be symmetric. - if (!haslast && i > 0) - result.append(", ]"); - else - result.append(']'); - } - return result.toString(); - } - - /** - * See ECMA 15.4.4.3 - */ - private static String js_join(Context cx, Scriptable thisObj, - Object[] args) - { - long llength = getLengthProperty(cx, thisObj); - int length = (int)llength; - if (llength != length) { - throw Context.reportRuntimeError1( - "msg.arraylength.too.big", String.valueOf(llength)); - } - // if no args, use "," as separator - String separator = (args.length < 1 || args[0] == Undefined.instance) - ? "," - : ScriptRuntime.toString(args[0]); - if (thisObj instanceof NativeArray) { - NativeArray na = (NativeArray) thisObj; - if (na.denseOnly) { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < length; i++) { - if (i != 0) { - sb.append(separator); - } - if (i < na.dense.length) { - Object temp = na.dense[i]; - if (temp != null && temp != Undefined.instance && - temp != Scriptable.NOT_FOUND) - { - sb.append(ScriptRuntime.toString(temp)); - } - } - } - return sb.toString(); - } - } - if (length == 0) { - return ""; - } - String[] buf = new String[length]; - int total_size = 0; - for (int i = 0; i != length; i++) { - Object temp = getElem(cx, thisObj, i); - if (temp != null && temp != Undefined.instance) { - String str = ScriptRuntime.toString(temp); - total_size += str.length(); - buf[i] = str; - } - } - total_size += (length - 1) * separator.length(); - StringBuffer sb = new StringBuffer(total_size); - for (int i = 0; i != length; i++) { - if (i != 0) { - sb.append(separator); - } - String str = buf[i]; - if (str != null) { - // str == null for undefined or null - sb.append(str); - } - } - return sb.toString(); - } - - /** - * See ECMA 15.4.4.4 - */ - private static Scriptable js_reverse(Context cx, Scriptable thisObj, - Object[] args) - { - if (thisObj instanceof NativeArray) { - NativeArray na = (NativeArray) thisObj; - if (na.denseOnly) { - for (int i=0, j=((int)na.length)-1; i < j; i++,j--) { - Object temp = na.dense[i]; - na.dense[i] = na.dense[j]; - na.dense[j] = temp; - } - return thisObj; - } - } - long len = getLengthProperty(cx, thisObj); - - long half = len / 2; - for(long i=0; i < half; i++) { - long j = len - i - 1; - Object temp1 = getElem(cx, thisObj, i); - Object temp2 = getElem(cx, thisObj, j); - setElem(cx, thisObj, i, temp2); - setElem(cx, thisObj, j, temp1); - } - return thisObj; - } - - /** - * See ECMA 15.4.4.5 - */ - private static Scriptable js_sort(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - long length = getLengthProperty(cx, thisObj); - - if (length <= 1) { return thisObj; } - - Object compare; - Object[] cmpBuf; - - if (args.length > 0 && Undefined.instance != args[0]) { - // sort with given compare function - compare = args[0]; - cmpBuf = new Object[2]; // Buffer for cmp arguments - } else { - // sort with default compare - compare = null; - cmpBuf = null; - } - if (thisObj instanceof NativeArray) { - NativeArray na = (NativeArray) thisObj; - if (na.denseOnly) { - int ilength = (int) length; - heapsort(cx, scope, na.dense, ilength, compare, cmpBuf); - return thisObj; - } - } - - // Should we use the extended sort function, or the faster one? - if (length >= Integer.MAX_VALUE) { - heapsort_extended(cx, scope, thisObj, length, compare, cmpBuf); - } else { - int ilength = (int)length; - // copy the JS array into a working array, so it can be - // sorted cheaply. - Object[] working = new Object[ilength]; - for (int i = 0; i != ilength; ++i) { - working[i] = getElem(cx, thisObj, i); - } - - heapsort(cx, scope, working, ilength, compare, cmpBuf); - - // copy the working array back into thisObj - for (int i = 0; i != ilength; ++i) { - setElem(cx, thisObj, i, working[i]); - } - } - return thisObj; - } - - // Return true only if x > y - private static boolean isBigger(Context cx, Scriptable scope, - Object x, Object y, - Object cmp, Object[] cmpBuf) - { - if (cmp == null) { - if (cmpBuf != null) Kit.codeBug(); - } else { - if (cmpBuf == null || cmpBuf.length != 2) Kit.codeBug(); - } - - Object undef = Undefined.instance; - Object notfound = Scriptable.NOT_FOUND; - - // sort undefined to end - if (y == undef || y == notfound) { - return false; // x can not be bigger then undef - } else if (x == undef || x == notfound) { - return true; // y != undef here, so x > y - } - - if (cmp == null) { - // if no cmp function supplied, sort lexicographically - String a = ScriptRuntime.toString(x); - String b = ScriptRuntime.toString(y); - return a.compareTo(b) > 0; - } - else { - // assemble args and call supplied JS cmp function - cmpBuf[0] = x; - cmpBuf[1] = y; - Callable fun = ScriptRuntime.getValueFunctionAndThis(cmp, cx); - Scriptable funThis = ScriptRuntime.lastStoredScriptable(cx); - - Object ret = fun.call(cx, scope, funThis, cmpBuf); - double d = ScriptRuntime.toNumber(ret); - - // XXX what to do when cmp function returns NaN? ECMA states - // that it's then not a 'consistent comparison function'... but - // then what do we do? Back out and start over with the generic - // cmp function when we see a NaN? Throw an error? - - // for now, just ignore it: - - return d > 0; - } - } - -/** Heapsort implementation. - * See "Introduction to Algorithms" by Cormen, Leiserson, Rivest for details. - * Adjusted for zero based indexes. - */ - private static void heapsort(Context cx, Scriptable scope, - Object[] array, int length, - Object cmp, Object[] cmpBuf) - { - if (length <= 1) Kit.codeBug(); - - // Build heap - for (int i = length / 2; i != 0;) { - --i; - Object pivot = array[i]; - heapify(cx, scope, pivot, array, i, length, cmp, cmpBuf); - } - - // Sort heap - for (int i = length; i != 1;) { - --i; - Object pivot = array[i]; - array[i] = array[0]; - heapify(cx, scope, pivot, array, 0, i, cmp, cmpBuf); - } - } - -/** pivot and child heaps of i should be made into heap starting at i, - * original array[i] is never used to have less array access during sorting. - */ - private static void heapify(Context cx, Scriptable scope, - Object pivot, Object[] array, int i, int end, - Object cmp, Object[] cmpBuf) - { - for (;;) { - int child = i * 2 + 1; - if (child >= end) { - break; - } - Object childVal = array[child]; - if (child + 1 < end) { - Object nextVal = array[child + 1]; - if (isBigger(cx, scope, nextVal, childVal, cmp, cmpBuf)) { - ++child; childVal = nextVal; - } - } - if (!isBigger(cx, scope, childVal, pivot, cmp, cmpBuf)) { - break; - } - array[i] = childVal; - i = child; - } - array[i] = pivot; - } - -/** Version of heapsort that call getElem/setElem on target to query/assign - * array elements instead of Java array access - */ - private static void heapsort_extended(Context cx, Scriptable scope, - Scriptable target, long length, - Object cmp, Object[] cmpBuf) - { - if (length <= 1) Kit.codeBug(); - - // Build heap - for (long i = length / 2; i != 0;) { - --i; - Object pivot = getElem(cx, target, i); - heapify_extended(cx, scope, pivot, target, i, length, cmp, cmpBuf); - } - - // Sort heap - for (long i = length; i != 1;) { - --i; - Object pivot = getElem(cx, target, i); - setElem(cx, target, i, getElem(cx, target, 0)); - heapify_extended(cx, scope, pivot, target, 0, i, cmp, cmpBuf); - } - } - - private static void heapify_extended(Context cx, Scriptable scope, - Object pivot, Scriptable target, - long i, long end, - Object cmp, Object[] cmpBuf) - { - for (;;) { - long child = i * 2 + 1; - if (child >= end) { - break; - } - Object childVal = getElem(cx, target, child); - if (child + 1 < end) { - Object nextVal = getElem(cx, target, child + 1); - if (isBigger(cx, scope, nextVal, childVal, cmp, cmpBuf)) { - ++child; childVal = nextVal; - } - } - if (!isBigger(cx, scope, childVal, pivot, cmp, cmpBuf)) { - break; - } - setElem(cx, target, i, childVal); - i = child; - } - setElem(cx, target, i, pivot); - } - - /** - * Non-ECMA methods. - */ - - private static Object js_push(Context cx, Scriptable thisObj, - Object[] args) - { - if (thisObj instanceof NativeArray) { - NativeArray na = (NativeArray) thisObj; - if (na.denseOnly && - na.ensureCapacity((int) na.length + args.length)) - { - for (int i = 0; i < args.length; i++) { - na.dense[(int)na.length++] = args[i]; - } - return ScriptRuntime.wrapNumber(na.length); - } - } - long length = getLengthProperty(cx, thisObj); - for (int i = 0; i < args.length; i++) { - setElem(cx, thisObj, length + i, args[i]); - } - - length += args.length; - Object lengthObj = setLengthProperty(cx, thisObj, length); - - /* - * If JS1.2, follow Perl4 by returning the last thing pushed. - * Otherwise, return the new array length. - */ - if (cx.getLanguageVersion() == Context.VERSION_1_2) - // if JS1.2 && no arguments, return undefined. - return args.length == 0 - ? Undefined.instance - : args[args.length - 1]; - - else - return lengthObj; - } - - private static Object js_pop(Context cx, Scriptable thisObj, - Object[] args) - { - Object result; - if (thisObj instanceof NativeArray) { - NativeArray na = (NativeArray) thisObj; - if (na.denseOnly && na.length > 0) { - na.length--; - result = na.dense[(int)na.length]; - na.dense[(int)na.length] = NOT_FOUND; - return result; - } - } - long length = getLengthProperty(cx, thisObj); - if (length > 0) { - length--; - - // Get the to-be-deleted property's value. - result = getElem(cx, thisObj, length); - - // We don't need to delete the last property, because - // setLength does that for us. - } else { - result = Undefined.instance; - } - // necessary to match js even when length < 0; js pop will give a - // length property to any target it is called on. - setLengthProperty(cx, thisObj, length); - - return result; - } - - private static Object js_shift(Context cx, Scriptable thisObj, - Object[] args) - { - if (thisObj instanceof NativeArray) { - NativeArray na = (NativeArray) thisObj; - if (na.denseOnly && na.length > 0) { - na.length--; - Object result = na.dense[0]; - System.arraycopy(na.dense, 1, na.dense, 0, (int)na.length); - na.dense[(int)na.length] = NOT_FOUND; - return result; - } - } - Object result; - long length = getLengthProperty(cx, thisObj); - if (length > 0) { - long i = 0; - length--; - - // Get the to-be-deleted property's value. - result = getElem(cx, thisObj, i); - - /* - * Slide down the array above the first element. Leave i - * set to point to the last element. - */ - if (length > 0) { - for (i = 1; i <= length; i++) { - Object temp = getElem(cx, thisObj, i); - setElem(cx, thisObj, i - 1, temp); - } - } - // We don't need to delete the last property, because - // setLength does that for us. - } else { - result = Undefined.instance; - } - setLengthProperty(cx, thisObj, length); - return result; - } - - private static Object js_unshift(Context cx, Scriptable thisObj, - Object[] args) - { - if (thisObj instanceof NativeArray) { - NativeArray na = (NativeArray) thisObj; - if (na.denseOnly && - na.ensureCapacity((int)na.length + args.length)) - { - System.arraycopy(na.dense, 0, na.dense, args.length, - (int) na.length); - for (int i = 0; i < args.length; i++) { - na.dense[i] = args[i]; - } - na.length += args.length; - return ScriptRuntime.wrapNumber(na.length); - } - } - long length = getLengthProperty(cx, thisObj); - int argc = args.length; - - if (args.length > 0) { - /* Slide up the array to make room for args at the bottom */ - if (length > 0) { - for (long last = length - 1; last >= 0; last--) { - Object temp = getElem(cx, thisObj, last); - setElem(cx, thisObj, last + argc, temp); - } - } - - /* Copy from argv to the bottom of the array. */ - for (int i = 0; i < args.length; i++) { - setElem(cx, thisObj, i, args[i]); - } - - /* Follow Perl by returning the new array length. */ - length += args.length; - return setLengthProperty(cx, thisObj, length); - } - return ScriptRuntime.wrapNumber(length); - } - - private static Object js_splice(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - NativeArray na = null; - boolean denseMode = false; - if (thisObj instanceof NativeArray) { - na = (NativeArray) thisObj; - denseMode = na.denseOnly; - } - - /* create an empty Array to return. */ - scope = getTopLevelScope(scope); - int argc = args.length; - if (argc == 0) - return ScriptRuntime.newObject(cx, scope, "Array", null); - long length = getLengthProperty(cx, thisObj); - - /* Convert the first argument into a starting index. */ - long begin = toSliceIndex(ScriptRuntime.toInteger(args[0]), length); - argc--; - - /* Convert the second argument into count */ - long count; - if (args.length == 1) { - count = length - begin; - } else { - double dcount = ScriptRuntime.toInteger(args[1]); - if (dcount < 0) { - count = 0; - } else if (dcount > (length - begin)) { - count = length - begin; - } else { - count = (long)dcount; - } - argc--; - } - - long end = begin + count; - - /* If there are elements to remove, put them into the return value. */ - Object result; - if (count != 0) { - if (count == 1 - && (cx.getLanguageVersion() == Context.VERSION_1_2)) - { - /* - * JS lacks "list context", whereby in Perl one turns the - * single scalar that's spliced out into an array just by - * assigning it to @single instead of $single, or by using it - * as Perl push's first argument, for instance. - * - * JS1.2 emulated Perl too closely and returned a non-Array for - * the single-splice-out case, requiring callers to test and - * wrap in [] if necessary. So JS1.3, default, and other - * versions all return an array of length 1 for uniformity. - */ - result = getElem(cx, thisObj, begin); - } else { - if (denseMode) { - int intLen = (int) (end - begin); - Object[] copy = new Object[intLen]; - System.arraycopy(na.dense, (int) begin, copy, 0, intLen); - result = cx.newArray(scope, copy); - } else { - Scriptable resultArray = ScriptRuntime.newObject(cx, scope, - "Array", null); - for (long last = begin; last != end; last++) { - Object temp = getElem(cx, thisObj, last); - setElem(cx, resultArray, last - begin, temp); - } - result = resultArray; - } - } - } else { // (count == 0) - if (cx.getLanguageVersion() == Context.VERSION_1_2) { - /* Emulate C JS1.2; if no elements are removed, return undefined. */ - result = Undefined.instance; - } else { - result = ScriptRuntime.newObject(cx, scope, "Array", null); - } - } - - /* Find the direction (up or down) to copy and make way for argv. */ - long delta = argc - count; - if (denseMode && length + delta < Integer.MAX_VALUE && - na.ensureCapacity((int) (length + delta))) - { - System.arraycopy(na.dense, (int) end, na.dense, - (int) (begin + argc), (int) (length - end)); - if (argc > 0) { - System.arraycopy(args, 2, na.dense, (int) begin, argc); - } - if (delta < 0) { - Arrays.fill(na.dense, (int) (length + delta), (int) length, - NOT_FOUND); - } - na.length = length + delta; - return result; - } - - if (delta > 0) { - for (long last = length - 1; last >= end; last--) { - Object temp = getElem(cx, thisObj, last); - setElem(cx, thisObj, last + delta, temp); - } - } else if (delta < 0) { - for (long last = end; last < length; last++) { - Object temp = getElem(cx, thisObj, last); - setElem(cx, thisObj, last + delta, temp); - } - } - - /* Copy from argv into the hole to complete the splice. */ - int argoffset = args.length - argc; - for (int i = 0; i < argc; i++) { - setElem(cx, thisObj, begin + i, args[i + argoffset]); - } - - /* Update length in case we deleted elements from the end. */ - setLengthProperty(cx, thisObj, length + delta); - return result; - } - - /* - * See Ecma 262v3 15.4.4.4 - */ - private static Scriptable js_concat(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - // create an empty Array to return. - scope = getTopLevelScope(scope); - Function ctor = ScriptRuntime.getExistingCtor(cx, scope, "Array"); - Scriptable result = ctor.construct(cx, scope, ScriptRuntime.emptyArgs); - if (thisObj instanceof NativeArray && result instanceof NativeArray) { - NativeArray denseThis = (NativeArray) thisObj; - NativeArray denseResult = (NativeArray) result; - if (denseThis.denseOnly && denseResult.denseOnly) { - // First calculate length of resulting array - boolean canUseDense = true; - int length = (int) denseThis.length; - for (int i = 0; i < args.length && canUseDense; i++) { - if (ScriptRuntime.instanceOf(args[i], ctor, cx)) { - // only try to use dense approach for Array-like - // objects that are actually NativeArrays - canUseDense = args[i] instanceof NativeArray; - length += ((NativeArray) args[i]).length; - } else { - length++; - } - } - if (canUseDense && denseResult.ensureCapacity(length)) { - System.arraycopy(denseThis.dense, 0, denseResult.dense, - 0, (int) denseThis.length); - int cursor = (int) denseThis.length; - for (int i = 0; i < args.length && canUseDense; i++) { - if (args[i] instanceof NativeArray) { - NativeArray arg = (NativeArray) args[i]; - System.arraycopy(arg.dense, 0, - denseResult.dense, cursor, - (int)arg.length); - cursor += (int)arg.length; - } else { - denseResult.dense[cursor++] = args[i]; - } - } - denseResult.length = length; - return result; - } - } - } - - long length; - long slot = 0; - - /* Put the target in the result array; only add it as an array - * if it looks like one. - */ - if (ScriptRuntime.instanceOf(thisObj, ctor, cx)) { - length = getLengthProperty(cx, thisObj); - - // Copy from the target object into the result - for (slot = 0; slot < length; slot++) { - Object temp = getElem(cx, thisObj, slot); - setElem(cx, result, slot, temp); - } - } else { - setElem(cx, result, slot++, thisObj); - } - - /* Copy from the arguments into the result. If any argument - * has a numeric length property, treat it as an array and add - * elements separately; otherwise, just copy the argument. - */ - for (int i = 0; i < args.length; i++) { - if (ScriptRuntime.instanceOf(args[i], ctor, cx)) { - // ScriptRuntime.instanceOf => instanceof Scriptable - Scriptable arg = (Scriptable)args[i]; - length = getLengthProperty(cx, arg); - for (long j = 0; j < length; j++, slot++) { - Object temp = getElem(cx, arg, j); - setElem(cx, result, slot, temp); - } - } else { - setElem(cx, result, slot++, args[i]); - } - } - return result; - } - - private Scriptable js_slice(Context cx, Scriptable thisObj, - Object[] args) - { - Scriptable scope = getTopLevelScope(this); - Scriptable result = ScriptRuntime.newObject(cx, scope, "Array", null); - long length = getLengthProperty(cx, thisObj); - - long begin, end; - if (args.length == 0) { - begin = 0; - end = length; - } else { - begin = toSliceIndex(ScriptRuntime.toInteger(args[0]), length); - if (args.length == 1) { - end = length; - } else { - end = toSliceIndex(ScriptRuntime.toInteger(args[1]), length); - } - } - - for (long slot = begin; slot < end; slot++) { - Object temp = getElem(cx, thisObj, slot); - setElem(cx, result, slot - begin, temp); - } - - return result; - } - - private static long toSliceIndex(double value, long length) { - long result; - if (value < 0.0) { - if (value + length < 0.0) { - result = 0; - } else { - result = (long)(value + length); - } - } else if (value > length) { - result = length; - } else { - result = (long)value; - } - return result; - } - - /** - * Implements the methods "indexOf" and "lastIndexOf". - */ - private Object indexOfHelper(Context cx, Scriptable thisObj, - Object[] args, boolean isLast) - { - Object compareTo = args.length > 0 ? args[0] : Undefined.instance; - long length = getLengthProperty(cx, thisObj); - long start; - if (isLast) { - // lastIndexOf - /* - * From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:lastIndexOf - * The index at which to start searching backwards. Defaults to the - * array's length, i.e. the whole array will be searched. If the - * index is greater than or equal to the length of the array, the - * whole array will be searched. If negative, it is taken as the - * offset from the end of the array. Note that even when the index - * is negative, the array is still searched from back to front. If - * the calculated index is less than 0, -1 is returned, i.e. the - * array will not be searched. - */ - if (args.length < 2) { - // default - start = length-1; - } else { - start = ScriptRuntime.toInt32(ScriptRuntime.toNumber(args[1])); - if (start >= length) - start = length-1; - else if (start < 0) - start += length; - // Note that start may be negative, but that's okay - // as the result of -1 will fall out from the code below - } - } else { - // indexOf - /* - * From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf - * The index at which to begin the search. Defaults to 0, i.e. the - * whole array will be searched. If the index is greater than or - * equal to the length of the array, -1 is returned, i.e. the array - * will not be searched. If negative, it is taken as the offset from - * the end of the array. Note that even when the index is negative, - * the array is still searched from front to back. If the calculated - * index is less than 0, the whole array will be searched. - */ - if (args.length < 2) { - // default - start = 0; - } else { - start = ScriptRuntime.toInt32(ScriptRuntime.toNumber(args[1])); - if (start < 0) { - start += length; - if (start < 0) - start = 0; - } - // Note that start may be > length-1, but that's okay - // as the result of -1 will fall out from the code below - } - } - if (thisObj instanceof NativeArray) { - NativeArray na = (NativeArray) thisObj; - if (na.denseOnly) { - if (isLast) { - for (int i=(int)start; i >= 0; i--) { - if (na.dense[i] != Scriptable.NOT_FOUND && - ScriptRuntime.shallowEq(na.dense[i], compareTo)) - { - return new Long(i); - } - } - } else { - for (int i=(int)start; i < length; i++) { - if (na.dense[i] != Scriptable.NOT_FOUND && - ScriptRuntime.shallowEq(na.dense[i], compareTo)) - { - return new Long(i); - } - } - } - return NEGATIVE_ONE; - } - } - if (isLast) { - for (long i=start; i >= 0; i--) { - if (ScriptRuntime.shallowEq(getElem(cx, thisObj, i), compareTo)) { - return new Long(i); - } - } - } else { - for (long i=start; i < length; i++) { - if (ScriptRuntime.shallowEq(getElem(cx, thisObj, i), compareTo)) { - return new Long(i); - } - } - } - return NEGATIVE_ONE; - } - - /** - * Implements the methods "every", "filter", "forEach", "map", and "some". - */ - private Object iterativeMethod(Context cx, int id, Scriptable scope, - Scriptable thisObj, Object[] args) - { - Object callbackArg = args.length > 0 ? args[0] : Undefined.instance; - if (callbackArg == null || !(callbackArg instanceof Function)) { - throw ScriptRuntime.notFunctionError( - ScriptRuntime.toString(callbackArg)); - } - Function f = (Function) callbackArg; - Scriptable parent = ScriptableObject.getTopLevelScope(f); - Scriptable thisArg; - if (args.length < 2 || args[1] == null || args[1] == Undefined.instance) - { - thisArg = parent; - } else { - thisArg = ScriptRuntime.toObject(cx, scope, args[1]); - } - long length = getLengthProperty(cx, thisObj); - Scriptable array = ScriptRuntime.newObject(cx, scope, "Array", null); - long j=0; - for (long i=0; i < length; i++) { - Object[] innerArgs = new Object[3]; - Object elem = (i > Integer.MAX_VALUE) - ? ScriptableObject.getProperty(thisObj, Long.toString(i)) - : ScriptableObject.getProperty(thisObj, (int)i); - if (elem == Scriptable.NOT_FOUND) { - continue; - } - innerArgs[0] = elem; - innerArgs[1] = new Long(i); - innerArgs[2] = thisObj; - Object result = f.call(cx, parent, thisArg, innerArgs); - switch (id) { - case Id_every: - if (!ScriptRuntime.toBoolean(result)) - return Boolean.FALSE; - break; - case Id_filter: - if (ScriptRuntime.toBoolean(result)) - setElem(cx, array, j++, innerArgs[0]); - break; - case Id_forEach: - break; - case Id_map: - setElem(cx, array, i, result); - break; - case Id_some: - if (ScriptRuntime.toBoolean(result)) - return Boolean.TRUE; - break; - } - } - switch (id) { - case Id_every: - return Boolean.TRUE; - case Id_filter: - case Id_map: - return array; - case Id_some: - return Boolean.FALSE; - case Id_forEach: - default: - return Undefined.instance; - } - } - -// #string_id_map# - - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2005-09-26 15:47:42 EDT - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 3: c=s.charAt(0); - if (c=='m') { if (s.charAt(2)=='p' && s.charAt(1)=='a') {id=Id_map; break L0;} } - else if (c=='p') { if (s.charAt(2)=='p' && s.charAt(1)=='o') {id=Id_pop; break L0;} } - break L; - case 4: switch (s.charAt(2)) { - case 'i': X="join";id=Id_join; break L; - case 'm': X="some";id=Id_some; break L; - case 'r': X="sort";id=Id_sort; break L; - case 's': X="push";id=Id_push; break L; - } break L; - case 5: c=s.charAt(1); - if (c=='h') { X="shift";id=Id_shift; } - else if (c=='l') { X="slice";id=Id_slice; } - else if (c=='v') { X="every";id=Id_every; } - break L; - case 6: c=s.charAt(0); - if (c=='c') { X="concat";id=Id_concat; } - else if (c=='f') { X="filter";id=Id_filter; } - else if (c=='s') { X="splice";id=Id_splice; } - break L; - case 7: switch (s.charAt(0)) { - case 'f': X="forEach";id=Id_forEach; break L; - case 'i': X="indexOf";id=Id_indexOf; break L; - case 'r': X="reverse";id=Id_reverse; break L; - case 'u': X="unshift";id=Id_unshift; break L; - } break L; - case 8: c=s.charAt(3); - if (c=='o') { X="toSource";id=Id_toSource; } - else if (c=='t') { X="toString";id=Id_toString; } - break L; - case 11: c=s.charAt(0); - if (c=='c') { X="constructor";id=Id_constructor; } - else if (c=='l') { X="lastIndexOf";id=Id_lastIndexOf; } - break L; - case 14: X="toLocaleString";id=Id_toLocaleString; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - } -// #/generated# - return id; - } - - private static final int - Id_constructor = 1, - Id_toString = 2, - Id_toLocaleString = 3, - Id_toSource = 4, - Id_join = 5, - Id_reverse = 6, - Id_sort = 7, - Id_push = 8, - Id_pop = 9, - Id_shift = 10, - Id_unshift = 11, - Id_splice = 12, - Id_concat = 13, - Id_slice = 14, - Id_indexOf = 15, - Id_lastIndexOf = 16, - Id_every = 17, - Id_filter = 18, - Id_forEach = 19, - Id_map = 20, - Id_some = 21, - - MAX_PROTOTYPE_ID = 21; - -// #/string_id_map# - - private static final int - ConstructorId_join = -Id_join, - ConstructorId_reverse = -Id_reverse, - ConstructorId_sort = -Id_sort, - ConstructorId_push = -Id_push, - ConstructorId_pop = -Id_pop, - ConstructorId_shift = -Id_shift, - ConstructorId_unshift = -Id_unshift, - ConstructorId_splice = -Id_splice, - ConstructorId_concat = -Id_concat, - ConstructorId_slice = -Id_slice, - ConstructorId_indexOf = -Id_indexOf, - ConstructorId_lastIndexOf = -Id_lastIndexOf, - ConstructorId_every = -Id_every, - ConstructorId_filter = -Id_filter, - ConstructorId_forEach = -Id_forEach, - ConstructorId_map = -Id_map, - ConstructorId_some = -Id_some; - - /** - * Internal representation of the JavaScript array's length property. - */ - private long length; - - /** - * Fast storage for dense arrays. Sparse arrays will use the superclass's - * hashtable storage scheme. - */ - private Object[] dense; - - /** - * True if all numeric properties are stored in <code>dense</code>. - */ - private boolean denseOnly; - - /** - * The maximum size of <code>dense</code> that will be allocated initially. - */ - private static int maximumInitialCapacity = 10000; - - /** - * The default capacity for <code>dense</code>. - */ - private static final int DEFAULT_INITIAL_CAPACITY = 10; - - /** - * The factor to grow <code>dense</code> by. - */ - private static final double GROW_FACTOR = 1.5; - private static final int MAX_PRE_GROW_SIZE = (int)(Integer.MAX_VALUE / GROW_FACTOR); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeBoolean.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeBoolean.java deleted file mode 100644 index b6a106a..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeBoolean.java +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class implements the Boolean native object. - * See ECMA 15.6. - * @author Norris Boyd - */ -final class NativeBoolean extends IdScriptableObject -{ - static final long serialVersionUID = -3716996899943880933L; - - private static final Object BOOLEAN_TAG = new Object(); - - static void init(Scriptable scope, boolean sealed) - { - NativeBoolean obj = new NativeBoolean(false); - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - private NativeBoolean(boolean b) - { - booleanValue = b; - } - - public String getClassName() - { - return "Boolean"; - } - - public Object getDefaultValue(Class typeHint) { - // This is actually non-ECMA, but will be proposed - // as a change in round 2. - if (typeHint == ScriptRuntime.BooleanClass) - return ScriptRuntime.wrapBoolean(booleanValue); - return super.getDefaultValue(typeHint); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=1; s="constructor"; break; - case Id_toString: arity=0; s="toString"; break; - case Id_toSource: arity=0; s="toSource"; break; - case Id_valueOf: arity=0; s="valueOf"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(BOOLEAN_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(BOOLEAN_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - - if (id == Id_constructor) { - boolean b; - if (args.length == 0) { - b = false; - } else { - b = args[0] instanceof ScriptableObject && - ((ScriptableObject) args[0]).avoidObjectDetection() - ? true - : ScriptRuntime.toBoolean(args[0]); - } - if (thisObj == null) { - // new Boolean(val) creates a new boolean object. - return new NativeBoolean(b); - } - // Boolean(val) converts val to a boolean. - return ScriptRuntime.wrapBoolean(b); - } - - // The rest of Boolean.prototype methods require thisObj to be Boolean - - if (!(thisObj instanceof NativeBoolean)) - throw incompatibleCallError(f); - boolean value = ((NativeBoolean)thisObj).booleanValue; - - switch (id) { - - case Id_toString: - return value ? "true" : "false"; - - case Id_toSource: - return value ? "(new Boolean(true))" : "(new Boolean(false))"; - - case Id_valueOf: - return ScriptRuntime.wrapBoolean(value); - } - throw new IllegalArgumentException(String.valueOf(id)); - } - -// #string_id_map# - - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:15:31 EDT - L0: { id = 0; String X = null; int c; - int s_length = s.length(); - if (s_length==7) { X="valueOf";id=Id_valueOf; } - else if (s_length==8) { - c=s.charAt(3); - if (c=='o') { X="toSource";id=Id_toSource; } - else if (c=='t') { X="toString";id=Id_toString; } - } - else if (s_length==11) { X="constructor";id=Id_constructor; } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_constructor = 1, - Id_toString = 2, - Id_toSource = 3, - Id_valueOf = 4, - MAX_PROTOTYPE_ID = 4; - -// #/string_id_map# - - private boolean booleanValue; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeCall.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeCall.java deleted file mode 100644 index b196ac3..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeCall.java +++ /dev/null @@ -1,154 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Bob Jervis - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class implements the activation object. - * - * See ECMA 10.1.6 - * - * @see org.mozilla.javascript.Arguments - * @author Norris Boyd - */ -public final class NativeCall extends IdScriptableObject -{ - static final long serialVersionUID = -7471457301304454454L; - - private static final Object CALL_TAG = new Object(); - - static void init(Scriptable scope, boolean sealed) - { - NativeCall obj = new NativeCall(); - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - NativeCall() { } - - NativeCall(NativeFunction function, Scriptable scope, Object[] args) - { - this.function = function; - - setParentScope(scope); - // leave prototype null - - this.originalArgs = (args == null) ? ScriptRuntime.emptyArgs : args; - - // initialize values of arguments - int paramAndVarCount = function.getParamAndVarCount(); - int paramCount = function.getParamCount(); - if (paramAndVarCount != 0) { - for (int i = 0; i < paramCount; ++i) { - String name = function.getParamOrVarName(i); - Object val = i < args.length ? args[i] - : Undefined.instance; - defineProperty(name, val, PERMANENT); - } - } - - // initialize "arguments" property but only if it was not overridden by - // the parameter with the same name - if (!super.has("arguments", this)) { - defineProperty("arguments", new Arguments(this), PERMANENT); - } - - if (paramAndVarCount != 0) { - for (int i = paramCount; i < paramAndVarCount; ++i) { - String name = function.getParamOrVarName(i); - if (!super.has(name, this)) { - if (function.getParamOrVarConst(i)) - defineProperty(name, Undefined.instance, CONST); - else - defineProperty(name, Undefined.instance, PERMANENT); - } - } - } - } - - public String getClassName() - { - return "Call"; - } - - protected int findPrototypeId(String s) - { - return s.equals("constructor") ? Id_constructor : 0; - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - if (id == Id_constructor) { - arity=1; s="constructor"; - } else { - throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(CALL_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(CALL_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - if (id == Id_constructor) { - if (thisObj != null) { - throw Context.reportRuntimeError1("msg.only.from.new", "Call"); - } - ScriptRuntime.checkDeprecated(cx, "Call"); - NativeCall result = new NativeCall(); - result.setPrototype(getObjectPrototype(scope)); - return result; - } - throw new IllegalArgumentException(String.valueOf(id)); - } - - private static final int - Id_constructor = 1, - MAX_PROTOTYPE_ID = 1; - - NativeFunction function; - Object[] originalArgs; - - transient NativeCall parentActivationCall; -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeDate.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeDate.java deleted file mode 100644 index 75d41ab..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeDate.java +++ /dev/null @@ -1,1604 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Peter Annema - * Norris Boyd - * Mike McCabe - * Ilya Frank - * - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.util.Date; -import java.text.DateFormat; - -/** - * This class implements the Date native object. - * See ECMA 15.9. - * @author Mike McCabe - */ -final class NativeDate extends IdScriptableObject -{ - static final long serialVersionUID = -8307438915861678966L; - - private static final Object DATE_TAG = new Object(); - - private static final String js_NaN_date_str = "Invalid Date"; - - static void init(Scriptable scope, boolean sealed) - { - NativeDate obj = new NativeDate(); - // Set the value of the prototype Date to NaN ('invalid date'); - obj.date = ScriptRuntime.NaN; - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - private NativeDate() - { - if (thisTimeZone == null) { - // j.u.TimeZone is synchronized, so setting class statics from it - // should be OK. - thisTimeZone = java.util.TimeZone.getDefault(); - LocalTZA = thisTimeZone.getRawOffset(); - } - } - - public String getClassName() - { - return "Date"; - } - - public Object getDefaultValue(Class typeHint) - { - if (typeHint == null) - typeHint = ScriptRuntime.StringClass; - return super.getDefaultValue(typeHint); - } - - double getJSTimeValue() - { - return date; - } - - protected void fillConstructorProperties(IdFunctionObject ctor) - { - addIdFunctionProperty(ctor, DATE_TAG, ConstructorId_now, - "now", 0); - addIdFunctionProperty(ctor, DATE_TAG, ConstructorId_parse, - "parse", 1); - addIdFunctionProperty(ctor, DATE_TAG, ConstructorId_UTC, - "UTC", 1); - super.fillConstructorProperties(ctor); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=1; s="constructor"; break; - case Id_toString: arity=0; s="toString"; break; - case Id_toTimeString: arity=0; s="toTimeString"; break; - case Id_toDateString: arity=0; s="toDateString"; break; - case Id_toLocaleString: arity=0; s="toLocaleString"; break; - case Id_toLocaleTimeString: arity=0; s="toLocaleTimeString"; break; - case Id_toLocaleDateString: arity=0; s="toLocaleDateString"; break; - case Id_toUTCString: arity=0; s="toUTCString"; break; - case Id_toSource: arity=0; s="toSource"; break; - case Id_valueOf: arity=0; s="valueOf"; break; - case Id_getTime: arity=0; s="getTime"; break; - case Id_getYear: arity=0; s="getYear"; break; - case Id_getFullYear: arity=0; s="getFullYear"; break; - case Id_getUTCFullYear: arity=0; s="getUTCFullYear"; break; - case Id_getMonth: arity=0; s="getMonth"; break; - case Id_getUTCMonth: arity=0; s="getUTCMonth"; break; - case Id_getDate: arity=0; s="getDate"; break; - case Id_getUTCDate: arity=0; s="getUTCDate"; break; - case Id_getDay: arity=0; s="getDay"; break; - case Id_getUTCDay: arity=0; s="getUTCDay"; break; - case Id_getHours: arity=0; s="getHours"; break; - case Id_getUTCHours: arity=0; s="getUTCHours"; break; - case Id_getMinutes: arity=0; s="getMinutes"; break; - case Id_getUTCMinutes: arity=0; s="getUTCMinutes"; break; - case Id_getSeconds: arity=0; s="getSeconds"; break; - case Id_getUTCSeconds: arity=0; s="getUTCSeconds"; break; - case Id_getMilliseconds: arity=0; s="getMilliseconds"; break; - case Id_getUTCMilliseconds: arity=0; s="getUTCMilliseconds"; break; - case Id_getTimezoneOffset: arity=0; s="getTimezoneOffset"; break; - case Id_setTime: arity=1; s="setTime"; break; - case Id_setMilliseconds: arity=1; s="setMilliseconds"; break; - case Id_setUTCMilliseconds: arity=1; s="setUTCMilliseconds"; break; - case Id_setSeconds: arity=2; s="setSeconds"; break; - case Id_setUTCSeconds: arity=2; s="setUTCSeconds"; break; - case Id_setMinutes: arity=3; s="setMinutes"; break; - case Id_setUTCMinutes: arity=3; s="setUTCMinutes"; break; - case Id_setHours: arity=4; s="setHours"; break; - case Id_setUTCHours: arity=4; s="setUTCHours"; break; - case Id_setDate: arity=1; s="setDate"; break; - case Id_setUTCDate: arity=1; s="setUTCDate"; break; - case Id_setMonth: arity=2; s="setMonth"; break; - case Id_setUTCMonth: arity=2; s="setUTCMonth"; break; - case Id_setFullYear: arity=3; s="setFullYear"; break; - case Id_setUTCFullYear: arity=3; s="setUTCFullYear"; break; - case Id_setYear: arity=1; s="setYear"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(DATE_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(DATE_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case ConstructorId_now: - return ScriptRuntime.wrapNumber(now()); - - case ConstructorId_parse: - { - String dataStr = ScriptRuntime.toString(args, 0); - return ScriptRuntime.wrapNumber(date_parseString(dataStr)); - } - - case ConstructorId_UTC: - return ScriptRuntime.wrapNumber(jsStaticFunction_UTC(args)); - - case Id_constructor: - { - // if called as a function, just return a string - // representing the current time. - if (thisObj != null) - return date_format(now(), Id_toString); - return jsConstructor(args); - } - } - - // The rest of Date.prototype methods require thisObj to be Date - - if (!(thisObj instanceof NativeDate)) - throw incompatibleCallError(f); - NativeDate realThis = (NativeDate)thisObj; - double t = realThis.date; - - switch (id) { - - case Id_toString: - case Id_toTimeString: - case Id_toDateString: - if (t == t) { - return date_format(t, id); - } - return js_NaN_date_str; - - case Id_toLocaleString: - case Id_toLocaleTimeString: - case Id_toLocaleDateString: - if (t == t) { - return toLocale_helper(t, id); - } - return js_NaN_date_str; - - case Id_toUTCString: - if (t == t) { - return js_toUTCString(t); - } - return js_NaN_date_str; - - case Id_toSource: - return "(new Date("+ScriptRuntime.toString(t)+"))"; - - case Id_valueOf: - case Id_getTime: - return ScriptRuntime.wrapNumber(t); - - case Id_getYear: - case Id_getFullYear: - case Id_getUTCFullYear: - if (t == t) { - if (id != Id_getUTCFullYear) t = LocalTime(t); - t = YearFromTime(t); - if (id == Id_getYear) { - if (cx.hasFeature(Context.FEATURE_NON_ECMA_GET_YEAR)) { - if (1900 <= t && t < 2000) { - t -= 1900; - } - } else { - t -= 1900; - } - } - } - return ScriptRuntime.wrapNumber(t); - - case Id_getMonth: - case Id_getUTCMonth: - if (t == t) { - if (id == Id_getMonth) t = LocalTime(t); - t = MonthFromTime(t); - } - return ScriptRuntime.wrapNumber(t); - - case Id_getDate: - case Id_getUTCDate: - if (t == t) { - if (id == Id_getDate) t = LocalTime(t); - t = DateFromTime(t); - } - return ScriptRuntime.wrapNumber(t); - - case Id_getDay: - case Id_getUTCDay: - if (t == t) { - if (id == Id_getDay) t = LocalTime(t); - t = WeekDay(t); - } - return ScriptRuntime.wrapNumber(t); - - case Id_getHours: - case Id_getUTCHours: - if (t == t) { - if (id == Id_getHours) t = LocalTime(t); - t = HourFromTime(t); - } - return ScriptRuntime.wrapNumber(t); - - case Id_getMinutes: - case Id_getUTCMinutes: - if (t == t) { - if (id == Id_getMinutes) t = LocalTime(t); - t = MinFromTime(t); - } - return ScriptRuntime.wrapNumber(t); - - case Id_getSeconds: - case Id_getUTCSeconds: - if (t == t) { - if (id == Id_getSeconds) t = LocalTime(t); - t = SecFromTime(t); - } - return ScriptRuntime.wrapNumber(t); - - case Id_getMilliseconds: - case Id_getUTCMilliseconds: - if (t == t) { - if (id == Id_getMilliseconds) t = LocalTime(t); - t = msFromTime(t); - } - return ScriptRuntime.wrapNumber(t); - - case Id_getTimezoneOffset: - if (t == t) { - t = (t - LocalTime(t)) / msPerMinute; - } - return ScriptRuntime.wrapNumber(t); - - case Id_setTime: - t = TimeClip(ScriptRuntime.toNumber(args, 0)); - realThis.date = t; - return ScriptRuntime.wrapNumber(t); - - case Id_setMilliseconds: - case Id_setUTCMilliseconds: - case Id_setSeconds: - case Id_setUTCSeconds: - case Id_setMinutes: - case Id_setUTCMinutes: - case Id_setHours: - case Id_setUTCHours: - t = makeTime(t, args, id); - realThis.date = t; - return ScriptRuntime.wrapNumber(t); - - case Id_setDate: - case Id_setUTCDate: - case Id_setMonth: - case Id_setUTCMonth: - case Id_setFullYear: - case Id_setUTCFullYear: - t = makeDate(t, args, id); - realThis.date = t; - return ScriptRuntime.wrapNumber(t); - - case Id_setYear: - { - double year = ScriptRuntime.toNumber(args, 0); - - if (year != year || Double.isInfinite(year)) { - t = ScriptRuntime.NaN; - } else { - if (t != t) { - t = 0; - } else { - t = LocalTime(t); - } - - if (year >= 0 && year <= 99) - year += 1900; - - double day = MakeDay(year, MonthFromTime(t), - DateFromTime(t)); - t = MakeDate(day, TimeWithinDay(t)); - t = internalUTC(t); - t = TimeClip(t); - } - } - realThis.date = t; - return ScriptRuntime.wrapNumber(t); - - default: throw new IllegalArgumentException(String.valueOf(id)); - } - - } - - /* ECMA helper functions */ - - private static final double HalfTimeDomain = 8.64e15; - private static final double HoursPerDay = 24.0; - private static final double MinutesPerHour = 60.0; - private static final double SecondsPerMinute = 60.0; - private static final double msPerSecond = 1000.0; - private static final double MinutesPerDay = (HoursPerDay * MinutesPerHour); - private static final double SecondsPerDay = (MinutesPerDay * SecondsPerMinute); - private static final double SecondsPerHour = (MinutesPerHour * SecondsPerMinute); - private static final double msPerDay = (SecondsPerDay * msPerSecond); - private static final double msPerHour = (SecondsPerHour * msPerSecond); - private static final double msPerMinute = (SecondsPerMinute * msPerSecond); - - private static double Day(double t) - { - return Math.floor(t / msPerDay); - } - - private static double TimeWithinDay(double t) - { - double result; - result = t % msPerDay; - if (result < 0) - result += msPerDay; - return result; - } - - private static boolean IsLeapYear(int year) - { - return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); - } - - /* math here has to be f.p, because we need - * floor((1968 - 1969) / 4) == -1 - */ - private static double DayFromYear(double y) - { - return ((365 * ((y)-1970) + Math.floor(((y)-1969)/4.0) - - Math.floor(((y)-1901)/100.0) + Math.floor(((y)-1601)/400.0))); - } - - private static double TimeFromYear(double y) - { - return DayFromYear(y) * msPerDay; - } - - private static int YearFromTime(double t) - { - int lo = (int) Math.floor((t / msPerDay) / 366) + 1970; - int hi = (int) Math.floor((t / msPerDay) / 365) + 1970; - int mid; - - /* above doesn't work for negative dates... */ - if (hi < lo) { - int temp = lo; - lo = hi; - hi = temp; - } - - /* Use a simple binary search algorithm to find the right - year. This seems like brute force... but the computation - of hi and lo years above lands within one year of the - correct answer for years within a thousand years of - 1970; the loop below only requires six iterations - for year 270000. */ - while (hi > lo) { - mid = (hi + lo) / 2; - if (TimeFromYear(mid) > t) { - hi = mid - 1; - } else { - lo = mid + 1; - if (TimeFromYear(lo) > t) { - return mid; - } - } - } - return lo; - } - - private static double DayFromMonth(int m, int year) - { - int day = m * 30; - - if (m >= 7) { day += m / 2 - 1; } - else if (m >= 2) { day += (m - 1) / 2 - 1; } - else { day += m; } - - if (m >= 2 && IsLeapYear(year)) { ++day; } - - return day; - } - - private static int MonthFromTime(double t) - { - int year = YearFromTime(t); - int d = (int)(Day(t) - DayFromYear(year)); - - d -= 31 + 28; - if (d < 0) { - return (d < -28) ? 0 : 1; - } - - if (IsLeapYear(year)) { - if (d == 0) - return 1; // 29 February - --d; - } - - // d: date count from 1 March - int estimate = d / 30; // approx number of month since March - int mstart; - switch (estimate) { - case 0: return 2; - case 1: mstart = 31; break; - case 2: mstart = 31+30; break; - case 3: mstart = 31+30+31; break; - case 4: mstart = 31+30+31+30; break; - case 5: mstart = 31+30+31+30+31; break; - case 6: mstart = 31+30+31+30+31+31; break; - case 7: mstart = 31+30+31+30+31+31+30; break; - case 8: mstart = 31+30+31+30+31+31+30+31; break; - case 9: mstart = 31+30+31+30+31+31+30+31+30; break; - case 10: return 11; //Late december - default: throw Kit.codeBug(); - } - // if d < mstart then real month since March == estimate - 1 - return (d >= mstart) ? estimate + 2 : estimate + 1; - } - - private static int DateFromTime(double t) - { - int year = YearFromTime(t); - int d = (int)(Day(t) - DayFromYear(year)); - - d -= 31 + 28; - if (d < 0) { - return (d < -28) ? d + 31 + 28 + 1 : d + 28 + 1; - } - - if (IsLeapYear(year)) { - if (d == 0) - return 29; // 29 February - --d; - } - - // d: date count from 1 March - int mdays, mstart; - switch (d / 30) { // approx number of month since March - case 0: return d + 1; - case 1: mdays = 31; mstart = 31; break; - case 2: mdays = 30; mstart = 31+30; break; - case 3: mdays = 31; mstart = 31+30+31; break; - case 4: mdays = 30; mstart = 31+30+31+30; break; - case 5: mdays = 31; mstart = 31+30+31+30+31; break; - case 6: mdays = 31; mstart = 31+30+31+30+31+31; break; - case 7: mdays = 30; mstart = 31+30+31+30+31+31+30; break; - case 8: mdays = 31; mstart = 31+30+31+30+31+31+30+31; break; - case 9: mdays = 30; mstart = 31+30+31+30+31+31+30+31+30; break; - case 10: - return d - (31+30+31+30+31+31+30+31+30) + 1; //Late december - default: throw Kit.codeBug(); - } - d -= mstart; - if (d < 0) { - // wrong estimate: sfhift to previous month - d += mdays; - } - return d + 1; - } - - private static int WeekDay(double t) - { - double result; - result = Day(t) + 4; - result = result % 7; - if (result < 0) - result += 7; - return (int) result; - } - - private static double now() - { - return System.currentTimeMillis(); - } - - /* Should be possible to determine the need for this dynamically - * if we go with the workaround... I'm not using it now, because I - * can't think of any clean way to make toLocaleString() and the - * time zone (comment) in toString match the generated string - * values. Currently it's wrong-but-consistent in all but the - * most recent betas of the JRE - seems to work in 1.1.7. - */ - private final static boolean TZO_WORKAROUND = false; - private static double DaylightSavingTA(double t) - { - // Another workaround! The JRE doesn't seem to know about DST - // before year 1 AD, so we map to equivalent dates for the - // purposes of finding dst. To be safe, we do this for years - // outside 1970-2038. - if (t < 0.0 || t > 2145916800000.0) { - int year = EquivalentYear(YearFromTime(t)); - double day = MakeDay(year, MonthFromTime(t), DateFromTime(t)); - t = MakeDate(day, TimeWithinDay(t)); - } - if (!TZO_WORKAROUND) { - Date date = new Date((long) t); - if (thisTimeZone.inDaylightTime(date)) - return msPerHour; - else - return 0; - } else { - /* Use getOffset if inDaylightTime() is broken, because it - * seems to work acceptably. We don't switch over to it - * entirely, because it requires (expensive) exploded date arguments, - * and the api makes it impossible to handle dst - * changeovers cleanly. - */ - - // Hardcode the assumption that the changeover always - // happens at 2:00 AM: - t += LocalTZA + (HourFromTime(t) <= 2 ? msPerHour : 0); - - int year = YearFromTime(t); - double offset = thisTimeZone.getOffset(year > 0 ? 1 : 0, - year, - MonthFromTime(t), - DateFromTime(t), - WeekDay(t), - (int)TimeWithinDay(t)); - - if ((offset - LocalTZA) != 0) - return msPerHour; - else - return 0; - // return offset - LocalTZA; - } - } - - /* - * Find a year for which any given date will fall on the same weekday. - * - * This function should be used with caution when used other than - * for determining DST; it hasn't been proven not to produce an - * incorrect year for times near year boundaries. - */ - private static int EquivalentYear(int year) - { - int day = (int) DayFromYear(year) + 4; - day = day % 7; - if (day < 0) - day += 7; - // Years and leap years on which Jan 1 is a Sunday, Monday, etc. - if (IsLeapYear(year)) { - switch (day) { - case 0: return 1984; - case 1: return 1996; - case 2: return 1980; - case 3: return 1992; - case 4: return 1976; - case 5: return 1988; - case 6: return 1972; - } - } else { - switch (day) { - case 0: return 1978; - case 1: return 1973; - case 2: return 1974; - case 3: return 1975; - case 4: return 1981; - case 5: return 1971; - case 6: return 1977; - } - } - // Unreachable - throw Kit.codeBug(); - } - - private static double LocalTime(double t) - { - return t + LocalTZA + DaylightSavingTA(t); - } - - private static double internalUTC(double t) - { - return t - LocalTZA - DaylightSavingTA(t - LocalTZA); - } - - private static int HourFromTime(double t) - { - double result; - result = Math.floor(t / msPerHour) % HoursPerDay; - if (result < 0) - result += HoursPerDay; - return (int) result; - } - - private static int MinFromTime(double t) - { - double result; - result = Math.floor(t / msPerMinute) % MinutesPerHour; - if (result < 0) - result += MinutesPerHour; - return (int) result; - } - - private static int SecFromTime(double t) - { - double result; - result = Math.floor(t / msPerSecond) % SecondsPerMinute; - if (result < 0) - result += SecondsPerMinute; - return (int) result; - } - - private static int msFromTime(double t) - { - double result; - result = t % msPerSecond; - if (result < 0) - result += msPerSecond; - return (int) result; - } - - private static double MakeTime(double hour, double min, - double sec, double ms) - { - return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) - * msPerSecond + ms; - } - - private static double MakeDay(double year, double month, double date) - { - year += Math.floor(month / 12); - - month = month % 12; - if (month < 0) - month += 12; - - double yearday = Math.floor(TimeFromYear(year) / msPerDay); - double monthday = DayFromMonth((int)month, (int)year); - - return yearday + monthday + date - 1; - } - - private static double MakeDate(double day, double time) - { - return day * msPerDay + time; - } - - private static double TimeClip(double d) - { - if (d != d || - d == Double.POSITIVE_INFINITY || - d == Double.NEGATIVE_INFINITY || - Math.abs(d) > HalfTimeDomain) - { - return ScriptRuntime.NaN; - } - if (d > 0.0) - return Math.floor(d + 0.); - else - return Math.ceil(d + 0.); - } - - /* end of ECMA helper functions */ - - /* find UTC time from given date... no 1900 correction! */ - private static double date_msecFromDate(double year, double mon, - double mday, double hour, - double min, double sec, - double msec) - { - double day; - double time; - double result; - - day = MakeDay(year, mon, mday); - time = MakeTime(hour, min, sec, msec); - result = MakeDate(day, time); - return result; - } - - /* compute the time in msec (unclipped) from the given args */ - private static final int MAXARGS = 7; - private static double date_msecFromArgs(Object[] args) - { - double array[] = new double[MAXARGS]; - int loop; - double d; - - for (loop = 0; loop < MAXARGS; loop++) { - if (loop < args.length) { - d = ScriptRuntime.toNumber(args[loop]); - if (d != d || Double.isInfinite(d)) { - return ScriptRuntime.NaN; - } - array[loop] = ScriptRuntime.toInteger(args[loop]); - } else { - if (loop == 2) { - array[loop] = 1; /* Default the date argument to 1. */ - } else { - array[loop] = 0; - } - } - } - - /* adjust 2-digit years into the 20th century */ - if (array[0] >= 0 && array[0] <= 99) - array[0] += 1900; - - return date_msecFromDate(array[0], array[1], array[2], - array[3], array[4], array[5], array[6]); - } - - private static double jsStaticFunction_UTC(Object[] args) - { - return TimeClip(date_msecFromArgs(args)); - } - - private static double date_parseString(String s) - { - int year = -1; - int mon = -1; - int mday = -1; - int hour = -1; - int min = -1; - int sec = -1; - char c = 0; - char si = 0; - int i = 0; - int n = -1; - double tzoffset = -1; - char prevc = 0; - int limit = 0; - boolean seenplusminus = false; - - limit = s.length(); - while (i < limit) { - c = s.charAt(i); - i++; - if (c <= ' ' || c == ',' || c == '-') { - if (i < limit) { - si = s.charAt(i); - if (c == '-' && '0' <= si && si <= '9') { - prevc = c; - } - } - continue; - } - if (c == '(') { /* comments) */ - int depth = 1; - while (i < limit) { - c = s.charAt(i); - i++; - if (c == '(') - depth++; - else if (c == ')') - if (--depth <= 0) - break; - } - continue; - } - if ('0' <= c && c <= '9') { - n = c - '0'; - while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') { - n = n * 10 + c - '0'; - i++; - } - - /* allow TZA before the year, so - * 'Wed Nov 05 21:49:11 GMT-0800 1997' - * works */ - - /* uses of seenplusminus allow : in TZA, so Java - * no-timezone style of GMT+4:30 works - */ - if ((prevc == '+' || prevc == '-')/* && year>=0 */) { - /* make ':' case below change tzoffset */ - seenplusminus = true; - - /* offset */ - if (n < 24) - n = n * 60; /* EG. "GMT-3" */ - else - n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */ - if (prevc == '+') /* plus means east of GMT */ - n = -n; - if (tzoffset != 0 && tzoffset != -1) - return ScriptRuntime.NaN; - tzoffset = n; - } else if (n >= 70 || - (prevc == '/' && mon >= 0 && mday >= 0 - && year < 0)) - { - if (year >= 0) - return ScriptRuntime.NaN; - else if (c <= ' ' || c == ',' || c == '/' || i >= limit) - year = n < 100 ? n + 1900 : n; - else - return ScriptRuntime.NaN; - } else if (c == ':') { - if (hour < 0) - hour = /*byte*/ n; - else if (min < 0) - min = /*byte*/ n; - else - return ScriptRuntime.NaN; - } else if (c == '/') { - if (mon < 0) - mon = /*byte*/ n-1; - else if (mday < 0) - mday = /*byte*/ n; - else - return ScriptRuntime.NaN; - } else if (i < limit && c != ',' && c > ' ' && c != '-') { - return ScriptRuntime.NaN; - } else if (seenplusminus && n < 60) { /* handle GMT-3:30 */ - if (tzoffset < 0) - tzoffset -= n; - else - tzoffset += n; - } else if (hour >= 0 && min < 0) { - min = /*byte*/ n; - } else if (min >= 0 && sec < 0) { - sec = /*byte*/ n; - } else if (mday < 0) { - mday = /*byte*/ n; - } else { - return ScriptRuntime.NaN; - } - prevc = 0; - } else if (c == '/' || c == ':' || c == '+' || c == '-') { - prevc = c; - } else { - int st = i - 1; - while (i < limit) { - c = s.charAt(i); - if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))) - break; - i++; - } - int letterCount = i - st; - if (letterCount < 2) - return ScriptRuntime.NaN; - /* - * Use ported code from jsdate.c rather than the locale-specific - * date-parsing code from Java, to keep js and rhino consistent. - * Is this the right strategy? - */ - String wtb = "am;pm;" - +"monday;tuesday;wednesday;thursday;friday;" - +"saturday;sunday;" - +"january;february;march;april;may;june;" - +"july;august;september;october;november;december;" - +"gmt;ut;utc;est;edt;cst;cdt;mst;mdt;pst;pdt;"; - int index = 0; - for (int wtbOffset = 0; ;) { - int wtbNext = wtb.indexOf(';', wtbOffset); - if (wtbNext < 0) - return ScriptRuntime.NaN; - if (wtb.regionMatches(true, wtbOffset, s, st, letterCount)) - break; - wtbOffset = wtbNext + 1; - ++index; - } - if (index < 2) { - /* - * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as - * 12:30, instead of blindly adding 12 if PM. - */ - if (hour > 12 || hour < 0) { - return ScriptRuntime.NaN; - } else if (index == 0) { - // AM - if (hour == 12) - hour = 0; - } else { - // PM - if (hour != 12) - hour += 12; - } - } else if ((index -= 2) < 7) { - // ignore week days - } else if ((index -= 7) < 12) { - // month - if (mon < 0) { - mon = index; - } else { - return ScriptRuntime.NaN; - } - } else { - index -= 12; - // timezones - switch (index) { - case 0 /* gmt */: tzoffset = 0; break; - case 1 /* ut */: tzoffset = 0; break; - case 2 /* utc */: tzoffset = 0; break; - case 3 /* est */: tzoffset = 5 * 60; break; - case 4 /* edt */: tzoffset = 4 * 60; break; - case 5 /* cst */: tzoffset = 6 * 60; break; - case 6 /* cdt */: tzoffset = 5 * 60; break; - case 7 /* mst */: tzoffset = 7 * 60; break; - case 8 /* mdt */: tzoffset = 6 * 60; break; - case 9 /* pst */: tzoffset = 8 * 60; break; - case 10 /* pdt */:tzoffset = 7 * 60; break; - default: Kit.codeBug(); - } - } - } - } - if (year < 0 || mon < 0 || mday < 0) - return ScriptRuntime.NaN; - if (sec < 0) - sec = 0; - if (min < 0) - min = 0; - if (hour < 0) - hour = 0; - - double msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0); - if (tzoffset == -1) { /* no time zone specified, have to use local */ - return internalUTC(msec); - } else { - return msec + tzoffset * msPerMinute; - } - } - - private static String date_format(double t, int methodId) - { - StringBuffer result = new StringBuffer(60); - double local = LocalTime(t); - - /* Tue Oct 31 09:41:40 GMT-0800 (PST) 2000 */ - /* Tue Oct 31 2000 */ - /* 09:41:40 GMT-0800 (PST) */ - - if (methodId != Id_toTimeString) { - appendWeekDayName(result, WeekDay(local)); - result.append(' '); - appendMonthName(result, MonthFromTime(local)); - result.append(' '); - append0PaddedUint(result, DateFromTime(local), 2); - result.append(' '); - int year = YearFromTime(local); - if (year < 0) { - result.append('-'); - year = -year; - } - append0PaddedUint(result, year, 4); - if (methodId != Id_toDateString) - result.append(' '); - } - - if (methodId != Id_toDateString) { - append0PaddedUint(result, HourFromTime(local), 2); - result.append(':'); - append0PaddedUint(result, MinFromTime(local), 2); - result.append(':'); - append0PaddedUint(result, SecFromTime(local), 2); - - // offset from GMT in minutes. The offset includes daylight - // savings, if it applies. - int minutes = (int) Math.floor((LocalTZA + DaylightSavingTA(t)) - / msPerMinute); - // map 510 minutes to 0830 hours - int offset = (minutes / 60) * 100 + minutes % 60; - if (offset > 0) { - result.append(" GMT+"); - } else { - result.append(" GMT-"); - offset = -offset; - } - append0PaddedUint(result, offset, 4); - - if (timeZoneFormatter == null) - timeZoneFormatter = new java.text.SimpleDateFormat("zzz"); - - // Find an equivalent year before getting the timezone - // comment. See DaylightSavingTA. - if (t < 0.0 || t > 2145916800000.0) { - int equiv = EquivalentYear(YearFromTime(local)); - double day = MakeDay(equiv, MonthFromTime(t), DateFromTime(t)); - t = MakeDate(day, TimeWithinDay(t)); - } - result.append(" ("); - java.util.Date date = new Date((long) t); - synchronized (timeZoneFormatter) { - result.append(timeZoneFormatter.format(date)); - } - result.append(')'); - } - return result.toString(); - } - - /* the javascript constructor */ - private static Object jsConstructor(Object[] args) - { - NativeDate obj = new NativeDate(); - - // if called as a constructor with no args, - // return a new Date with the current time. - if (args.length == 0) { - obj.date = now(); - return obj; - } - - // if called with just one arg - - if (args.length == 1) { - Object arg0 = args[0]; - if (arg0 instanceof Scriptable) - arg0 = ((Scriptable) arg0).getDefaultValue(null); - double date; - if (arg0 instanceof String) { - // it's a string; parse it. - date = date_parseString((String)arg0); - } else { - // if it's not a string, use it as a millisecond date - date = ScriptRuntime.toNumber(arg0); - } - obj.date = TimeClip(date); - return obj; - } - - double time = date_msecFromArgs(args); - - if (!Double.isNaN(time) && !Double.isInfinite(time)) - time = TimeClip(internalUTC(time)); - - obj.date = time; - - return obj; - } - - private static String toLocale_helper(double t, int methodId) - { - java.text.DateFormat formatter; - switch (methodId) { - case Id_toLocaleString: - if (localeDateTimeFormatter == null) { - localeDateTimeFormatter - = DateFormat.getDateTimeInstance(DateFormat.LONG, - DateFormat.LONG); - } - formatter = localeDateTimeFormatter; - break; - case Id_toLocaleTimeString: - if (localeTimeFormatter == null) { - localeTimeFormatter - = DateFormat.getTimeInstance(DateFormat.LONG); - } - formatter = localeTimeFormatter; - break; - case Id_toLocaleDateString: - if (localeDateFormatter == null) { - localeDateFormatter - = DateFormat.getDateInstance(DateFormat.LONG); - } - formatter = localeDateFormatter; - break; - default: formatter = null; // unreachable - } - - synchronized (formatter) { - return formatter.format(new Date((long) t)); - } - } - - private static String js_toUTCString(double date) - { - StringBuffer result = new StringBuffer(60); - - appendWeekDayName(result, WeekDay(date)); - result.append(", "); - append0PaddedUint(result, DateFromTime(date), 2); - result.append(' '); - appendMonthName(result, MonthFromTime(date)); - result.append(' '); - int year = YearFromTime(date); - if (year < 0) { - result.append('-'); year = -year; - } - append0PaddedUint(result, year, 4); - result.append(' '); - append0PaddedUint(result, HourFromTime(date), 2); - result.append(':'); - append0PaddedUint(result, MinFromTime(date), 2); - result.append(':'); - append0PaddedUint(result, SecFromTime(date), 2); - result.append(" GMT"); - return result.toString(); - } - - private static void append0PaddedUint(StringBuffer sb, int i, int minWidth) - { - if (i < 0) Kit.codeBug(); - int scale = 1; - --minWidth; - if (i >= 10) { - if (i < 1000 * 1000 * 1000) { - for (;;) { - int newScale = scale * 10; - if (i < newScale) { break; } - --minWidth; - scale = newScale; - } - } else { - // Separated case not to check against 10 * 10^9 overflow - minWidth -= 9; - scale = 1000 * 1000 * 1000; - } - } - while (minWidth > 0) { - sb.append('0'); - --minWidth; - } - while (scale != 1) { - sb.append((char)('0' + (i / scale))); - i %= scale; - scale /= 10; - } - sb.append((char)('0' + i)); - } - - private static void appendMonthName(StringBuffer sb, int index) - { - // Take advantage of the fact that all month abbreviations - // have the same length to minimize amount of strings runtime has - // to keep in memory - String months = "Jan"+"Feb"+"Mar"+"Apr"+"May"+"Jun" - +"Jul"+"Aug"+"Sep"+"Oct"+"Nov"+"Dec"; - index *= 3; - for (int i = 0; i != 3; ++i) { - sb.append(months.charAt(index + i)); - } - } - - private static void appendWeekDayName(StringBuffer sb, int index) - { - String days = "Sun"+"Mon"+"Tue"+"Wed"+"Thu"+"Fri"+"Sat"; - index *= 3; - for (int i = 0; i != 3; ++i) { - sb.append(days.charAt(index + i)); - } - } - - private static double makeTime(double date, Object[] args, int methodId) - { - int maxargs; - boolean local = true; - switch (methodId) { - case Id_setUTCMilliseconds: - local = false; - // fallthrough - case Id_setMilliseconds: - maxargs = 1; - break; - - case Id_setUTCSeconds: - local = false; - // fallthrough - case Id_setSeconds: - maxargs = 2; - break; - - case Id_setUTCMinutes: - local = false; - // fallthrough - case Id_setMinutes: - maxargs = 3; - break; - - case Id_setUTCHours: - local = false; - // fallthrough - case Id_setHours: - maxargs = 4; - break; - - default: - Kit.codeBug(); - maxargs = 0; - } - - int i; - double conv[] = new double[4]; - double hour, min, sec, msec; - double lorutime; /* Local or UTC version of date */ - - double time; - double result; - - /* just return NaN if the date is already NaN */ - if (date != date) - return date; - - /* Satisfy the ECMA rule that if a function is called with - * fewer arguments than the specified formal arguments, the - * remaining arguments are set to undefined. Seems like all - * the Date.setWhatever functions in ECMA are only varargs - * beyond the first argument; this should be set to undefined - * if it's not given. This means that "d = new Date(); - * d.setMilliseconds()" returns NaN. Blech. - */ - if (args.length == 0) - args = ScriptRuntime.padArguments(args, 1); - - for (i = 0; i < args.length && i < maxargs; i++) { - conv[i] = ScriptRuntime.toNumber(args[i]); - - // limit checks that happen in MakeTime in ECMA. - if (conv[i] != conv[i] || Double.isInfinite(conv[i])) { - return ScriptRuntime.NaN; - } - conv[i] = ScriptRuntime.toInteger(conv[i]); - } - - if (local) - lorutime = LocalTime(date); - else - lorutime = date; - - i = 0; - int stop = args.length; - - if (maxargs >= 4 && i < stop) - hour = conv[i++]; - else - hour = HourFromTime(lorutime); - - if (maxargs >= 3 && i < stop) - min = conv[i++]; - else - min = MinFromTime(lorutime); - - if (maxargs >= 2 && i < stop) - sec = conv[i++]; - else - sec = SecFromTime(lorutime); - - if (maxargs >= 1 && i < stop) - msec = conv[i++]; - else - msec = msFromTime(lorutime); - - time = MakeTime(hour, min, sec, msec); - result = MakeDate(Day(lorutime), time); - - if (local) - result = internalUTC(result); - date = TimeClip(result); - - return date; - } - - private static double makeDate(double date, Object[] args, int methodId) - { - int maxargs; - boolean local = true; - switch (methodId) { - case Id_setUTCDate: - local = false; - // fallthrough - case Id_setDate: - maxargs = 1; - break; - - case Id_setUTCMonth: - local = false; - // fallthrough - case Id_setMonth: - maxargs = 2; - break; - - case Id_setUTCFullYear: - local = false; - // fallthrough - case Id_setFullYear: - maxargs = 3; - break; - - default: - Kit.codeBug(); - maxargs = 0; - } - - int i; - double conv[] = new double[3]; - double year, month, day; - double lorutime; /* local or UTC version of date */ - double result; - - /* See arg padding comment in makeTime.*/ - if (args.length == 0) - args = ScriptRuntime.padArguments(args, 1); - - for (i = 0; i < args.length && i < maxargs; i++) { - conv[i] = ScriptRuntime.toNumber(args[i]); - - // limit checks that happen in MakeDate in ECMA. - if (conv[i] != conv[i] || Double.isInfinite(conv[i])) { - return ScriptRuntime.NaN; - } - conv[i] = ScriptRuntime.toInteger(conv[i]); - } - - /* return NaN if date is NaN and we're not setting the year, - * If we are, use 0 as the time. */ - if (date != date) { - if (args.length < 3) { - return ScriptRuntime.NaN; - } else { - lorutime = 0; - } - } else { - if (local) - lorutime = LocalTime(date); - else - lorutime = date; - } - - i = 0; - int stop = args.length; - - if (maxargs >= 3 && i < stop) - year = conv[i++]; - else - year = YearFromTime(lorutime); - - if (maxargs >= 2 && i < stop) - month = conv[i++]; - else - month = MonthFromTime(lorutime); - - if (maxargs >= 1 && i < stop) - day = conv[i++]; - else - day = DateFromTime(lorutime); - - day = MakeDay(year, month, day); /* day within year */ - result = MakeDate(day, TimeWithinDay(lorutime)); - - if (local) - result = internalUTC(result); - - date = TimeClip(result); - - return date; - } - -// #string_id_map# - - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:15:38 EDT - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 6: X="getDay";id=Id_getDay; break L; - case 7: switch (s.charAt(3)) { - case 'D': c=s.charAt(0); - if (c=='g') { X="getDate";id=Id_getDate; } - else if (c=='s') { X="setDate";id=Id_setDate; } - break L; - case 'T': c=s.charAt(0); - if (c=='g') { X="getTime";id=Id_getTime; } - else if (c=='s') { X="setTime";id=Id_setTime; } - break L; - case 'Y': c=s.charAt(0); - if (c=='g') { X="getYear";id=Id_getYear; } - else if (c=='s') { X="setYear";id=Id_setYear; } - break L; - case 'u': X="valueOf";id=Id_valueOf; break L; - } break L; - case 8: switch (s.charAt(3)) { - case 'H': c=s.charAt(0); - if (c=='g') { X="getHours";id=Id_getHours; } - else if (c=='s') { X="setHours";id=Id_setHours; } - break L; - case 'M': c=s.charAt(0); - if (c=='g') { X="getMonth";id=Id_getMonth; } - else if (c=='s') { X="setMonth";id=Id_setMonth; } - break L; - case 'o': X="toSource";id=Id_toSource; break L; - case 't': X="toString";id=Id_toString; break L; - } break L; - case 9: X="getUTCDay";id=Id_getUTCDay; break L; - case 10: c=s.charAt(3); - if (c=='M') { - c=s.charAt(0); - if (c=='g') { X="getMinutes";id=Id_getMinutes; } - else if (c=='s') { X="setMinutes";id=Id_setMinutes; } - } - else if (c=='S') { - c=s.charAt(0); - if (c=='g') { X="getSeconds";id=Id_getSeconds; } - else if (c=='s') { X="setSeconds";id=Id_setSeconds; } - } - else if (c=='U') { - c=s.charAt(0); - if (c=='g') { X="getUTCDate";id=Id_getUTCDate; } - else if (c=='s') { X="setUTCDate";id=Id_setUTCDate; } - } - break L; - case 11: switch (s.charAt(3)) { - case 'F': c=s.charAt(0); - if (c=='g') { X="getFullYear";id=Id_getFullYear; } - else if (c=='s') { X="setFullYear";id=Id_setFullYear; } - break L; - case 'M': X="toGMTString";id=Id_toGMTString; break L; - case 'T': X="toUTCString";id=Id_toUTCString; break L; - case 'U': c=s.charAt(0); - if (c=='g') { - c=s.charAt(9); - if (c=='r') { X="getUTCHours";id=Id_getUTCHours; } - else if (c=='t') { X="getUTCMonth";id=Id_getUTCMonth; } - } - else if (c=='s') { - c=s.charAt(9); - if (c=='r') { X="setUTCHours";id=Id_setUTCHours; } - else if (c=='t') { X="setUTCMonth";id=Id_setUTCMonth; } - } - break L; - case 's': X="constructor";id=Id_constructor; break L; - } break L; - case 12: c=s.charAt(2); - if (c=='D') { X="toDateString";id=Id_toDateString; } - else if (c=='T') { X="toTimeString";id=Id_toTimeString; } - break L; - case 13: c=s.charAt(0); - if (c=='g') { - c=s.charAt(6); - if (c=='M') { X="getUTCMinutes";id=Id_getUTCMinutes; } - else if (c=='S') { X="getUTCSeconds";id=Id_getUTCSeconds; } - } - else if (c=='s') { - c=s.charAt(6); - if (c=='M') { X="setUTCMinutes";id=Id_setUTCMinutes; } - else if (c=='S') { X="setUTCSeconds";id=Id_setUTCSeconds; } - } - break L; - case 14: c=s.charAt(0); - if (c=='g') { X="getUTCFullYear";id=Id_getUTCFullYear; } - else if (c=='s') { X="setUTCFullYear";id=Id_setUTCFullYear; } - else if (c=='t') { X="toLocaleString";id=Id_toLocaleString; } - break L; - case 15: c=s.charAt(0); - if (c=='g') { X="getMilliseconds";id=Id_getMilliseconds; } - else if (c=='s') { X="setMilliseconds";id=Id_setMilliseconds; } - break L; - case 17: X="getTimezoneOffset";id=Id_getTimezoneOffset; break L; - case 18: c=s.charAt(0); - if (c=='g') { X="getUTCMilliseconds";id=Id_getUTCMilliseconds; } - else if (c=='s') { X="setUTCMilliseconds";id=Id_setUTCMilliseconds; } - else if (c=='t') { - c=s.charAt(8); - if (c=='D') { X="toLocaleDateString";id=Id_toLocaleDateString; } - else if (c=='T') { X="toLocaleTimeString";id=Id_toLocaleTimeString; } - } - break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - ConstructorId_now = -3, - ConstructorId_parse = -2, - ConstructorId_UTC = -1, - - Id_constructor = 1, - Id_toString = 2, - Id_toTimeString = 3, - Id_toDateString = 4, - Id_toLocaleString = 5, - Id_toLocaleTimeString = 6, - Id_toLocaleDateString = 7, - Id_toUTCString = 8, - Id_toSource = 9, - Id_valueOf = 10, - Id_getTime = 11, - Id_getYear = 12, - Id_getFullYear = 13, - Id_getUTCFullYear = 14, - Id_getMonth = 15, - Id_getUTCMonth = 16, - Id_getDate = 17, - Id_getUTCDate = 18, - Id_getDay = 19, - Id_getUTCDay = 20, - Id_getHours = 21, - Id_getUTCHours = 22, - Id_getMinutes = 23, - Id_getUTCMinutes = 24, - Id_getSeconds = 25, - Id_getUTCSeconds = 26, - Id_getMilliseconds = 27, - Id_getUTCMilliseconds = 28, - Id_getTimezoneOffset = 29, - Id_setTime = 30, - Id_setMilliseconds = 31, - Id_setUTCMilliseconds = 32, - Id_setSeconds = 33, - Id_setUTCSeconds = 34, - Id_setMinutes = 35, - Id_setUTCMinutes = 36, - Id_setHours = 37, - Id_setUTCHours = 38, - Id_setDate = 39, - Id_setUTCDate = 40, - Id_setMonth = 41, - Id_setUTCMonth = 42, - Id_setFullYear = 43, - Id_setUTCFullYear = 44, - Id_setYear = 45, - - MAX_PROTOTYPE_ID = 45; - - private static final int - Id_toGMTString = Id_toUTCString; // Alias, see Ecma B.2.6 -// #/string_id_map# - - /* cached values */ - private static java.util.TimeZone thisTimeZone; - private static double LocalTZA; - private static java.text.DateFormat timeZoneFormatter; - private static java.text.DateFormat localeDateTimeFormatter; - private static java.text.DateFormat localeDateFormatter; - private static java.text.DateFormat localeTimeFormatter; - - private double date; -} - - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeError.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeError.java deleted file mode 100644 index 4aff10c..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeError.java +++ /dev/null @@ -1,227 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - - -package org.mozilla.javascript; - -/** - * - * The class of error objects - * - * ECMA 15.11 - */ -final class NativeError extends IdScriptableObject -{ - static final long serialVersionUID = -5338413581437645187L; - - private static final Object ERROR_TAG = new Object(); - - static void init(Scriptable scope, boolean sealed) - { - NativeError obj = new NativeError(); - ScriptableObject.putProperty(obj, "name", "Error"); - ScriptableObject.putProperty(obj, "message", ""); - ScriptableObject.putProperty(obj, "fileName", ""); - ScriptableObject.putProperty(obj, "lineNumber", new Integer(0)); - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - static NativeError make(Context cx, Scriptable scope, - IdFunctionObject ctorObj, Object[] args) - { - Scriptable proto = (Scriptable)(ctorObj.get("prototype", ctorObj)); - - NativeError obj = new NativeError(); - obj.setPrototype(proto); - obj.setParentScope(scope); - - int arglen = args.length; - if (arglen >= 1) { - ScriptableObject.putProperty(obj, "message", - ScriptRuntime.toString(args[0])); - if (arglen >= 2) { - ScriptableObject.putProperty(obj, "fileName", args[1]); - if (arglen >= 3) { - int line = ScriptRuntime.toInt32(args[2]); - ScriptableObject.putProperty(obj, "lineNumber", - new Integer(line)); - } - } - } - if(arglen < 3 && cx.hasFeature(Context.FEATURE_LOCATION_INFORMATION_IN_ERROR)) { - // Fill in fileName and lineNumber automatically when not specified - // explicitly, see Bugzilla issue #342807 - int[] linep = new int[1]; - String fileName = Context.getSourcePositionFromStack(linep); - ScriptableObject.putProperty(obj, "lineNumber", - new Integer(linep[0])); - if(arglen < 2) { - ScriptableObject.putProperty(obj, "fileName", fileName); - } - } - return obj; - } - - public String getClassName() - { - return "Error"; - } - - public String toString() - { - return js_toString(this); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=1; s="constructor"; break; - case Id_toString: arity=0; s="toString"; break; - case Id_toSource: arity=0; s="toSource"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(ERROR_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(ERROR_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case Id_constructor: - return make(cx, scope, f, args); - - case Id_toString: - return js_toString(thisObj); - - case Id_toSource: - return js_toSource(cx, scope, thisObj); - } - throw new IllegalArgumentException(String.valueOf(id)); - } - - private static String js_toString(Scriptable thisObj) - { - return getString(thisObj, "name")+": "+getString(thisObj, "message"); - } - - private static String js_toSource(Context cx, Scriptable scope, - Scriptable thisObj) - { - // Emulation of SpiderMonkey behavior - Object name = ScriptableObject.getProperty(thisObj, "name"); - Object message = ScriptableObject.getProperty(thisObj, "message"); - Object fileName = ScriptableObject.getProperty(thisObj, "fileName"); - Object lineNumber = ScriptableObject.getProperty(thisObj, "lineNumber"); - - StringBuffer sb = new StringBuffer(); - sb.append("(new "); - if (name == NOT_FOUND) { - name = Undefined.instance; - } - sb.append(ScriptRuntime.toString(name)); - sb.append("("); - if (message != NOT_FOUND - || fileName != NOT_FOUND - || lineNumber != NOT_FOUND) - { - if (message == NOT_FOUND) { - message = ""; - } - sb.append(ScriptRuntime.uneval(cx, scope, message)); - if (fileName != NOT_FOUND || lineNumber != NOT_FOUND) { - sb.append(", "); - if (fileName == NOT_FOUND) { - fileName = ""; - } - sb.append(ScriptRuntime.uneval(cx, scope, fileName)); - if (lineNumber != NOT_FOUND) { - int line = ScriptRuntime.toInt32(lineNumber); - if (line != 0) { - sb.append(", "); - sb.append(ScriptRuntime.toString(line)); - } - } - } - } - sb.append("))"); - return sb.toString(); - } - - private static String getString(Scriptable obj, String id) - { - Object value = ScriptableObject.getProperty(obj, id); - if (value == NOT_FOUND) return ""; - return ScriptRuntime.toString(value); - } - - protected int findPrototypeId(String s) - { - int id; -// #string_id_map# -// #generated# Last update: 2007-05-09 08:15:45 EDT - L0: { id = 0; String X = null; int c; - int s_length = s.length(); - if (s_length==8) { - c=s.charAt(3); - if (c=='o') { X="toSource";id=Id_toSource; } - else if (c=='t') { X="toString";id=Id_toString; } - } - else if (s_length==11) { X="constructor";id=Id_constructor; } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_constructor = 1, - Id_toString = 2, - Id_toSource = 3, - - MAX_PROTOTYPE_ID = 3; - -// #/string_id_map# -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeFunction.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeFunction.java deleted file mode 100644 index ac70556..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeFunction.java +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Bob Jervis - * Roger Lawrence - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import org.mozilla.javascript.debug.DebuggableScript; - -/** - * This class implements the Function native object. - * See ECMA 15.3. - * @author Norris Boyd - */ -public abstract class NativeFunction extends BaseFunction -{ - - public final void initScriptFunction(Context cx, Scriptable scope) - { - ScriptRuntime.setFunctionProtoAndParent(this, scope); - } - - /** - * @param indent How much to indent the decompiled result - * - * @param flags Flags specifying format of decompilation output - */ - final String decompile(int indent, int flags) - { - String encodedSource = getEncodedSource(); - if (encodedSource == null) { - return super.decompile(indent, flags); - } else { - UintMap properties = new UintMap(1); - properties.put(Decompiler.INITIAL_INDENT_PROP, indent); - return Decompiler.decompile(encodedSource, flags, properties); - } - } - - public int getLength() - { - int paramCount = getParamCount(); - if (getLanguageVersion() != Context.VERSION_1_2) { - return paramCount; - } - Context cx = Context.getContext(); - NativeCall activation = ScriptRuntime.findFunctionActivation(cx, this); - if (activation == null) { - return paramCount; - } - return activation.originalArgs.length; - } - - public int getArity() - { - return getParamCount(); - } - - /** - * @deprecated Use {@link BaseFunction#getFunctionName()} instead. - * For backwards compatibility keep an old method name used by - * Batik and possibly others. - */ - public String jsGet_name() - { - return getFunctionName(); - } - - /** - * Get encoded source string. - */ - public String getEncodedSource() - { - return null; - } - - public DebuggableScript getDebuggableView() - { - return null; - } - - /** - * Resume execution of a suspended generator. - * @param cx The current context - * @param scope Scope for the parent generator function - * @param operation The resumption operation (next, send, etc.. ) - * @param state The generator state (has locals, stack, etc.) - * @param value The return value of yield (if required). - * @return The next yielded value (if any) - */ - public Object resumeGenerator(Context cx, Scriptable scope, - int operation, Object state, Object value) - { - throw new EvaluatorException("resumeGenerator() not implemented"); - } - - - protected abstract int getLanguageVersion(); - - /** - * Get number of declared parameters. It should be 0 for scripts. - */ - protected abstract int getParamCount(); - - /** - * Get number of declared parameters and variables defined through var - * statements. - */ - protected abstract int getParamAndVarCount(); - - /** - * Get parameter or variable name. - * If <tt>index < {@link #getParamCount()}</tt>, then return the name of the - * corresponding parameter. Otherwise return the name of variable. - */ - protected abstract String getParamOrVarName(int index); - - /** - * Get parameter or variable const-ness. - * If <tt>index < {@link #getParamCount()}</tt>, then return the const-ness - * of the corresponding parameter. Otherwise return whether the variable is - * const. - */ - protected boolean getParamOrVarConst(int index) - { - // By default return false to preserve compatibility with existing - // classes subclassing this class, which are mostly generated by jsc - // from earlier Rhino versions. See Bugzilla #396117. - return false; - } -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeGenerator.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeGenerator.java deleted file mode 100644 index 0a8da9f..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeGenerator.java +++ /dev/null @@ -1,281 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class implements generator objects. See - * http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7#Generators - * - * @author Norris Boyd - */ -public final class NativeGenerator extends IdScriptableObject { - private static final Object GENERATOR_TAG = new Object(); - - static NativeGenerator init(ScriptableObject scope, boolean sealed) { - // Generator - // Can't use "NativeGenerator().exportAsJSClass" since we don't want - // to define "Generator" as a constructor in the top-level scope. - - NativeGenerator prototype = new NativeGenerator(); - if (scope != null) { - prototype.setParentScope(scope); - prototype.setPrototype(getObjectPrototype(scope)); - } - prototype.activatePrototypeMap(MAX_PROTOTYPE_ID); - if (sealed) { - prototype.sealObject(); - } - - // Need to access Generator prototype when constructing - // Generator instances, but don't have a generator constructor - // to use to find the prototype. Use the "associateValue" - // approach instead. - if (scope != null) { - scope.associateValue(GENERATOR_TAG, prototype); - } - - return prototype; - } - - /** - * Only for constructing the prototype object. - */ - private NativeGenerator() { } - - public NativeGenerator(Scriptable scope, NativeFunction function, - Object savedState) - { - this.function = function; - this.savedState = savedState; - // Set parent and prototype properties. Since we don't have a - // "Generator" constructor in the top scope, we stash the - // prototype in the top scope's associated value. - Scriptable top = ScriptableObject.getTopLevelScope(scope); - this.setParentScope(top); - NativeGenerator prototype = (NativeGenerator) - ScriptableObject.getTopScopeValue(top, GENERATOR_TAG); - this.setPrototype(prototype); - } - - public static final int GENERATOR_SEND = 0, - GENERATOR_THROW = 1, - GENERATOR_CLOSE = 2; - - public String getClassName() { - return "Generator"; - } - - /** - * Close the generator if it is still open. - */ - public void finalize() throws Throwable { - if (savedState != null) { - // This is a little tricky since we are most likely running in - // a different thread. We need to get a Context to run this, and - // we must call "doTopCall" since this will likely be the outermost - // JavaScript frame on this thread. - Context cx = Context.getCurrentContext(); - ContextFactory factory = cx != null ? cx.getFactory() - : ContextFactory.getGlobal(); - Scriptable scope = ScriptableObject.getTopLevelScope(this); - factory.call(new CloseGeneratorAction(this)); - } - } - - private static class CloseGeneratorAction implements ContextAction { - private NativeGenerator generator; - - CloseGeneratorAction(NativeGenerator generator) { - this.generator = generator; - } - - public Object run(Context cx) { - Scriptable scope = ScriptableObject.getTopLevelScope(generator); - Callable closeGenerator = new Callable() { - public Object call(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) { - return ((NativeGenerator)thisObj).resume(cx, scope, - GENERATOR_CLOSE, new GeneratorClosedException()); - } - }; - return ScriptRuntime.doTopCall(closeGenerator, cx, scope, - generator, null); - } - } - - protected void initPrototypeId(int id) { - String s; - int arity; - switch (id) { - case Id_close: arity=1; s="close"; break; - case Id_next: arity=1; s="next"; break; - case Id_send: arity=0; s="send"; break; - case Id_throw: arity=0; s="throw"; break; - case Id___iterator__: arity=1; s="__iterator__"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(GENERATOR_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(GENERATOR_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - - if (!(thisObj instanceof NativeGenerator)) - throw incompatibleCallError(f); - - NativeGenerator generator = (NativeGenerator) thisObj; - - switch (id) { - - case Id_close: - // need to run any pending finally clauses - return generator.resume(cx, scope, GENERATOR_CLOSE, - new GeneratorClosedException()); - - case Id_next: - // arguments to next() are ignored - generator.firstTime = false; - return generator.resume(cx, scope, GENERATOR_SEND, - Undefined.instance); - - case Id_send: { - Object arg = args.length > 0 ? args[0] : Undefined.instance; - if (generator.firstTime && !arg.equals(Undefined.instance)) { - throw ScriptRuntime.typeError0("msg.send.newborn"); - } - return generator.resume(cx, scope, GENERATOR_SEND, arg); - } - - case Id_throw: - return generator.resume(cx, scope, GENERATOR_THROW, - args.length > 0 ? args[0] : Undefined.instance); - - case Id___iterator__: - return thisObj; - - default: - throw new IllegalArgumentException(String.valueOf(id)); - } - } - - private Object resume(Context cx, Scriptable scope, int operation, - Object value) - { - if (savedState == null) { - if (operation == GENERATOR_CLOSE) - return Undefined.instance; - Object thrown; - if (operation == GENERATOR_THROW) { - thrown = value; - } else { - thrown = NativeIterator.getStopIterationObject(scope); - } - throw new JavaScriptException(thrown, lineSource, lineNumber); - } - try { - synchronized (this) { - // generator execution is necessarily single-threaded and - // non-reentrant. - // See https://bugzilla.mozilla.org/show_bug.cgi?id=349263 - if (locked) - throw ScriptRuntime.typeError0("msg.already.exec.gen"); - locked = true; - } - return function.resumeGenerator(cx, scope, operation, savedState, - value); - } catch (GeneratorClosedException e) { - // On closing a generator in the compile path, the generator - // throws a special exception. This ensures execution of all pending - // finalizers and will not get caught by user code. - return Undefined.instance; - } catch (RhinoException e) { - lineNumber = e.lineNumber(); - lineSource = e.lineSource(); - savedState = null; - throw e; - } finally { - synchronized (this) { - locked = false; - } - if (operation == GENERATOR_CLOSE) - savedState = null; - } - } - -// #string_id_map# - - protected int findPrototypeId(String s) { - int id; -// #generated# Last update: 2007-06-14 13:13:03 EDT - L0: { id = 0; String X = null; int c; - int s_length = s.length(); - if (s_length==4) { - c=s.charAt(0); - if (c=='n') { X="next";id=Id_next; } - else if (c=='s') { X="send";id=Id_send; } - } - else if (s_length==5) { - c=s.charAt(0); - if (c=='c') { X="close";id=Id_close; } - else if (c=='t') { X="throw";id=Id_throw; } - } - else if (s_length==12) { X="__iterator__";id=Id___iterator__; } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_close = 1, - Id_next = 2, - Id_send = 3, - Id_throw = 4, - Id___iterator__ = 5, - MAX_PROTOTYPE_ID = 5; - -// #/string_id_map# - private NativeFunction function; - private Object savedState; - private String lineSource; - private int lineNumber; - private boolean firstTime = true; - private boolean locked; - - public static class GeneratorClosedException extends RuntimeException { - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeGlobal.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeGlobal.java deleted file mode 100644 index 58faad4..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeGlobal.java +++ /dev/null @@ -1,790 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Serializable; - -import org.mozilla.javascript.xml.XMLLib; - -/** - * This class implements the global native object (function and value - * properties only). - * - * See ECMA 15.1.[12]. - * - * @author Mike Shaver - */ - -public class NativeGlobal implements Serializable, IdFunctionCall -{ - static final long serialVersionUID = 6080442165748707530L; - - public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeGlobal obj = new NativeGlobal(); - - for (int id = 1; id <= LAST_SCOPE_FUNCTION_ID; ++id) { - String name; - int arity = 1; - switch (id) { - case Id_decodeURI: - name = "decodeURI"; - break; - case Id_decodeURIComponent: - name = "decodeURIComponent"; - break; - case Id_encodeURI: - name = "encodeURI"; - break; - case Id_encodeURIComponent: - name = "encodeURIComponent"; - break; - case Id_escape: - name = "escape"; - break; - case Id_eval: - name = "eval"; - break; - case Id_isFinite: - name = "isFinite"; - break; - case Id_isNaN: - name = "isNaN"; - break; - case Id_isXMLName: - name = "isXMLName"; - break; - case Id_parseFloat: - name = "parseFloat"; - break; - case Id_parseInt: - name = "parseInt"; - arity = 2; - break; - case Id_unescape: - name = "unescape"; - break; - case Id_uneval: - name = "uneval"; - break; - default: - throw Kit.codeBug(); - } - IdFunctionObject f = new IdFunctionObject(obj, FTAG, id, name, - arity, scope); - if (sealed) { - f.sealObject(); - } - f.exportAsScopeProperty(); - } - - ScriptableObject.defineProperty( - scope, "NaN", ScriptRuntime.NaNobj, - ScriptableObject.DONTENUM); - ScriptableObject.defineProperty( - scope, "Infinity", - ScriptRuntime.wrapNumber(Double.POSITIVE_INFINITY), - ScriptableObject.DONTENUM); - ScriptableObject.defineProperty( - scope, "undefined", Undefined.instance, - ScriptableObject.DONTENUM); - - String[] errorMethods = Kit.semicolonSplit("" - +"ConversionError;" - +"EvalError;" - +"RangeError;" - +"ReferenceError;" - +"SyntaxError;" - +"TypeError;" - +"URIError;" - +"InternalError;" - +"JavaException;" - ); - - /* - Each error constructor gets its own Error object as a prototype, - with the 'name' property set to the name of the error. - */ - for (int i = 0; i < errorMethods.length; i++) { - String name = errorMethods[i]; - Scriptable errorProto = ScriptRuntime. - newObject(cx, scope, "Error", - ScriptRuntime.emptyArgs); - errorProto.put("name", errorProto, name); - if (sealed) { - if (errorProto instanceof ScriptableObject) { - ((ScriptableObject)errorProto).sealObject(); - } - } - IdFunctionObject ctor = new IdFunctionObject(obj, FTAG, - Id_new_CommonError, - name, 1, scope); - ctor.markAsConstructor(errorProto); - if (sealed) { - ctor.sealObject(); - } - ctor.exportAsScopeProperty(); - } - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (f.hasTag(FTAG)) { - int methodId = f.methodId(); - switch (methodId) { - case Id_decodeURI: - case Id_decodeURIComponent: { - String str = ScriptRuntime.toString(args, 0); - return decode(str, methodId == Id_decodeURI); - } - - case Id_encodeURI: - case Id_encodeURIComponent: { - String str = ScriptRuntime.toString(args, 0); - return encode(str, methodId == Id_encodeURI); - } - - case Id_escape: - return js_escape(args); - - case Id_eval: - return js_eval(cx, scope, args); - - case Id_isFinite: { - boolean result; - if (args.length < 1) { - result = false; - } else { - double d = ScriptRuntime.toNumber(args[0]); - result = (d == d - && d != Double.POSITIVE_INFINITY - && d != Double.NEGATIVE_INFINITY); - } - return ScriptRuntime.wrapBoolean(result); - } - - case Id_isNaN: { - // The global method isNaN, as per ECMA-262 15.1.2.6. - boolean result; - if (args.length < 1) { - result = true; - } else { - double d = ScriptRuntime.toNumber(args[0]); - result = (d != d); - } - return ScriptRuntime.wrapBoolean(result); - } - - case Id_isXMLName: { - Object name = (args.length == 0) - ? Undefined.instance : args[0]; - XMLLib xmlLib = XMLLib.extractFromScope(scope); - return ScriptRuntime.wrapBoolean( - xmlLib.isXMLName(cx, name)); - } - - case Id_parseFloat: - return js_parseFloat(args); - - case Id_parseInt: - return js_parseInt(args); - - case Id_unescape: - return js_unescape(args); - - case Id_uneval: { - Object value = (args.length != 0) - ? args[0] : Undefined.instance; - return ScriptRuntime.uneval(cx, scope, value); - } - - case Id_new_CommonError: - // The implementation of all the ECMA error constructors - // (SyntaxError, TypeError, etc.) - return NativeError.make(cx, scope, f, args); - } - } - throw f.unknown(); - } - - /** - * The global method parseInt, as per ECMA-262 15.1.2.2. - */ - private Object js_parseInt(Object[] args) { - String s = ScriptRuntime.toString(args, 0); - int radix = ScriptRuntime.toInt32(args, 1); - - int len = s.length(); - if (len == 0) - return ScriptRuntime.NaNobj; - - boolean negative = false; - int start = 0; - char c; - do { - c = s.charAt(start); - if (!Character.isWhitespace(c)) - break; - start++; - } while (start < len); - - if (c == '+' || (negative = (c == '-'))) - start++; - - final int NO_RADIX = -1; - if (radix == 0) { - radix = NO_RADIX; - } else if (radix < 2 || radix > 36) { - return ScriptRuntime.NaNobj; - } else if (radix == 16 && len - start > 1 && s.charAt(start) == '0') { - c = s.charAt(start+1); - if (c == 'x' || c == 'X') - start += 2; - } - - if (radix == NO_RADIX) { - radix = 10; - if (len - start > 1 && s.charAt(start) == '0') { - c = s.charAt(start+1); - if (c == 'x' || c == 'X') { - radix = 16; - start += 2; - } else if ('0' <= c && c <= '9') { - radix = 8; - start++; - } - } - } - - double d = ScriptRuntime.stringToNumber(s, start, radix); - return ScriptRuntime.wrapNumber(negative ? -d : d); - } - - /** - * The global method parseFloat, as per ECMA-262 15.1.2.3. - * - * @param args the arguments to parseFloat, ignoring args[>=1] - */ - private Object js_parseFloat(Object[] args) - { - if (args.length < 1) - return ScriptRuntime.NaNobj; - - String s = ScriptRuntime.toString(args[0]); - int len = s.length(); - int start = 0; - // Scan forward to skip whitespace - char c; - for (;;) { - if (start == len) { - return ScriptRuntime.NaNobj; - } - c = s.charAt(start); - if (!TokenStream.isJSSpace(c)) { - break; - } - ++start; - } - - int i = start; - if (c == '+' || c == '-') { - ++i; - if (i == len) { - return ScriptRuntime.NaNobj; - } - c = s.charAt(i); - } - - if (c == 'I') { - // check for "Infinity" - if (i+8 <= len && s.regionMatches(i, "Infinity", 0, 8)) { - double d; - if (s.charAt(start) == '-') { - d = Double.NEGATIVE_INFINITY; - } else { - d = Double.POSITIVE_INFINITY; - } - return ScriptRuntime.wrapNumber(d); - } - return ScriptRuntime.NaNobj; - } - - // Find the end of the legal bit - int decimal = -1; - int exponent = -1; - for (; i < len; i++) { - switch (s.charAt(i)) { - case '.': - if (decimal != -1) // Only allow a single decimal point. - break; - decimal = i; - continue; - - case 'e': - case 'E': - if (exponent != -1) - break; - exponent = i; - continue; - - case '+': - case '-': - // Only allow '+' or '-' after 'e' or 'E' - if (exponent != i-1) - break; - continue; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - continue; - - default: - break; - } - break; - } - s = s.substring(start, i); - try { - return Double.valueOf(s); - } - catch (NumberFormatException ex) { - return ScriptRuntime.NaNobj; - } - } - - /** - * The global method escape, as per ECMA-262 15.1.2.4. - - * Includes code for the 'mask' argument supported by the C escape - * method, which used to be part of the browser imbedding. Blame - * for the strange constant names should be directed there. - */ - - private Object js_escape(Object[] args) { - final int - URL_XALPHAS = 1, - URL_XPALPHAS = 2, - URL_PATH = 4; - - String s = ScriptRuntime.toString(args, 0); - - int mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH; - if (args.length > 1) { // the 'mask' argument. Non-ECMA. - double d = ScriptRuntime.toNumber(args[1]); - if (d != d || ((mask = (int) d) != d) || - 0 != (mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH))) - { - throw Context.reportRuntimeError0("msg.bad.esc.mask"); - } - } - - StringBuffer sb = null; - for (int k = 0, L = s.length(); k != L; ++k) { - int c = s.charAt(k); - if (mask != 0 - && ((c >= '0' && c <= '9') - || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') - || c == '@' || c == '*' || c == '_' || c == '-' || c == '.' - || (0 != (mask & URL_PATH) && (c == '/' || c == '+')))) - { - if (sb != null) { - sb.append((char)c); - } - } else { - if (sb == null) { - sb = new StringBuffer(L + 3); - sb.append(s); - sb.setLength(k); - } - - int hexSize; - if (c < 256) { - if (c == ' ' && mask == URL_XPALPHAS) { - sb.append('+'); - continue; - } - sb.append('%'); - hexSize = 2; - } else { - sb.append('%'); - sb.append('u'); - hexSize = 4; - } - - // append hexadecimal form of c left-padded with 0 - for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4) { - int digit = 0xf & (c >> shift); - int hc = (digit < 10) ? '0' + digit : 'A' - 10 + digit; - sb.append((char)hc); - } - } - } - - return (sb == null) ? s : sb.toString(); - } - - /** - * The global unescape method, as per ECMA-262 15.1.2.5. - */ - - private Object js_unescape(Object[] args) - { - String s = ScriptRuntime.toString(args, 0); - int firstEscapePos = s.indexOf('%'); - if (firstEscapePos >= 0) { - int L = s.length(); - char[] buf = s.toCharArray(); - int destination = firstEscapePos; - for (int k = firstEscapePos; k != L;) { - char c = buf[k]; - ++k; - if (c == '%' && k != L) { - int end, start; - if (buf[k] == 'u') { - start = k + 1; - end = k + 5; - } else { - start = k; - end = k + 2; - } - if (end <= L) { - int x = 0; - for (int i = start; i != end; ++i) { - x = Kit.xDigitToInt(buf[i], x); - } - if (x >= 0) { - c = (char)x; - k = end; - } - } - } - buf[destination] = c; - ++destination; - } - s = new String(buf, 0, destination); - } - return s; - } - - private Object js_eval(Context cx, Scriptable scope, Object[] args) - { - String m = ScriptRuntime.getMessage1("msg.cant.call.indirect", "eval"); - throw NativeGlobal.constructError(cx, "EvalError", m, scope); - } - - static boolean isEvalFunction(Object functionObj) - { - if (functionObj instanceof IdFunctionObject) { - IdFunctionObject function = (IdFunctionObject)functionObj; - if (function.hasTag(FTAG) && function.methodId() == Id_eval) { - return true; - } - } - return false; - } - - /** - * @deprecated Use {@link ScriptRuntime#constructError(String,String)} - * instead. - */ - public static EcmaError constructError(Context cx, - String error, - String message, - Scriptable scope) - { - return ScriptRuntime.constructError(error, message); - } - - /** - * @deprecated Use - * {@link ScriptRuntime#constructError(String,String,String,int,String,int)} - * instead. - */ - public static EcmaError constructError(Context cx, - String error, - String message, - Scriptable scope, - String sourceName, - int lineNumber, - int columnNumber, - String lineSource) - { - return ScriptRuntime.constructError(error, message, - sourceName, lineNumber, - lineSource, columnNumber); - } - - /* - * ECMA 3, 15.1.3 URI Handling Function Properties - * - * The following are implementations of the algorithms - * given in the ECMA specification for the hidden functions - * 'Encode' and 'Decode'. - */ - private static String encode(String str, boolean fullUri) { - byte[] utf8buf = null; - StringBuffer sb = null; - - for (int k = 0, length = str.length(); k != length; ++k) { - char C = str.charAt(k); - if (encodeUnescaped(C, fullUri)) { - if (sb != null) { - sb.append(C); - } - } else { - if (sb == null) { - sb = new StringBuffer(length + 3); - sb.append(str); - sb.setLength(k); - utf8buf = new byte[6]; - } - if (0xDC00 <= C && C <= 0xDFFF) { - throw Context.reportRuntimeError0("msg.bad.uri"); - } - int V; - if (C < 0xD800 || 0xDBFF < C) { - V = C; - } else { - k++; - if (k == length) { - throw Context.reportRuntimeError0("msg.bad.uri"); - } - char C2 = str.charAt(k); - if (!(0xDC00 <= C2 && C2 <= 0xDFFF)) { - throw Context.reportRuntimeError0("msg.bad.uri"); - } - V = ((C - 0xD800) << 10) + (C2 - 0xDC00) + 0x10000; - } - int L = oneUcs4ToUtf8Char(utf8buf, V); - for (int j = 0; j < L; j++) { - int d = 0xff & utf8buf[j]; - sb.append('%'); - sb.append(toHexChar(d >>> 4)); - sb.append(toHexChar(d & 0xf)); - } - } - } - return (sb == null) ? str : sb.toString(); - } - - private static char toHexChar(int i) { - if (i >> 4 != 0) Kit.codeBug(); - return (char)((i < 10) ? i + '0' : i - 10 + 'a'); - } - - private static int unHex(char c) { - if ('A' <= c && c <= 'F') { - return c - 'A' + 10; - } else if ('a' <= c && c <= 'f') { - return c - 'a' + 10; - } else if ('0' <= c && c <= '9') { - return c - '0'; - } else { - return -1; - } - } - - private static int unHex(char c1, char c2) { - int i1 = unHex(c1); - int i2 = unHex(c2); - if (i1 >= 0 && i2 >= 0) { - return (i1 << 4) | i2; - } - return -1; - } - - private static String decode(String str, boolean fullUri) { - char[] buf = null; - int bufTop = 0; - - for (int k = 0, length = str.length(); k != length;) { - char C = str.charAt(k); - if (C != '%') { - if (buf != null) { - buf[bufTop++] = C; - } - ++k; - } else { - if (buf == null) { - // decode always compress so result can not be bigger then - // str.length() - buf = new char[length]; - str.getChars(0, k, buf, 0); - bufTop = k; - } - int start = k; - if (k + 3 > length) - throw Context.reportRuntimeError0("msg.bad.uri"); - int B = unHex(str.charAt(k + 1), str.charAt(k + 2)); - if (B < 0) throw Context.reportRuntimeError0("msg.bad.uri"); - k += 3; - if ((B & 0x80) == 0) { - C = (char)B; - } else { - // Decode UTF-8 sequence into ucs4Char and encode it into - // UTF-16 - int utf8Tail, ucs4Char, minUcs4Char; - if ((B & 0xC0) == 0x80) { - // First UTF-8 should be ouside 0x80..0xBF - throw Context.reportRuntimeError0("msg.bad.uri"); - } else if ((B & 0x20) == 0) { - utf8Tail = 1; ucs4Char = B & 0x1F; - minUcs4Char = 0x80; - } else if ((B & 0x10) == 0) { - utf8Tail = 2; ucs4Char = B & 0x0F; - minUcs4Char = 0x800; - } else if ((B & 0x08) == 0) { - utf8Tail = 3; ucs4Char = B & 0x07; - minUcs4Char = 0x10000; - } else if ((B & 0x04) == 0) { - utf8Tail = 4; ucs4Char = B & 0x03; - minUcs4Char = 0x200000; - } else if ((B & 0x02) == 0) { - utf8Tail = 5; ucs4Char = B & 0x01; - minUcs4Char = 0x4000000; - } else { - // First UTF-8 can not be 0xFF or 0xFE - throw Context.reportRuntimeError0("msg.bad.uri"); - } - if (k + 3 * utf8Tail > length) - throw Context.reportRuntimeError0("msg.bad.uri"); - for (int j = 0; j != utf8Tail; j++) { - if (str.charAt(k) != '%') - throw Context.reportRuntimeError0("msg.bad.uri"); - B = unHex(str.charAt(k + 1), str.charAt(k + 2)); - if (B < 0 || (B & 0xC0) != 0x80) - throw Context.reportRuntimeError0("msg.bad.uri"); - ucs4Char = (ucs4Char << 6) | (B & 0x3F); - k += 3; - } - // Check for overlongs and other should-not-present codes - if (ucs4Char < minUcs4Char - || ucs4Char == 0xFFFE || ucs4Char == 0xFFFF) - { - ucs4Char = 0xFFFD; - } - if (ucs4Char >= 0x10000) { - ucs4Char -= 0x10000; - if (ucs4Char > 0xFFFFF) - throw Context.reportRuntimeError0("msg.bad.uri"); - char H = (char)((ucs4Char >>> 10) + 0xD800); - C = (char)((ucs4Char & 0x3FF) + 0xDC00); - buf[bufTop++] = H; - } else { - C = (char)ucs4Char; - } - } - if (fullUri && URI_DECODE_RESERVED.indexOf(C) >= 0) { - for (int x = start; x != k; x++) { - buf[bufTop++] = str.charAt(x); - } - } else { - buf[bufTop++] = C; - } - } - } - return (buf == null) ? str : new String(buf, 0, bufTop); - } - - private static boolean encodeUnescaped(char c, boolean fullUri) { - if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') - || ('0' <= c && c <= '9')) - { - return true; - } - if ("-_.!~*'()".indexOf(c) >= 0) - return true; - if (fullUri) { - return URI_DECODE_RESERVED.indexOf(c) >= 0; - } - return false; - } - - private static final String URI_DECODE_RESERVED = ";/?:@&=+$,#"; - - /* Convert one UCS-4 char and write it into a UTF-8 buffer, which must be - * at least 6 bytes long. Return the number of UTF-8 bytes of data written. - */ - private static int oneUcs4ToUtf8Char(byte[] utf8Buffer, int ucs4Char) { - int utf8Length = 1; - - //JS_ASSERT(ucs4Char <= 0x7FFFFFFF); - if ((ucs4Char & ~0x7F) == 0) - utf8Buffer[0] = (byte)ucs4Char; - else { - int i; - int a = ucs4Char >>> 11; - utf8Length = 2; - while (a != 0) { - a >>>= 5; - utf8Length++; - } - i = utf8Length; - while (--i > 0) { - utf8Buffer[i] = (byte)((ucs4Char & 0x3F) | 0x80); - ucs4Char >>>= 6; - } - utf8Buffer[0] = (byte)(0x100 - (1 << (8-utf8Length)) + ucs4Char); - } - return utf8Length; - } - - private static final Object FTAG = new Object(); - - private static final int - Id_decodeURI = 1, - Id_decodeURIComponent = 2, - Id_encodeURI = 3, - Id_encodeURIComponent = 4, - Id_escape = 5, - Id_eval = 6, - Id_isFinite = 7, - Id_isNaN = 8, - Id_isXMLName = 9, - Id_parseFloat = 10, - Id_parseInt = 11, - Id_unescape = 12, - Id_uneval = 13, - - LAST_SCOPE_FUNCTION_ID = 13, - - Id_new_CommonError = 14; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeIterator.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeIterator.java deleted file mode 100644 index c61f417..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeIterator.java +++ /dev/null @@ -1,260 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.util.Iterator; - -/** - * This class implements iterator objects. See - * http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7#Iterators - * - * @author Norris Boyd - */ -public final class NativeIterator extends IdScriptableObject { - private static final Object ITERATOR_TAG = new Object(); - - static void init(ScriptableObject scope, boolean sealed) { - // Iterator - NativeIterator iterator = new NativeIterator(); - iterator.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - - // Generator - NativeGenerator.init(scope, sealed); - - // StopIteration - NativeObject obj = new StopIteration(); - obj.setPrototype(getObjectPrototype(scope)); - obj.setParentScope(scope); - if (sealed) { obj.sealObject(); } - ScriptableObject.defineProperty(scope, STOP_ITERATION, obj, - ScriptableObject.DONTENUM); - // Use "associateValue" so that generators can continue to - // throw StopIteration even if the property of the global - // scope is replaced or deleted. - scope.associateValue(ITERATOR_TAG, obj); - } - - /** - * Only for constructing the prototype object. - */ - private NativeIterator() { - } - - private NativeIterator(Object objectIterator) { - this.objectIterator = objectIterator; - } - - /** - * Get the value of the "StopIteration" object. Note that this value - * is stored in the top-level scope using "associateValue" so the - * value can still be found even if a script overwrites or deletes - * the global "StopIteration" property. - * @param scope a scope whose parent chain reaches a top-level scope - * @return the StopIteration object - */ - public static Object getStopIterationObject(Scriptable scope) { - Scriptable top = ScriptableObject.getTopLevelScope(scope); - return ScriptableObject.getTopScopeValue(top, ITERATOR_TAG); - } - - private static final String STOP_ITERATION = "StopIteration"; - public static final String ITERATOR_PROPERTY_NAME = "__iterator__"; - - static class StopIteration extends NativeObject { - public String getClassName() { - return STOP_ITERATION; - } - - /* StopIteration has custom instanceof behavior since it - * doesn't have a constructor. - */ - public boolean hasInstance(Scriptable instance) { - return instance instanceof StopIteration; - } - } - - public String getClassName() { - return "Iterator"; - } - - protected void initPrototypeId(int id) { - String s; - int arity; - switch (id) { - case Id_constructor: arity=2; s="constructor"; break; - case Id_next: arity=0; s="next"; break; - case Id___iterator__: arity=1; s=ITERATOR_PROPERTY_NAME; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(ITERATOR_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(ITERATOR_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - - if (id == Id_constructor) { - return jsConstructor(cx, scope, thisObj, args); - } - - if (!(thisObj instanceof NativeIterator)) - throw incompatibleCallError(f); - - NativeIterator iterator = (NativeIterator) thisObj; - - switch (id) { - - case Id_next: - return iterator.next(cx, scope); - - case Id___iterator__: - /// XXX: what about argument? SpiderMonkey apparently ignores it - return thisObj; - - default: - throw new IllegalArgumentException(String.valueOf(id)); - } - } - - /* the javascript constructor */ - private static Object jsConstructor(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (args.length == 0 || args[0] == null || - args[0] == Undefined.instance) - { - throw ScriptRuntime.typeError1("msg.no.properties", - ScriptRuntime.toString(args[0])); - } - Scriptable obj = ScriptRuntime.toObject(scope, args[0]); - boolean keyOnly = args.length > 1 && ScriptRuntime.toBoolean(args[1]); - if (thisObj != null) { - // Called as a function. Convert to iterator if possible. - - // For objects that implement java.lang.Iterable or - // java.util.Iterator, have JavaScript Iterator call the underlying - // iteration methods - Iterator iterator = - VMBridge.instance.getJavaIterator(cx, scope, obj); - if (iterator != null) { - scope = ScriptableObject.getTopLevelScope(scope); - return cx.getWrapFactory().wrap(cx, scope, - new WrappedJavaIterator(iterator, scope), - WrappedJavaIterator.class); - } - - // Otherwise, just call the runtime routine - Scriptable jsIterator = ScriptRuntime.toIterator(cx, scope, obj, - keyOnly); - if (jsIterator != null) { - return jsIterator; - } - } - - // Otherwise, just set up to iterate over the properties of the object. - // Do not call __iterator__ method. - Object objectIterator = ScriptRuntime.enumInit(obj, cx, - keyOnly ? ScriptRuntime.ENUMERATE_KEYS_NO_ITERATOR - : ScriptRuntime.ENUMERATE_ARRAY_NO_ITERATOR); - ScriptRuntime.setEnumNumbers(objectIterator, true); - NativeIterator result = new NativeIterator(objectIterator); - result.setPrototype(NativeIterator.getClassPrototype(scope, - result.getClassName())); - result.setParentScope(scope); - return result; - } - - private Object next(Context cx, Scriptable scope) { - Boolean b = ScriptRuntime.enumNext(this.objectIterator); - if (!b.booleanValue()) { - // Out of values. Throw StopIteration. - throw new JavaScriptException( - NativeIterator.getStopIterationObject(scope), null, 0); - } - return ScriptRuntime.enumId(this.objectIterator, cx); - } - - static public class WrappedJavaIterator - { - WrappedJavaIterator(Iterator iterator, Scriptable scope) { - this.iterator = iterator; - this.scope = scope; - } - - public Object next() { - if (!iterator.hasNext()) { - // Out of values. Throw StopIteration. - throw new JavaScriptException( - NativeIterator.getStopIterationObject(scope), null, 0); - } - return iterator.next(); - } - - public Object __iterator__(boolean b) { - return this; - } - - private Iterator iterator; - private Scriptable scope; - } - -// #string_id_map# - - protected int findPrototypeId(String s) { - int id; -// #generated# Last update: 2007-06-11 09:43:19 EDT - L0: { id = 0; String X = null; - int s_length = s.length(); - if (s_length==4) { X="next";id=Id_next; } - else if (s_length==11) { X="constructor";id=Id_constructor; } - else if (s_length==12) { X="__iterator__";id=Id___iterator__; } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_constructor = 1, - Id_next = 2, - Id___iterator__ = 3, - MAX_PROTOTYPE_ID = 3; - -// #/string_id_map# - - private Object objectIterator; -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaArray.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaArray.java deleted file mode 100644 index 2f711a0..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaArray.java +++ /dev/null @@ -1,168 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Frank Mitchell - * Mike Shaver - * Kemal Bayram - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.lang.reflect.Array; - -/** - * This class reflects Java arrays into the JavaScript environment. - * - * @author Mike Shaver - * @see NativeJavaClass - * @see NativeJavaObject - * @see NativeJavaPackage - */ - -public class NativeJavaArray extends NativeJavaObject -{ - static final long serialVersionUID = -924022554283675333L; - - public String getClassName() { - return "JavaArray"; - } - - public static NativeJavaArray wrap(Scriptable scope, Object array) { - return new NativeJavaArray(scope, array); - } - - public Object unwrap() { - return array; - } - - public NativeJavaArray(Scriptable scope, Object array) { - super(scope, null, ScriptRuntime.ObjectClass); - Class cl = array.getClass(); - if (!cl.isArray()) { - throw new RuntimeException("Array expected"); - } - this.array = array; - this.length = Array.getLength(array); - this.cls = cl.getComponentType(); - } - - public boolean has(String id, Scriptable start) { - return id.equals("length") || super.has(id, start); - } - - public boolean has(int index, Scriptable start) { - return 0 <= index && index < length; - } - - public Object get(String id, Scriptable start) { - if (id.equals("length")) - return new Integer(length); - Object result = super.get(id, start); - if (result == NOT_FOUND && - !ScriptableObject.hasProperty(getPrototype(), id)) - { - throw Context.reportRuntimeError2( - "msg.java.member.not.found", array.getClass().getName(), id); - } - return result; - } - - public Object get(int index, Scriptable start) { - if (0 <= index && index < length) { - Context cx = Context.getContext(); - Object obj = Array.get(array, index); - return cx.getWrapFactory().wrap(cx, this, obj, cls); - } - return Undefined.instance; - } - - public void put(String id, Scriptable start, Object value) { - // Ignore assignments to "length"--it's readonly. - if (!id.equals("length")) - throw Context.reportRuntimeError1( - "msg.java.array.member.not.found", id); - } - - public void put(int index, Scriptable start, Object value) { - if (0 <= index && index < length) { - Array.set(array, index, Context.jsToJava(value, cls)); - } - else { - throw Context.reportRuntimeError2( - "msg.java.array.index.out.of.bounds", String.valueOf(index), - String.valueOf(length - 1)); - } - } - - public Object getDefaultValue(Class hint) { - if (hint == null || hint == ScriptRuntime.StringClass) - return array.toString(); - if (hint == ScriptRuntime.BooleanClass) - return Boolean.TRUE; - if (hint == ScriptRuntime.NumberClass) - return ScriptRuntime.NaNobj; - return this; - } - - public Object[] getIds() { - Object[] result = new Object[length]; - int i = length; - while (--i >= 0) - result[i] = new Integer(i); - return result; - } - - public boolean hasInstance(Scriptable value) { - if (!(value instanceof Wrapper)) - return false; - Object instance = ((Wrapper)value).unwrap(); - return cls.isInstance(instance); - } - - public Scriptable getPrototype() { - if (prototype == null) { - prototype = - ScriptableObject.getClassPrototype(this.getParentScope(), - "Array"); - } - return prototype; - } - - Object array; - int length; - Class cls; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaClass.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaClass.java deleted file mode 100644 index ab8af5c..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaClass.java +++ /dev/null @@ -1,320 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Frank Mitchell - * Mike Shaver - * Kurt Westerfeld - * Kemal Bayram - * Ulrike Mueller <umueller@demandware.com> - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.lang.reflect.*; -import java.util.Hashtable; - -/** - * This class reflects Java classes into the JavaScript environment, mainly - * for constructors and static members. We lazily reflect properties, - * and currently do not guarantee that a single j.l.Class is only - * reflected once into the JS environment, although we should. - * The only known case where multiple reflections - * are possible occurs when a j.l.Class is wrapped as part of a - * method return or property access, rather than by walking the - * Packages/java tree. - * - * @author Mike Shaver - * @see NativeJavaArray - * @see NativeJavaObject - * @see NativeJavaPackage - */ - -public class NativeJavaClass extends NativeJavaObject implements Function -{ - static final long serialVersionUID = -6460763940409461664L; - - // Special property for getting the underlying Java class object. - static final String javaClassPropertyName = "__javaObject__"; - - public NativeJavaClass() { - } - - public NativeJavaClass(Scriptable scope, Class cl) { - this.parent = scope; - this.javaObject = cl; - initMembers(); - } - - protected void initMembers() { - Class cl = (Class)javaObject; - members = JavaMembers.lookupClass(parent, cl, cl, false); - staticFieldAndMethods - = members.getFieldAndMethodsObjects(this, cl, true); - } - - public String getClassName() { - return "JavaClass"; - } - - public boolean has(String name, Scriptable start) { - return members.has(name, true) || javaClassPropertyName.equals(name); - } - - public Object get(String name, Scriptable start) { - // When used as a constructor, ScriptRuntime.newObject() asks - // for our prototype to create an object of the correct type. - // We don't really care what the object is, since we're returning - // one constructed out of whole cloth, so we return null. - if (name.equals("prototype")) - return null; - - if (staticFieldAndMethods != null) { - Object result = staticFieldAndMethods.get(name); - if (result != null) - return result; - } - - if (members.has(name, true)) { - return members.get(this, name, javaObject, true); - } - - if (javaClassPropertyName.equals(name)) { - Context cx = Context.getContext(); - Scriptable scope = ScriptableObject.getTopLevelScope(start); - return cx.getWrapFactory().wrap(cx, scope, javaObject, - ScriptRuntime.ClassClass); - } - - // experimental: look for nested classes by appending $name to - // current class' name. - Class nestedClass = findNestedClass(getClassObject(), name); - if (nestedClass != null) { - NativeJavaClass nestedValue = new NativeJavaClass - (ScriptableObject.getTopLevelScope(this), nestedClass); - nestedValue.setParentScope(this); - return nestedValue; - } - - throw members.reportMemberNotFound(name); - } - - public void put(String name, Scriptable start, Object value) { - members.put(this, name, javaObject, value, true); - } - - public Object[] getIds() { - return members.getIds(true); - } - - public Class getClassObject() { - return (Class) super.unwrap(); - } - - public Object getDefaultValue(Class hint) { - if (hint == null || hint == ScriptRuntime.StringClass) - return this.toString(); - if (hint == ScriptRuntime.BooleanClass) - return Boolean.TRUE; - if (hint == ScriptRuntime.NumberClass) - return ScriptRuntime.NaNobj; - return this; - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - // If it looks like a "cast" of an object to this class type, - // walk the prototype chain to see if there's a wrapper of a - // object that's an instanceof this class. - if (args.length == 1 && args[0] instanceof Scriptable) { - Class c = getClassObject(); - Scriptable p = (Scriptable) args[0]; - do { - if (p instanceof Wrapper) { - Object o = ((Wrapper) p).unwrap(); - if (c.isInstance(o)) - return p; - } - p = p.getPrototype(); - } while (p != null); - } - return construct(cx, scope, args); - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) - { - Class classObject = getClassObject(); - int modifiers = classObject.getModifiers(); - if (! (Modifier.isInterface(modifiers) || - Modifier.isAbstract(modifiers))) - { - MemberBox[] ctors = members.ctors; - int index = NativeJavaMethod.findFunction(cx, ctors, args); - if (index < 0) { - String sig = NativeJavaMethod.scriptSignature(args); - throw Context.reportRuntimeError2( - "msg.no.java.ctor", classObject.getName(), sig); - } - - // Found the constructor, so try invoking it. - return constructSpecific(cx, scope, args, ctors[index]); - } else { - Scriptable topLevel = ScriptableObject.getTopLevelScope(this); - String msg = ""; - try { - // trying to construct an interface; use JavaAdapter to - // construct a new class on the fly that implements this - // interface. - Object v = topLevel.get("JavaAdapter", topLevel); - if (v != NOT_FOUND) { - Function f = (Function) v; - Object[] adapterArgs = { this, args[0] }; - return f.construct(cx, topLevel,adapterArgs); - } - } catch (Exception ex) { - // fall through to error - String m = ex.getMessage(); - if (m != null) - msg = m; - } - throw Context.reportRuntimeError2( - "msg.cant.instantiate", msg, classObject.getName()); - } - } - - static Scriptable constructSpecific(Context cx, Scriptable scope, - Object[] args, MemberBox ctor) - { - Scriptable topLevel = ScriptableObject.getTopLevelScope(scope); - Class[] argTypes = ctor.argTypes; - - if (ctor.vararg) { - // marshall the explicit parameter - Object[] newArgs = new Object[argTypes.length]; - for (int i = 0; i < argTypes.length-1; i++) { - newArgs[i] = Context.jsToJava(args[i], argTypes[i]); - } - - Object varArgs; - - // Handle special situation where a single variable parameter - // is given and it is a Java or ECMA array. - if (args.length == argTypes.length && - (args[args.length-1] == null || - args[args.length-1] instanceof NativeArray || - args[args.length-1] instanceof NativeJavaArray)) - { - // convert the ECMA array into a native array - varArgs = Context.jsToJava(args[args.length-1], - argTypes[argTypes.length - 1]); - } else { - // marshall the variable parameter - Class componentType = argTypes[argTypes.length - 1]. - getComponentType(); - varArgs = Array.newInstance(componentType, - args.length - argTypes.length + 1); - for (int i=0; i < Array.getLength(varArgs); i++) { - Object value = Context.jsToJava(args[argTypes.length-1 + i], - componentType); - Array.set(varArgs, i, value); - } - } - - // add varargs - newArgs[argTypes.length-1] = varArgs; - // replace the original args with the new one - args = newArgs; - } else { - Object[] origArgs = args; - for (int i = 0; i < args.length; i++) { - Object arg = args[i]; - Object x = Context.jsToJava(arg, argTypes[i]); - if (x != arg) { - if (args == origArgs) { - args = origArgs.clone(); - } - args[i] = x; - } - } - } - - Object instance = ctor.newInstance(args); - // we need to force this to be wrapped, because construct _has_ - // to return a scriptable - return cx.getWrapFactory().wrapNewObject(cx, topLevel, instance); - } - - public String toString() { - return "[JavaClass " + getClassObject().getName() + "]"; - } - - /** - * Determines if prototype is a wrapped Java object and performs - * a Java "instanceof". - * Exception: if value is an instance of NativeJavaClass, it isn't - * considered an instance of the Java class; this forestalls any - * name conflicts between java.lang.Class's methods and the - * static methods exposed by a JavaNativeClass. - */ - public boolean hasInstance(Scriptable value) { - - if (value instanceof Wrapper && - !(value instanceof NativeJavaClass)) { - Object instance = ((Wrapper)value).unwrap(); - - return getClassObject().isInstance(instance); - } - - // value wasn't something we understand - return false; - } - - private static Class findNestedClass(Class parentClass, String name) { - String nestedClassName = parentClass.getName() + '$' + name; - ClassLoader loader = parentClass.getClassLoader(); - if (loader == null) { - // ALERT: if loader is null, nested class should be loaded - // via system class loader which can be different from the - // loader that brought Rhino classes that Class.forName() would - // use, but ClassLoader.getSystemClassLoader() is Java 2 only - return Kit.classOrNull(nestedClassName); - } else { - return Kit.classOrNull(loader, nestedClassName); - } - } - - private Hashtable staticFieldAndMethods; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaConstructor.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaConstructor.java deleted file mode 100644 index 530bf81..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaConstructor.java +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Frank Mitchell - * Mike Shaver - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class reflects a single Java constructor into the JavaScript - * environment. It satisfies a request for an overloaded constructor, - * as introduced in LiveConnect 3. - * All NativeJavaConstructors behave as JSRef `bound' methods, in that they - * always construct the same NativeJavaClass regardless of any reparenting - * that may occur. - * - * @author Frank Mitchell - * @see NativeJavaMethod - * @see NativeJavaPackage - * @see NativeJavaClass - */ - -public class NativeJavaConstructor extends BaseFunction -{ - static final long serialVersionUID = -8149253217482668463L; - - MemberBox ctor; - - public NativeJavaConstructor(MemberBox ctor) - { - this.ctor = ctor; - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - return NativeJavaClass.constructSpecific(cx, scope, args, ctor); - } - - public String getFunctionName() - { - String sig = JavaMembers.liveConnectSignature(ctor.argTypes); - return "<init>".concat(sig); - } - - public String toString() - { - return "[JavaConstructor " + ctor.getName() + "]"; - } -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaMethod.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaMethod.java deleted file mode 100644 index eb66f40..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaMethod.java +++ /dev/null @@ -1,576 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Frank Mitchell - * Mike Shaver - * Ulrike Mueller <umueller@demandware.com> - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.lang.reflect.*; - -/** - * This class reflects Java methods into the JavaScript environment and - * handles overloading of methods. - * - * @author Mike Shaver - * @see NativeJavaArray - * @see NativeJavaPackage - * @see NativeJavaClass - */ - -public class NativeJavaMethod extends BaseFunction -{ - static final long serialVersionUID = -3440381785576412928L; - - NativeJavaMethod(MemberBox[] methods) - { - this.functionName = methods[0].getName(); - this.methods = methods; - } - - NativeJavaMethod(MemberBox method, String name) - { - this.functionName = name; - this.methods = new MemberBox[] { method }; - } - - public NativeJavaMethod(Method method, String name) - { - this(new MemberBox(method), name); - } - - public String getFunctionName() - { - return functionName; - } - - static String scriptSignature(Object[] values) - { - StringBuffer sig = new StringBuffer(); - for (int i = 0; i != values.length; ++i) { - Object value = values[i]; - - String s; - if (value == null) { - s = "null"; - } else if (value instanceof Boolean) { - s = "boolean"; - } else if (value instanceof String) { - s = "string"; - } else if (value instanceof Number) { - s = "number"; - } else if (value instanceof Scriptable) { - if (value instanceof Undefined) { - s = "undefined"; - } else if (value instanceof Wrapper) { - Object wrapped = ((Wrapper)value).unwrap(); - s = wrapped.getClass().getName(); - } else if (value instanceof Function) { - s = "function"; - } else { - s = "object"; - } - } else { - s = JavaMembers.javaSignature(value.getClass()); - } - - if (i != 0) { - sig.append(','); - } - sig.append(s); - } - return sig.toString(); - } - - String decompile(int indent, int flags) - { - StringBuffer sb = new StringBuffer(); - boolean justbody = (0 != (flags & Decompiler.ONLY_BODY_FLAG)); - if (!justbody) { - sb.append("function "); - sb.append(getFunctionName()); - sb.append("() {"); - } - sb.append("/*\n"); - sb.append(toString()); - sb.append(justbody ? "*/\n" : "*/}\n"); - return sb.toString(); - } - - public String toString() - { - StringBuffer sb = new StringBuffer(); - for (int i = 0, N = methods.length; i != N; ++i) { - Method method = methods[i].method(); - sb.append(JavaMembers.javaSignature(method.getReturnType())); - sb.append(' '); - sb.append(method.getName()); - sb.append(JavaMembers.liveConnectSignature(methods[i].argTypes)); - sb.append('\n'); - } - return sb.toString(); - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - // Find a method that matches the types given. - if (methods.length == 0) { - throw new RuntimeException("No methods defined for call"); - } - - int index = findFunction(cx, methods, args); - if (index < 0) { - Class c = methods[0].method().getDeclaringClass(); - String sig = c.getName() + '.' + getFunctionName() + '(' + - scriptSignature(args) + ')'; - throw Context.reportRuntimeError1("msg.java.no_such_method", sig); - } - - MemberBox meth = methods[index]; - Class[] argTypes = meth.argTypes; - - if (meth.vararg) { - // marshall the explicit parameters - Object[] newArgs = new Object[argTypes.length]; - for (int i = 0; i < argTypes.length-1; i++) { - newArgs[i] = Context.jsToJava(args[i], argTypes[i]); - } - - Object varArgs; - - // Handle special situation where a single variable parameter - // is given and it is a Java or ECMA array or is null. - if (args.length == argTypes.length && - (args[args.length-1] == null || - args[args.length-1] instanceof NativeArray || - args[args.length-1] instanceof NativeJavaArray)) - { - // convert the ECMA array into a native array - varArgs = Context.jsToJava(args[args.length-1], - argTypes[argTypes.length - 1]); - } else { - // marshall the variable parameters - Class componentType = argTypes[argTypes.length - 1]. - getComponentType(); - varArgs = Array.newInstance(componentType, - args.length - argTypes.length + 1); - for (int i = 0; i < Array.getLength(varArgs); i++) { - Object value = Context.jsToJava(args[argTypes.length-1 + i], - componentType); - Array.set(varArgs, i, value); - } - } - - // add varargs - newArgs[argTypes.length-1] = varArgs; - // replace the original args with the new one - args = newArgs; - } else { - // First, we marshall the args. - Object[] origArgs = args; - for (int i = 0; i < args.length; i++) { - Object arg = args[i]; - Object coerced = Context.jsToJava(arg, argTypes[i]); - if (coerced != arg) { - if (origArgs == args) { - args = args.clone(); - } - args[i] = coerced; - } - } - } - Object javaObject; - if (meth.isStatic()) { - javaObject = null; // don't need an object - } else { - Scriptable o = thisObj; - Class c = meth.getDeclaringClass(); - for (;;) { - if (o == null) { - throw Context.reportRuntimeError3( - "msg.nonjava.method", getFunctionName(), - ScriptRuntime.toString(thisObj), c.getName()); - } - if (o instanceof Wrapper) { - javaObject = ((Wrapper)o).unwrap(); - if (c.isInstance(javaObject)) { - break; - } - } - o = o.getPrototype(); - } - } - if (debug) { - printDebug("Calling ", meth, args); - } - - Object retval = meth.invoke(javaObject, args); - Class staticType = meth.method().getReturnType(); - - if (debug) { - Class actualType = (retval == null) ? null - : retval.getClass(); - System.err.println(" ----- Returned " + retval + - " actual = " + actualType + - " expect = " + staticType); - } - - Object wrapped = cx.getWrapFactory().wrap(cx, scope, - retval, staticType); - if (debug) { - Class actualType = (wrapped == null) ? null - : wrapped.getClass(); - System.err.println(" ----- Wrapped as " + wrapped + - " class = " + actualType); - } - - if (wrapped == null && staticType == Void.TYPE) { - wrapped = Undefined.instance; - } - return wrapped; - } - - /** - * Find the index of the correct function to call given the set of methods - * or constructors and the arguments. - * If no function can be found to call, return -1. - */ - static int findFunction(Context cx, - MemberBox[] methodsOrCtors, Object[] args) - { - if (methodsOrCtors.length == 0) { - return -1; - } else if (methodsOrCtors.length == 1) { - MemberBox member = methodsOrCtors[0]; - Class[] argTypes = member.argTypes; - int alength = argTypes.length; - - if (member.vararg) { - alength--; - if ( alength > args.length) { - return -1; - } - } else { - if (alength != args.length) { - return -1; - } - } - for (int j = 0; j != alength; ++j) { - if (!NativeJavaObject.canConvert(args[j], argTypes[j])) { - if (debug) printDebug("Rejecting (args can't convert) ", - member, args); - return -1; - } - } - if (debug) printDebug("Found ", member, args); - return 0; - } - - int firstBestFit = -1; - int[] extraBestFits = null; - int extraBestFitsCount = 0; - - search: - for (int i = 0; i < methodsOrCtors.length; i++) { - MemberBox member = methodsOrCtors[i]; - Class[] argTypes = member.argTypes; - int alength = argTypes.length; - if (member.vararg) { - alength--; - if ( alength > args.length) { - continue search; - } - } else { - if (alength != args.length) { - continue search; - } - } - for (int j = 0; j < alength; j++) { - if (!NativeJavaObject.canConvert(args[j], argTypes[j])) { - if (debug) printDebug("Rejecting (args can't convert) ", - member, args); - continue search; - } - } - if (firstBestFit < 0) { - if (debug) printDebug("Found first applicable ", member, args); - firstBestFit = i; - } else { - // Compare with all currently fit methods. - // The loop starts from -1 denoting firstBestFit and proceed - // until extraBestFitsCount to avoid extraBestFits allocation - // in the most common case of no ambiguity - int betterCount = 0; // number of times member was prefered over - // best fits - int worseCount = 0; // number of times best fits were prefered - // over member - for (int j = -1; j != extraBestFitsCount; ++j) { - int bestFitIndex; - if (j == -1) { - bestFitIndex = firstBestFit; - } else { - bestFitIndex = extraBestFits[j]; - } - MemberBox bestFit = methodsOrCtors[bestFitIndex]; - if (cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) && - (bestFit.member().getModifiers() & Modifier.PUBLIC) != - (member.member().getModifiers() & Modifier.PUBLIC)) - { - // When FEATURE_ENHANCED_JAVA_ACCESS gives us access - // to non-public members, continue to prefer public - // methods in overloading - if ((bestFit.member().getModifiers() & Modifier.PUBLIC) == 0) - ++betterCount; - else - ++worseCount; - } else { - int preference = preferSignature(args, argTypes, - member.vararg, - bestFit.argTypes, - bestFit.vararg ); - if (preference == PREFERENCE_AMBIGUOUS) { - break; - } else if (preference == PREFERENCE_FIRST_ARG) { - ++betterCount; - } else if (preference == PREFERENCE_SECOND_ARG) { - ++worseCount; - } else { - if (preference != PREFERENCE_EQUAL) Kit.codeBug(); - // This should not happen in theory - // but on some JVMs, Class.getMethods will return all - // static methods of the class heirarchy, even if - // a derived class's parameters match exactly. - // We want to call the dervied class's method. - if (bestFit.isStatic() - && bestFit.getDeclaringClass().isAssignableFrom( - member.getDeclaringClass())) - { - // On some JVMs, Class.getMethods will return all - // static methods of the class heirarchy, even if - // a derived class's parameters match exactly. - // We want to call the dervied class's method. - if (debug) printDebug( - "Substituting (overridden static)", - member, args); - if (j == -1) { - firstBestFit = i; - } else { - extraBestFits[j] = i; - } - } else { - if (debug) printDebug( - "Ignoring same signature member ", - member, args); - } - continue search; - } - } - } - if (betterCount == 1 + extraBestFitsCount) { - // member was prefered over all best fits - if (debug) printDebug( - "New first applicable ", member, args); - firstBestFit = i; - extraBestFitsCount = 0; - } else if (worseCount == 1 + extraBestFitsCount) { - // all best fits were prefered over member, ignore it - if (debug) printDebug( - "Rejecting (all current bests better) ", member, args); - } else { - // some ambiguity was present, add member to best fit set - if (debug) printDebug( - "Added to best fit set ", member, args); - if (extraBestFits == null) { - // Allocate maximum possible array - extraBestFits = new int[methodsOrCtors.length - 1]; - } - extraBestFits[extraBestFitsCount] = i; - ++extraBestFitsCount; - } - } - } - - if (firstBestFit < 0) { - // Nothing was found - return -1; - } else if (extraBestFitsCount == 0) { - // single best fit - return firstBestFit; - } - - // report remaining ambiguity - StringBuffer buf = new StringBuffer(); - for (int j = -1; j != extraBestFitsCount; ++j) { - int bestFitIndex; - if (j == -1) { - bestFitIndex = firstBestFit; - } else { - bestFitIndex = extraBestFits[j]; - } - buf.append("\n "); - buf.append(methodsOrCtors[bestFitIndex].toJavaDeclaration()); - } - - MemberBox firstFitMember = methodsOrCtors[firstBestFit]; - String memberName = firstFitMember.getName(); - String memberClass = firstFitMember.getDeclaringClass().getName(); - - if (methodsOrCtors[0].isMethod()) { - throw Context.reportRuntimeError3( - "msg.constructor.ambiguous", - memberName, scriptSignature(args), buf.toString()); - } else { - throw Context.reportRuntimeError4( - "msg.method.ambiguous", memberClass, - memberName, scriptSignature(args), buf.toString()); - } - } - - /** Types are equal */ - private static final int PREFERENCE_EQUAL = 0; - private static final int PREFERENCE_FIRST_ARG = 1; - private static final int PREFERENCE_SECOND_ARG = 2; - /** No clear "easy" conversion */ - private static final int PREFERENCE_AMBIGUOUS = 3; - - /** - * Determine which of two signatures is the closer fit. - * Returns one of PREFERENCE_EQUAL, PREFERENCE_FIRST_ARG, - * PREFERENCE_SECOND_ARG, or PREFERENCE_AMBIGUOUS. - */ - private static int preferSignature(Object[] args, - Class[] sig1, - boolean vararg1, - Class[] sig2, - boolean vararg2 ) - { - // TODO: This test is pretty primitive. It bascially prefers - // a matching no vararg method over a vararg method independent - // of the type conversion cost. This can lead to unexpected results. - int alength = args.length; - if (!vararg1 && vararg2) { - // prefer the no vararg signature - return PREFERENCE_FIRST_ARG; - } else if (vararg1 && !vararg2) { - // prefer the no vararg signature - return PREFERENCE_SECOND_ARG; - } else if (vararg1 && vararg2) { - if (sig1.length < sig2.length) { - // prefer the signature with more explicit types - return PREFERENCE_SECOND_ARG; - } else if (sig1.length > sig2.length) { - // prefer the signature with more explicit types - return PREFERENCE_FIRST_ARG; - } else { - // Both are varargs and have the same length, so make the - // decision with the explicit args. - alength = Math.min(args.length, sig1.length-1); - } - } - - int totalPreference = 0; - for (int j = 0; j < alength; j++) { - Class type1 = sig1[j]; - Class type2 = sig2[j]; - if (type1 == type2) { - continue; - } - Object arg = args[j]; - - // Determine which of type1, type2 is easier to convert from arg. - - int rank1 = NativeJavaObject.getConversionWeight(arg, type1); - int rank2 = NativeJavaObject.getConversionWeight(arg, type2); - - int preference; - if (rank1 < rank2) { - preference = PREFERENCE_FIRST_ARG; - } else if (rank1 > rank2) { - preference = PREFERENCE_SECOND_ARG; - } else { - // Equal ranks - if (rank1 == NativeJavaObject.CONVERSION_NONTRIVIAL) { - if (type1.isAssignableFrom(type2)) { - preference = PREFERENCE_SECOND_ARG; - } else if (type2.isAssignableFrom(type1)) { - preference = PREFERENCE_FIRST_ARG; - } else { - preference = PREFERENCE_AMBIGUOUS; - } - } else { - preference = PREFERENCE_AMBIGUOUS; - } - } - - totalPreference |= preference; - - if (totalPreference == PREFERENCE_AMBIGUOUS) { - break; - } - } - return totalPreference; - } - - - private static final boolean debug = false; - - private static void printDebug(String msg, MemberBox member, - Object[] args) - { - if (debug) { - StringBuffer sb = new StringBuffer(); - sb.append(" ----- "); - sb.append(msg); - sb.append(member.getDeclaringClass().getName()); - sb.append('.'); - if (member.isMethod()) { - sb.append(member.getName()); - } - sb.append(JavaMembers.liveConnectSignature(member.argTypes)); - sb.append(" for arguments ("); - sb.append(scriptSignature(args)); - sb.append(')'); - System.out.println(sb); - } - } - - MemberBox[] methods; - private String functionName; -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaObject.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaObject.java deleted file mode 100644 index 3d27852..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaObject.java +++ /dev/null @@ -1,1002 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Frank Mitchell - * Mike Shaver - * Kemal Bayram - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.*; -import java.lang.reflect.*; -import java.util.Hashtable; -import java.util.Date; - -/** - * This class reflects non-Array Java objects into the JavaScript environment. It - * reflect fields directly, and uses NativeJavaMethod objects to reflect (possibly - * overloaded) methods.<p> - * - * @author Mike Shaver - * @see NativeJavaArray - * @see NativeJavaPackage - * @see NativeJavaClass - */ - -public class NativeJavaObject implements Scriptable, Wrapper, Serializable -{ - static final long serialVersionUID = -6948590651130498591L; - - public NativeJavaObject() { } - - public NativeJavaObject(Scriptable scope, Object javaObject, - Class staticType) - { - this(scope, javaObject, staticType, false); - } - - public NativeJavaObject(Scriptable scope, Object javaObject, - Class staticType, boolean isAdapter) - { - this.parent = ScriptableObject.getVeryTopLevelScope(scope); // APPJET - this.javaObject = javaObject; - this.staticType = staticType; - this.isAdapter = isAdapter; - initMembers(); - } - - protected void initMembers() { - Class dynamicType; - if (javaObject != null) { - dynamicType = javaObject.getClass(); - } else { - dynamicType = staticType; - } - members = JavaMembers.lookupClass(parent, dynamicType, staticType, - isAdapter); - fieldAndMethods - = members.getFieldAndMethodsObjects(this, javaObject, false); - } - - public boolean has(String name, Scriptable start) { - return members.has(name, false); - } - - public boolean has(int index, Scriptable start) { - return false; - } - - public Object get(String name, Scriptable start) { - if (fieldAndMethods != null) { - Object result = fieldAndMethods.get(name); - if (result != null) { - return result; - } - } - // TODO: passing 'this' as the scope is bogus since it has - // no parent scope - return members.get(this, name, javaObject, false); - } - - public Object get(int index, Scriptable start) { - throw members.reportMemberNotFound(Integer.toString(index)); - } - - public void put(String name, Scriptable start, Object value) { - // We could be asked to modify the value of a property in the - // prototype. Since we can't add a property to a Java object, - // we modify it in the prototype rather than copy it down. - if (prototype == null || members.has(name, false)) - members.put(this, name, javaObject, value, false); - else - prototype.put(name, prototype, value); - } - - public void put(int index, Scriptable start, Object value) { - throw members.reportMemberNotFound(Integer.toString(index)); - } - - public boolean hasInstance(Scriptable value) { - // This is an instance of a Java class, so always return false - return false; - } - - public void delete(String name) { - } - - public void delete(int index) { - } - - public Scriptable getPrototype() { - if (prototype == null && javaObject instanceof String) { - return ScriptableObject.getClassPrototype(parent, "String"); - } - return prototype; - } - - /** - * Sets the prototype of the object. - */ - public void setPrototype(Scriptable m) { - prototype = m; - } - - /** - * Returns the parent (enclosing) scope of the object. - */ - public Scriptable getParentScope() { - return parent; - } - - /** - * Sets the parent (enclosing) scope of the object. - */ - public void setParentScope(Scriptable m) { - parent = m; - } - - public Object[] getIds() { - return members.getIds(false); - } - -/** -@deprecated Use {@link Context#getWrapFactory()} together with calling {@link -WrapFactory#wrap(Context, Scriptable, Object, Class)} -*/ - public static Object wrap(Scriptable scope, Object obj, Class staticType) { - - Context cx = Context.getContext(); - return cx.getWrapFactory().wrap(cx, scope, obj, staticType); - } - - public Object unwrap() { - return javaObject; - } - - public String getClassName() { - return "JavaObject"; - } - - public Object getDefaultValue(Class hint) - { - Object value; - if (hint == null) { - if (javaObject instanceof Boolean) { - hint = ScriptRuntime.BooleanClass; - } - } - if (hint == null || hint == ScriptRuntime.StringClass) { - value = javaObject.toString(); - } else { - String converterName; - if (hint == ScriptRuntime.BooleanClass) { - converterName = "booleanValue"; - } else if (hint == ScriptRuntime.NumberClass) { - converterName = "doubleValue"; - } else { - throw Context.reportRuntimeError0("msg.default.value"); - } - Object converterObject = get(converterName, this); - if (converterObject instanceof Function) { - Function f = (Function)converterObject; - value = f.call(Context.getContext(), f.getParentScope(), - this, ScriptRuntime.emptyArgs); - } else { - if (hint == ScriptRuntime.NumberClass - && javaObject instanceof Boolean) - { - boolean b = ((Boolean)javaObject).booleanValue(); - value = ScriptRuntime.wrapNumber(b ? 1.0 : 0.0); - } else { - value = javaObject.toString(); - } - } - } - return value; - } - - /** - * Determine whether we can/should convert between the given type and the - * desired one. This should be superceded by a conversion-cost calculation - * function, but for now I'll hide behind precedent. - */ - public static boolean canConvert(Object fromObj, Class to) { - int weight = getConversionWeight(fromObj, to); - - return (weight < CONVERSION_NONE); - } - - private static final int JSTYPE_UNDEFINED = 0; // undefined type - private static final int JSTYPE_NULL = 1; // null - private static final int JSTYPE_BOOLEAN = 2; // boolean - private static final int JSTYPE_NUMBER = 3; // number - private static final int JSTYPE_STRING = 4; // string - private static final int JSTYPE_JAVA_CLASS = 5; // JavaClass - private static final int JSTYPE_JAVA_OBJECT = 6; // JavaObject - private static final int JSTYPE_JAVA_ARRAY = 7; // JavaArray - private static final int JSTYPE_OBJECT = 8; // Scriptable - - static final byte CONVERSION_TRIVIAL = 1; - static final byte CONVERSION_NONTRIVIAL = 0; - static final byte CONVERSION_NONE = 99; - - /** - * Derive a ranking based on how "natural" the conversion is. - * The special value CONVERSION_NONE means no conversion is possible, - * and CONVERSION_NONTRIVIAL signals that more type conformance testing - * is required. - * Based on - * <a href="http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html"> - * "preferred method conversions" from Live Connect 3</a> - */ - static int getConversionWeight(Object fromObj, Class to) { - int fromCode = getJSTypeCode(fromObj); - - switch (fromCode) { - - case JSTYPE_UNDEFINED: - if (to == ScriptRuntime.StringClass || - to == ScriptRuntime.ObjectClass) { - return 1; - } - break; - - case JSTYPE_NULL: - if (!to.isPrimitive()) { - return 1; - } - break; - - case JSTYPE_BOOLEAN: - // "boolean" is #1 - if (to == Boolean.TYPE) { - return 1; - } - else if (to == ScriptRuntime.BooleanClass) { - return 2; - } - else if (to == ScriptRuntime.ObjectClass) { - return 3; - } - else if (to == ScriptRuntime.StringClass) { - return 4; - } - break; - - case JSTYPE_NUMBER: - if (to.isPrimitive()) { - if (to == Double.TYPE) { - return 1; - } - else if (to != Boolean.TYPE) { - return 1 + getSizeRank(to); - } - } - else { - if (to == ScriptRuntime.StringClass) { - // native numbers are #1-8 - return 9; - } - else if (to == ScriptRuntime.ObjectClass) { - return 10; - } - else if (ScriptRuntime.NumberClass.isAssignableFrom(to)) { - // "double" is #1 - return 2; - } - } - break; - - case JSTYPE_STRING: - if (to == ScriptRuntime.StringClass) { - return 1; - } - else if (to.isInstance(fromObj)) { - return 2; - } - else if (to.isPrimitive()) { - if (to == Character.TYPE) { - return 3; - } else if (to != Boolean.TYPE) { - return 4; - } - } - break; - - case JSTYPE_JAVA_CLASS: - if (to == ScriptRuntime.ClassClass) { - return 1; - } - else if (to == ScriptRuntime.ObjectClass) { - return 3; - } - else if (to == ScriptRuntime.StringClass) { - return 4; - } - break; - - case JSTYPE_JAVA_OBJECT: - case JSTYPE_JAVA_ARRAY: - Object javaObj = fromObj; - if (javaObj instanceof Wrapper) { - javaObj = ((Wrapper)javaObj).unwrap(); - } - if (to.isInstance(javaObj)) { - return CONVERSION_NONTRIVIAL; - } - if (to == ScriptRuntime.StringClass) { - return 2; - } - else if (to.isPrimitive() && to != Boolean.TYPE) { - return (fromCode == JSTYPE_JAVA_ARRAY) - ? CONVERSION_NONE : 2 + getSizeRank(to); - } - break; - - case JSTYPE_OBJECT: - // Other objects takes #1-#3 spots - if (to == fromObj.getClass()) { - // No conversion required - return 1; - } - if (to.isArray()) { - if (fromObj instanceof NativeArray) { - // This is a native array conversion to a java array - // Array conversions are all equal, and preferable to object - // and string conversion, per LC3. - return 1; - } - } - else if (to == ScriptRuntime.ObjectClass) { - return 2; - } - else if (to == ScriptRuntime.StringClass) { - return 3; - } - else if (to == ScriptRuntime.DateClass) { - if (fromObj instanceof NativeDate) { - // This is a native date to java date conversion - return 1; - } - } - else if (to.isInterface()) { - if (fromObj instanceof Function) { - // See comments in coerceType - if (to.getMethods().length == 1) { - return 1; - } - } - return 11; - } - else if (to.isPrimitive() && to != Boolean.TYPE) { - return 3 + getSizeRank(to); - } - break; - } - - return CONVERSION_NONE; - } - - static int getSizeRank(Class aType) { - if (aType == Double.TYPE) { - return 1; - } - else if (aType == Float.TYPE) { - return 2; - } - else if (aType == Long.TYPE) { - return 3; - } - else if (aType == Integer.TYPE) { - return 4; - } - else if (aType == Short.TYPE) { - return 5; - } - else if (aType == Character.TYPE) { - return 6; - } - else if (aType == Byte.TYPE) { - return 7; - } - else if (aType == Boolean.TYPE) { - return CONVERSION_NONE; - } - else { - return 8; - } - } - - private static int getJSTypeCode(Object value) { - if (value == null) { - return JSTYPE_NULL; - } - else if (value == Undefined.instance) { - return JSTYPE_UNDEFINED; - } - else if (value instanceof String) { - return JSTYPE_STRING; - } - else if (value instanceof Number) { - return JSTYPE_NUMBER; - } - else if (value instanceof Boolean) { - return JSTYPE_BOOLEAN; - } - else if (value instanceof Scriptable) { - if (value instanceof NativeJavaClass) { - return JSTYPE_JAVA_CLASS; - } - else if (value instanceof NativeJavaArray) { - return JSTYPE_JAVA_ARRAY; - } - else if (value instanceof Wrapper) { - return JSTYPE_JAVA_OBJECT; - } - else { - return JSTYPE_OBJECT; - } - } - else if (value instanceof Class) { - return JSTYPE_JAVA_CLASS; - } - else { - Class valueClass = value.getClass(); - if (valueClass.isArray()) { - return JSTYPE_JAVA_ARRAY; - } - else { - return JSTYPE_JAVA_OBJECT; - } - } - } - - /** - * Not intended for public use. Callers should use the - * public API Context.toType. - * @deprecated as of 1.5 Release 4 - * @see org.mozilla.javascript.Context#jsToJava(Object, Class) - */ - public static Object coerceType(Class type, Object value) - { - return coerceTypeImpl(type, value); - } - - /** - * Type-munging for field setting and method invocation. - * Conforms to LC3 specification - */ - static Object coerceTypeImpl(Class type, Object value) - { - if (value != null && value.getClass() == type) { - return value; - } - - switch (getJSTypeCode(value)) { - - case JSTYPE_NULL: - // raise error if type.isPrimitive() - if (type.isPrimitive()) { - reportConversionError(value, type); - } - return null; - - case JSTYPE_UNDEFINED: - if (type == ScriptRuntime.StringClass || - type == ScriptRuntime.ObjectClass) { - return "undefined"; - } - else { - reportConversionError("undefined", type); - } - break; - - case JSTYPE_BOOLEAN: - // Under LC3, only JS Booleans can be coerced into a Boolean value - if (type == Boolean.TYPE || - type == ScriptRuntime.BooleanClass || - type == ScriptRuntime.ObjectClass) { - return value; - } - else if (type == ScriptRuntime.StringClass) { - return value.toString(); - } - else { - reportConversionError(value, type); - } - break; - - case JSTYPE_NUMBER: - if (type == ScriptRuntime.StringClass) { - return ScriptRuntime.toString(value); - } - else if (type == ScriptRuntime.ObjectClass) { - return coerceToNumber(Double.TYPE, value); - } - else if ((type.isPrimitive() && type != Boolean.TYPE) || - ScriptRuntime.NumberClass.isAssignableFrom(type)) { - return coerceToNumber(type, value); - } - else { - reportConversionError(value, type); - } - break; - - case JSTYPE_STRING: - if (type == ScriptRuntime.StringClass || type.isInstance(value)) { - return value; - } - else if (type == Character.TYPE - || type == ScriptRuntime.CharacterClass) - { - // Special case for converting a single char string to a - // character - // Placed here because it applies *only* to JS strings, - // not other JS objects converted to strings - if (((String)value).length() == 1) { - return new Character(((String)value).charAt(0)); - } - else { - return coerceToNumber(type, value); - } - } - else if ((type.isPrimitive() && type != Boolean.TYPE) - || ScriptRuntime.NumberClass.isAssignableFrom(type)) - { - return coerceToNumber(type, value); - } - else { - reportConversionError(value, type); - } - break; - - case JSTYPE_JAVA_CLASS: - if (value instanceof Wrapper) { - value = ((Wrapper)value).unwrap(); - } - - if (type == ScriptRuntime.ClassClass || - type == ScriptRuntime.ObjectClass) { - return value; - } - else if (type == ScriptRuntime.StringClass) { - return value.toString(); - } - else { - reportConversionError(value, type); - } - break; - - case JSTYPE_JAVA_OBJECT: - case JSTYPE_JAVA_ARRAY: - if (value instanceof Wrapper) { - value = ((Wrapper)value).unwrap(); - } - if (type.isPrimitive()) { - if (type == Boolean.TYPE) { - reportConversionError(value, type); - } - return coerceToNumber(type, value); - } - else { - if (type == ScriptRuntime.StringClass) { - return value.toString(); - } - else { - if (type.isInstance(value)) { - return value; - } - else { - reportConversionError(value, type); - } - } - } - break; - - case JSTYPE_OBJECT: - if (type == ScriptRuntime.StringClass) { - return ScriptRuntime.toString(value); - } - else if (type.isPrimitive()) { - if (type == Boolean.TYPE) { - reportConversionError(value, type); - } - return coerceToNumber(type, value); - } - else if (type.isInstance(value)) { - return value; - } - else if (type == ScriptRuntime.DateClass - && value instanceof NativeDate) - { - double time = ((NativeDate)value).getJSTimeValue(); - // XXX: This will replace NaN by 0 - return new Date((long)time); - } - else if (type.isArray() && value instanceof NativeArray) { - // Make a new java array, and coerce the JS array components - // to the target (component) type. - NativeArray array = (NativeArray) value; - long length = array.getLength(); - Class arrayType = type.getComponentType(); - Object Result = Array.newInstance(arrayType, (int)length); - for (int i = 0 ; i < length ; ++i) { - try { - Array.set(Result, i, coerceType(arrayType, - array.get(i, array))); - } - catch (EvaluatorException ee) { - reportConversionError(value, type); - } - } - - return Result; - } - else if (value instanceof Wrapper) { - value = ((Wrapper)value).unwrap(); - if (type.isInstance(value)) - return value; - reportConversionError(value, type); - } - else if (type.isInterface() && value instanceof Callable) { - // Try to use function as implementation of Java interface. - // - // XXX: Curently only instances of ScriptableObject are - // supported since the resulting interface proxies should - // be reused next time conversion is made and generic - // Callable has no storage for it. Weak references can - // address it but for now use this restriction. - if (value instanceof ScriptableObject) { - ScriptableObject so = (ScriptableObject)value; - Object key = Kit.makeHashKeyFromPair( - COERCED_INTERFACE_KEY, type); - Object old = so.getAssociatedValue(key); - if (old != null) { - // Function was already wrapped - return old; - } - Context cx = Context.getContext(); - Object glue - = InterfaceAdapter.create(cx, type, (Callable)value); - // Store for later retrival - glue = so.associateValue(key, glue); - return glue; - } - reportConversionError(value, type); - } else { - reportConversionError(value, type); - } - break; - } - - return value; - } - - private static Object coerceToNumber(Class type, Object value) - { - Class valueClass = value.getClass(); - - // Character - if (type == Character.TYPE || type == ScriptRuntime.CharacterClass) { - if (valueClass == ScriptRuntime.CharacterClass) { - return value; - } - return new Character((char)toInteger(value, - ScriptRuntime.CharacterClass, - Character.MIN_VALUE, - Character.MAX_VALUE)); - } - - // Double, Float - if (type == ScriptRuntime.ObjectClass || - type == ScriptRuntime.DoubleClass || type == Double.TYPE) { - return valueClass == ScriptRuntime.DoubleClass - ? value - : new Double(toDouble(value)); - } - - if (type == ScriptRuntime.FloatClass || type == Float.TYPE) { - if (valueClass == ScriptRuntime.FloatClass) { - return value; - } - else { - double number = toDouble(value); - if (Double.isInfinite(number) || Double.isNaN(number) - || number == 0.0) { - return new Float((float)number); - } - else { - double absNumber = Math.abs(number); - if (absNumber < Float.MIN_VALUE) { - return new Float((number > 0.0) ? +0.0 : -0.0); - } - else if (absNumber > Float.MAX_VALUE) { - return new Float((number > 0.0) ? - Float.POSITIVE_INFINITY : - Float.NEGATIVE_INFINITY); - } - else { - return new Float((float)number); - } - } - } - } - - // Integer, Long, Short, Byte - if (type == ScriptRuntime.IntegerClass || type == Integer.TYPE) { - if (valueClass == ScriptRuntime.IntegerClass) { - return value; - } - else { - return new Integer((int)toInteger(value, - ScriptRuntime.IntegerClass, - Integer.MIN_VALUE, - Integer.MAX_VALUE)); - } - } - - if (type == ScriptRuntime.LongClass || type == Long.TYPE) { - if (valueClass == ScriptRuntime.LongClass) { - return value; - } else { - /* Long values cannot be expressed exactly in doubles. - * We thus use the largest and smallest double value that - * has a value expressible as a long value. We build these - * numerical values from their hexidecimal representations - * to avoid any problems caused by attempting to parse a - * decimal representation. - */ - final double max = Double.longBitsToDouble(0x43dfffffffffffffL); - final double min = Double.longBitsToDouble(0xc3e0000000000000L); - return new Long(toInteger(value, - ScriptRuntime.LongClass, - min, - max)); - } - } - - if (type == ScriptRuntime.ShortClass || type == Short.TYPE) { - if (valueClass == ScriptRuntime.ShortClass) { - return value; - } - else { - return new Short((short)toInteger(value, - ScriptRuntime.ShortClass, - Short.MIN_VALUE, - Short.MAX_VALUE)); - } - } - - if (type == ScriptRuntime.ByteClass || type == Byte.TYPE) { - if (valueClass == ScriptRuntime.ByteClass) { - return value; - } - else { - return new Byte((byte)toInteger(value, - ScriptRuntime.ByteClass, - Byte.MIN_VALUE, - Byte.MAX_VALUE)); - } - } - - return new Double(toDouble(value)); - } - - - private static double toDouble(Object value) - { - if (value instanceof Number) { - return ((Number)value).doubleValue(); - } - else if (value instanceof String) { - return ScriptRuntime.toNumber((String)value); - } - else if (value instanceof Scriptable) { - if (value instanceof Wrapper) { - // XXX: optimize tail-recursion? - return toDouble(((Wrapper)value).unwrap()); - } - else { - return ScriptRuntime.toNumber(value); - } - } - else { - Method meth; - try { - meth = value.getClass().getMethod("doubleValue", - (Class [])null); - } - catch (NoSuchMethodException e) { - meth = null; - } - catch (SecurityException e) { - meth = null; - } - if (meth != null) { - try { - return ((Number)meth.invoke(value, - (Object [])null)).doubleValue(); - } - catch (IllegalAccessException e) { - // XXX: ignore, or error message? - reportConversionError(value, Double.TYPE); - } - catch (InvocationTargetException e) { - // XXX: ignore, or error message? - reportConversionError(value, Double.TYPE); - } - } - return ScriptRuntime.toNumber(value.toString()); - } - } - - private static long toInteger(Object value, Class type, - double min, double max) - { - double d = toDouble(value); - - if (Double.isInfinite(d) || Double.isNaN(d)) { - // Convert to string first, for more readable message - reportConversionError(ScriptRuntime.toString(value), type); - } - - if (d > 0.0) { - d = Math.floor(d); - } - else { - d = Math.ceil(d); - } - - if (d < min || d > max) { - // Convert to string first, for more readable message - reportConversionError(ScriptRuntime.toString(value), type); - } - return (long)d; - } - - static void reportConversionError(Object value, Class type) - { - // It uses String.valueOf(value), not value.toString() since - // value can be null, bug 282447. - throw Context.reportRuntimeError2( - "msg.conversion.not.allowed", - String.valueOf(value), - JavaMembers.javaSignature(type)); - } - - private void writeObject(ObjectOutputStream out) - throws IOException - { - out.defaultWriteObject(); - - out.writeBoolean(isAdapter); - if (isAdapter) { - if (adapter_writeAdapterObject == null) { - throw new IOException(); - } - Object[] args = { javaObject, out }; - try { - adapter_writeAdapterObject.invoke(null, args); - } catch (Exception ex) { - throw new IOException(); - } - } else { - out.writeObject(javaObject); - } - - if (staticType != null) { - out.writeObject(staticType.getClass().getName()); - } else { - out.writeObject(null); - } - } - - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - - isAdapter = in.readBoolean(); - if (isAdapter) { - if (adapter_readAdapterObject == null) - throw new ClassNotFoundException(); - Object[] args = { this, in }; - try { - javaObject = adapter_readAdapterObject.invoke(null, args); - } catch (Exception ex) { - throw new IOException(); - } - } else { - javaObject = in.readObject(); - } - - String className = (String)in.readObject(); - if (className != null) { - staticType = Class.forName(className); - } else { - staticType = null; - } - - initMembers(); - } - - /** - * The prototype of this object. - */ - protected Scriptable prototype; - - /** - * The parent scope of this object. - */ - protected Scriptable parent; - - protected transient Object javaObject; - - protected transient Class staticType; - protected transient JavaMembers members; - private transient Hashtable fieldAndMethods; - private transient boolean isAdapter; - - private static final Object COERCED_INTERFACE_KEY = new Object(); - private static Method adapter_writeAdapterObject; - private static Method adapter_readAdapterObject; - - static { - // Reflection in java is verbose - Class[] sig2 = new Class[2]; - Class cl = Kit.classOrNull("org.mozilla.javascript.JavaAdapter"); - if (cl != null) { - try { - sig2[0] = ScriptRuntime.ObjectClass; - sig2[1] = Kit.classOrNull("java.io.ObjectOutputStream"); - adapter_writeAdapterObject = cl.getMethod("writeAdapterObject", - sig2); - - sig2[0] = ScriptRuntime.ScriptableClass; - sig2[1] = Kit.classOrNull("java.io.ObjectInputStream"); - adapter_readAdapterObject = cl.getMethod("readAdapterObject", - sig2); - - } catch (Exception ex) { - adapter_writeAdapterObject = null; - adapter_readAdapterObject = null; - } - } - } - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaPackage.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaPackage.java deleted file mode 100644 index 71f09f7..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaPackage.java +++ /dev/null @@ -1,199 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Frank Mitchell - * Mike Shaver - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class reflects Java packages into the JavaScript environment. We - * lazily reflect classes and subpackages, and use a caching/sharing - * system to ensure that members reflected into one JavaPackage appear - * in all other references to the same package (as with Packages.java.lang - * and java.lang). - * - * @author Mike Shaver - * @see NativeJavaArray - * @see NativeJavaObject - * @see NativeJavaClass - */ - -public class NativeJavaPackage extends ScriptableObject -{ - static final long serialVersionUID = 7445054382212031523L; - - NativeJavaPackage(boolean internalUsage, - String packageName, ClassLoader classLoader) - { - this.packageName = packageName; - this.classLoader = classLoader; - } - - /** - * @deprecated NativeJavaPackage is an internal class, do not use - * it directly. - */ - public NativeJavaPackage(String packageName, ClassLoader classLoader) { - this(false, packageName, classLoader); - } - - /** - * @deprecated NativeJavaPackage is an internal class, do not use - * it directly. - */ - public NativeJavaPackage(String packageName) { - this(false, packageName, - Context.getCurrentContext().getApplicationClassLoader()); - } - - public String getClassName() { - return "JavaPackage"; - } - - public boolean has(String id, Scriptable start) { - return true; - } - - public boolean has(int index, Scriptable start) { - return false; - } - - public void put(String id, Scriptable start, Object value) { - // Can't add properties to Java packages. Sorry. - } - - public void put(int index, Scriptable start, Object value) { - throw Context.reportRuntimeError0("msg.pkg.int"); - } - - public Object get(String id, Scriptable start) { - return getPkgProperty(id, start, true); - } - - public Object get(int index, Scriptable start) { - return NOT_FOUND; - } - - // set up a name which is known to be a package so we don't - // need to look for a class by that name - void forcePackage(String name, Scriptable scope) - { - NativeJavaPackage pkg; - int end = name.indexOf('.'); - if (end == -1) { - end = name.length(); - } - - String id = name.substring(0, end); - Object cached = super.get(id, this); - if (cached != null && cached instanceof NativeJavaPackage) { - pkg = (NativeJavaPackage) cached; - } else { - String newPackage = packageName.length() == 0 - ? id - : packageName + "." + id; - pkg = new NativeJavaPackage(true, newPackage, classLoader); - ScriptRuntime.setObjectProtoAndParent(pkg, scope); - super.put(id, this, pkg); - } - if (end < name.length()) { - pkg.forcePackage(name.substring(end+1), scope); - } - } - - synchronized Object getPkgProperty(String name, Scriptable start, - boolean createPkg) - { - Object cached = super.get(name, start); - if (cached != NOT_FOUND) - return cached; - - String className = (packageName.length() == 0) - ? name : packageName + '.' + name; - Context cx = Context.getContext(); - ClassShutter shutter = cx.getClassShutter(); - Scriptable newValue = null; - if (shutter == null || shutter.visibleToScripts(className)) { - Class cl = null; - if (classLoader != null) { - cl = Kit.classOrNull(classLoader, className); - } else { - cl = Kit.classOrNull(className); - } - if (cl != null) { - newValue = new NativeJavaClass(getTopLevelScope(this), cl); - newValue.setPrototype(getPrototype()); - } - } - if (newValue == null && createPkg) { - NativeJavaPackage pkg; - pkg = new NativeJavaPackage(true, className, classLoader); - ScriptRuntime.setObjectProtoAndParent(pkg, getParentScope()); - newValue = pkg; - } - if (newValue != null) { - // Make it available for fast lookup and sharing of - // lazily-reflected constructors and static members. - super.put(name, start, newValue); - } - return newValue; - } - - public Object getDefaultValue(Class ignored) { - return toString(); - } - - public String toString() { - return "[JavaPackage " + packageName + "]"; - } - - public boolean equals(Object obj) { - if(obj instanceof NativeJavaPackage) { - NativeJavaPackage njp = (NativeJavaPackage)obj; - return packageName.equals(njp.packageName) && classLoader == njp.classLoader; - } - return false; - } - - public int hashCode() { - return packageName.hashCode() ^ (classLoader == null ? 0 : classLoader.hashCode()); - } - - private String packageName; - private ClassLoader classLoader; -}
\ No newline at end of file diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaTopPackage.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaTopPackage.java deleted file mode 100644 index b5c9b49..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeJavaTopPackage.java +++ /dev/null @@ -1,187 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Frank Mitchell - * Mike Shaver - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class reflects Java packages into the JavaScript environment. We - * lazily reflect classes and subpackages, and use a caching/sharing - * system to ensure that members reflected into one JavaPackage appear - * in all other references to the same package (as with Packages.java.lang - * and java.lang). - * - * @author Mike Shaver - * @see NativeJavaArray - * @see NativeJavaObject - * @see NativeJavaClass - */ - -public class NativeJavaTopPackage - extends NativeJavaPackage implements Function, IdFunctionCall -{ - static final long serialVersionUID = -1455787259477709999L; - - // we know these are packages so we can skip the class check - // note that this is ok even if the package isn't present. - private static final String commonPackages = "" - +"java.lang;" - +"java.lang.reflect;" - +"java.io;" - +"java.math;" - +"java.net;" - +"java.util;" - +"java.util.zip;" - +"java.text;" - +"java.text.resources;" - +"java.applet;" - +"javax.swing;" - ; - - NativeJavaTopPackage(ClassLoader loader) - { - super(true, "", loader); - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - return construct(cx, scope, args); - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) - { - ClassLoader loader = null; - if (args.length != 0) { - Object arg = args[0]; - if (arg instanceof Wrapper) { - arg = ((Wrapper)arg).unwrap(); - } - if (arg instanceof ClassLoader) { - loader = (ClassLoader)arg; - } - } - if (loader == null) { - Context.reportRuntimeError0("msg.not.classloader"); - return null; - } - return new NativeJavaPackage(true, "", loader); - } - - public static void init(Context cx, Scriptable scope, boolean sealed) - { - ClassLoader loader = cx.getApplicationClassLoader(); - final NativeJavaTopPackage top = new NativeJavaTopPackage(loader); - top.setPrototype(getObjectPrototype(scope)); - top.setParentScope(scope); - - String[] names = Kit.semicolonSplit(commonPackages); - for (int i = 0; i != names.length; ++i) { - top.forcePackage(names[i], scope); - } - - // getClass implementation - IdFunctionObject getClass = new IdFunctionObject(top, FTAG, Id_getClass, - "getClass", 1, scope); - - // We want to get a real alias, and not a distinct JavaPackage - // with the same packageName, so that we share classes and top - // that are underneath. - String[] topNames = { "java", "javax", "org", "com", "edu", "net" }; - NativeJavaPackage[] topPackages = new NativeJavaPackage[topNames.length]; - for (int i=0; i < topNames.length; i++) { - topPackages[i] = (NativeJavaPackage)top.get(topNames[i], top); - } - - // It's safe to downcast here since initStandardObjects takes - // a ScriptableObject. - ScriptableObject global = (ScriptableObject) scope; - - if (sealed) { - getClass.sealObject(); - } - getClass.exportAsScopeProperty(); - global.defineProperty("Packages", top, ScriptableObject.DONTENUM); - for (int i=0; i < topNames.length; i++) { - global.defineProperty(topNames[i], topPackages[i], - ScriptableObject.DONTENUM); - } - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (f.hasTag(FTAG)) { - if (f.methodId() == Id_getClass) { - return js_getClass(cx, scope, args); - } - } - throw f.unknown(); - } - - private Scriptable js_getClass(Context cx, Scriptable scope, Object[] args) - { - if (args.length > 0 && args[0] instanceof Wrapper) { - Scriptable result = this; - Class cl = ((Wrapper) args[0]).unwrap().getClass(); - // Evaluate the class name by getting successive properties of - // the string to find the appropriate NativeJavaClass object - String name = cl.getName(); - int offset = 0; - for (;;) { - int index = name.indexOf('.', offset); - String propName = index == -1 - ? name.substring(offset) - : name.substring(offset, index); - Object prop = result.get(propName, result); - if (!(prop instanceof Scriptable)) - break; // fall through to error - result = (Scriptable) prop; - if (index == -1) - return result; - offset = index+1; - } - } - throw Context.reportRuntimeError0("msg.not.java.obj"); - } - - private static final Object FTAG = new Object(); - private static final int Id_getClass = 1; -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeMath.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeMath.java deleted file mode 100644 index 36b66b4..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeMath.java +++ /dev/null @@ -1,399 +0,0 @@ -/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class implements the Math native object. - * See ECMA 15.8. - * @author Norris Boyd - */ - -final class NativeMath extends IdScriptableObject -{ - static final long serialVersionUID = -8838847185801131569L; - - private static final Object MATH_TAG = new Object(); - - static void init(Scriptable scope, boolean sealed) - { - NativeMath obj = new NativeMath(); - obj.activatePrototypeMap(MAX_ID); - obj.setPrototype(getObjectPrototype(scope)); - obj.setParentScope(scope); - if (sealed) { obj.sealObject(); } - ScriptableObject.defineProperty(scope, "Math", obj, - ScriptableObject.DONTENUM); - } - - private NativeMath() - { - } - - public String getClassName() { return "Math"; } - - protected void initPrototypeId(int id) - { - if (id <= LAST_METHOD_ID) { - String name; - int arity; - switch (id) { - case Id_toSource: arity = 0; name = "toSource"; break; - case Id_abs: arity = 1; name = "abs"; break; - case Id_acos: arity = 1; name = "acos"; break; - case Id_asin: arity = 1; name = "asin"; break; - case Id_atan: arity = 1; name = "atan"; break; - case Id_atan2: arity = 2; name = "atan2"; break; - case Id_ceil: arity = 1; name = "ceil"; break; - case Id_cos: arity = 1; name = "cos"; break; - case Id_exp: arity = 1; name = "exp"; break; - case Id_floor: arity = 1; name = "floor"; break; - case Id_log: arity = 1; name = "log"; break; - case Id_max: arity = 2; name = "max"; break; - case Id_min: arity = 2; name = "min"; break; - case Id_pow: arity = 2; name = "pow"; break; - case Id_random: arity = 0; name = "random"; break; - case Id_round: arity = 1; name = "round"; break; - case Id_sin: arity = 1; name = "sin"; break; - case Id_sqrt: arity = 1; name = "sqrt"; break; - case Id_tan: arity = 1; name = "tan"; break; - default: throw new IllegalStateException(String.valueOf(id)); - } - initPrototypeMethod(MATH_TAG, id, name, arity); - } else { - String name; - double x; - switch (id) { - case Id_E: x = Math.E; name = "E"; break; - case Id_PI: x = Math.PI; name = "PI"; break; - case Id_LN10: x = 2.302585092994046; name = "LN10"; break; - case Id_LN2: x = 0.6931471805599453; name = "LN2"; break; - case Id_LOG2E: x = 1.4426950408889634; name = "LOG2E"; break; - case Id_LOG10E: x = 0.4342944819032518; name = "LOG10E"; break; - case Id_SQRT1_2: x = 0.7071067811865476; name = "SQRT1_2"; break; - case Id_SQRT2: x = 1.4142135623730951; name = "SQRT2"; break; - default: throw new IllegalStateException(String.valueOf(id)); - } - initPrototypeValue(id, name, ScriptRuntime.wrapNumber(x), - DONTENUM | READONLY | PERMANENT); - } - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(MATH_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - double x; - int methodId = f.methodId(); - switch (methodId) { - case Id_toSource: - return "Math"; - - case Id_abs: - x = ScriptRuntime.toNumber(args, 0); - // abs(-0.0) should be 0.0, but -0.0 < 0.0 == false - x = (x == 0.0) ? 0.0 : (x < 0.0) ? -x : x; - break; - - case Id_acos: - case Id_asin: - x = ScriptRuntime.toNumber(args, 0); - if (x == x && -1.0 <= x && x <= 1.0) { - x = (methodId == Id_acos) ? Math.acos(x) : Math.asin(x); - } else { - x = Double.NaN; - } - break; - - case Id_atan: - x = ScriptRuntime.toNumber(args, 0); - x = Math.atan(x); - break; - - case Id_atan2: - x = ScriptRuntime.toNumber(args, 0); - x = Math.atan2(x, ScriptRuntime.toNumber(args, 1)); - break; - - case Id_ceil: - x = ScriptRuntime.toNumber(args, 0); - x = Math.ceil(x); - break; - - case Id_cos: - x = ScriptRuntime.toNumber(args, 0); - x = (x == Double.POSITIVE_INFINITY - || x == Double.NEGATIVE_INFINITY) - ? Double.NaN : Math.cos(x); - break; - - case Id_exp: - x = ScriptRuntime.toNumber(args, 0); - x = (x == Double.POSITIVE_INFINITY) ? x - : (x == Double.NEGATIVE_INFINITY) ? 0.0 - : Math.exp(x); - break; - - case Id_floor: - x = ScriptRuntime.toNumber(args, 0); - x = Math.floor(x); - break; - - case Id_log: - x = ScriptRuntime.toNumber(args, 0); - // Java's log(<0) = -Infinity; we need NaN - x = (x < 0) ? Double.NaN : Math.log(x); - break; - - case Id_max: - case Id_min: - x = (methodId == Id_max) - ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; - for (int i = 0; i != args.length; ++i) { - double d = ScriptRuntime.toNumber(args[i]); - if (d != d) { - x = d; // NaN - break; - } - if (methodId == Id_max) { - // if (x < d) x = d; does not work due to -0.0 >= +0.0 - x = Math.max(x, d); - } else { - x = Math.min(x, d); - } - } - break; - - case Id_pow: - x = ScriptRuntime.toNumber(args, 0); - x = js_pow(x, ScriptRuntime.toNumber(args, 1)); - break; - - case Id_random: - x = Math.random(); - break; - - case Id_round: - x = ScriptRuntime.toNumber(args, 0); - if (x == x && x != Double.POSITIVE_INFINITY - && x != Double.NEGATIVE_INFINITY) - { - // Round only finite x - long l = Math.round(x); - if (l != 0) { - x = l; - } else { - // We must propagate the sign of d into the result - if (x < 0.0) { - x = ScriptRuntime.negativeZero; - } else if (x != 0.0) { - x = 0.0; - } - } - } - break; - - case Id_sin: - x = ScriptRuntime.toNumber(args, 0); - x = (x == Double.POSITIVE_INFINITY - || x == Double.NEGATIVE_INFINITY) - ? Double.NaN : Math.sin(x); - break; - - case Id_sqrt: - x = ScriptRuntime.toNumber(args, 0); - x = Math.sqrt(x); - break; - - case Id_tan: - x = ScriptRuntime.toNumber(args, 0); - x = Math.tan(x); - break; - - default: throw new IllegalStateException(String.valueOf(methodId)); - } - return ScriptRuntime.wrapNumber(x); - } - - // See Ecma 15.8.2.13 - private double js_pow(double x, double y) { - double result; - if (y != y) { - // y is NaN, result is always NaN - result = y; - } else if (y == 0) { - // Java's pow(NaN, 0) = NaN; we need 1 - result = 1.0; - } else if (x == 0) { - // Many dirrerences from Java's Math.pow - if (1 / x > 0) { - result = (y > 0) ? 0 : Double.POSITIVE_INFINITY; - } else { - // x is -0, need to check if y is an odd integer - long y_long = (long)y; - if (y_long == y && (y_long & 0x1) != 0) { - result = (y > 0) ? -0.0 : Double.NEGATIVE_INFINITY; - } else { - result = (y > 0) ? 0.0 : Double.POSITIVE_INFINITY; - } - } - } else { - result = Math.pow(x, y); - if (result != result) { - // Check for broken Java implementations that gives NaN - // when they should return something else - if (y == Double.POSITIVE_INFINITY) { - if (x < -1.0 || 1.0 < x) { - result = Double.POSITIVE_INFINITY; - } else if (-1.0 < x && x < 1.0) { - result = 0; - } - } else if (y == Double.NEGATIVE_INFINITY) { - if (x < -1.0 || 1.0 < x) { - result = 0; - } else if (-1.0 < x && x < 1.0) { - result = Double.POSITIVE_INFINITY; - } - } else if (x == Double.POSITIVE_INFINITY) { - result = (y > 0) ? Double.POSITIVE_INFINITY : 0.0; - } else if (x == Double.NEGATIVE_INFINITY) { - long y_long = (long)y; - if (y_long == y && (y_long & 0x1) != 0) { - // y is odd integer - result = (y > 0) ? Double.NEGATIVE_INFINITY : -0.0; - } else { - result = (y > 0) ? Double.POSITIVE_INFINITY : 0.0; - } - } - } - } - return result; - } - -// #string_id_map# - - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2004-03-17 13:51:32 CET - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 1: if (s.charAt(0)=='E') {id=Id_E; break L0;} break L; - case 2: if (s.charAt(0)=='P' && s.charAt(1)=='I') {id=Id_PI; break L0;} break L; - case 3: switch (s.charAt(0)) { - case 'L': if (s.charAt(2)=='2' && s.charAt(1)=='N') {id=Id_LN2; break L0;} break L; - case 'a': if (s.charAt(2)=='s' && s.charAt(1)=='b') {id=Id_abs; break L0;} break L; - case 'c': if (s.charAt(2)=='s' && s.charAt(1)=='o') {id=Id_cos; break L0;} break L; - case 'e': if (s.charAt(2)=='p' && s.charAt(1)=='x') {id=Id_exp; break L0;} break L; - case 'l': if (s.charAt(2)=='g' && s.charAt(1)=='o') {id=Id_log; break L0;} break L; - case 'm': c=s.charAt(2); - if (c=='n') { if (s.charAt(1)=='i') {id=Id_min; break L0;} } - else if (c=='x') { if (s.charAt(1)=='a') {id=Id_max; break L0;} } - break L; - case 'p': if (s.charAt(2)=='w' && s.charAt(1)=='o') {id=Id_pow; break L0;} break L; - case 's': if (s.charAt(2)=='n' && s.charAt(1)=='i') {id=Id_sin; break L0;} break L; - case 't': if (s.charAt(2)=='n' && s.charAt(1)=='a') {id=Id_tan; break L0;} break L; - } break L; - case 4: switch (s.charAt(1)) { - case 'N': X="LN10";id=Id_LN10; break L; - case 'c': X="acos";id=Id_acos; break L; - case 'e': X="ceil";id=Id_ceil; break L; - case 'q': X="sqrt";id=Id_sqrt; break L; - case 's': X="asin";id=Id_asin; break L; - case 't': X="atan";id=Id_atan; break L; - } break L; - case 5: switch (s.charAt(0)) { - case 'L': X="LOG2E";id=Id_LOG2E; break L; - case 'S': X="SQRT2";id=Id_SQRT2; break L; - case 'a': X="atan2";id=Id_atan2; break L; - case 'f': X="floor";id=Id_floor; break L; - case 'r': X="round";id=Id_round; break L; - } break L; - case 6: c=s.charAt(0); - if (c=='L') { X="LOG10E";id=Id_LOG10E; } - else if (c=='r') { X="random";id=Id_random; } - break L; - case 7: X="SQRT1_2";id=Id_SQRT1_2; break L; - case 8: X="toSource";id=Id_toSource; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - } -// #/generated# - return id; - } - - private static final int - Id_toSource = 1, - Id_abs = 2, - Id_acos = 3, - Id_asin = 4, - Id_atan = 5, - Id_atan2 = 6, - Id_ceil = 7, - Id_cos = 8, - Id_exp = 9, - Id_floor = 10, - Id_log = 11, - Id_max = 12, - Id_min = 13, - Id_pow = 14, - Id_random = 15, - Id_round = 16, - Id_sin = 17, - Id_sqrt = 18, - Id_tan = 19, - - LAST_METHOD_ID = 19; - - private static final int - Id_E = LAST_METHOD_ID + 1, - Id_PI = LAST_METHOD_ID + 2, - Id_LN10 = LAST_METHOD_ID + 3, - Id_LN2 = LAST_METHOD_ID + 4, - Id_LOG2E = LAST_METHOD_ID + 5, - Id_LOG10E = LAST_METHOD_ID + 6, - Id_SQRT1_2 = LAST_METHOD_ID + 7, - Id_SQRT2 = LAST_METHOD_ID + 8, - - MAX_ID = LAST_METHOD_ID + 8; - -// #/string_id_map# -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeNumber.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeNumber.java deleted file mode 100644 index 8fc9fb0..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeNumber.java +++ /dev/null @@ -1,244 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class implements the Number native object. - * - * See ECMA 15.7. - * - * @author Norris Boyd - */ -final class NativeNumber extends IdScriptableObject -{ - static final long serialVersionUID = 3504516769741512101L; - - private static final Object NUMBER_TAG = new Object(); - - private static final int MAX_PRECISION = 100; - - static void init(Scriptable scope, boolean sealed) - { - NativeNumber obj = new NativeNumber(0.0); - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - private NativeNumber(double number) - { - doubleValue = number; - } - - public String getClassName() - { - return "Number"; - } - - protected void fillConstructorProperties(IdFunctionObject ctor) - { - final int attr = ScriptableObject.DONTENUM | - ScriptableObject.PERMANENT | - ScriptableObject.READONLY; - - ctor.defineProperty("NaN", ScriptRuntime.NaNobj, attr); - ctor.defineProperty("POSITIVE_INFINITY", - ScriptRuntime.wrapNumber(Double.POSITIVE_INFINITY), - attr); - ctor.defineProperty("NEGATIVE_INFINITY", - ScriptRuntime.wrapNumber(Double.NEGATIVE_INFINITY), - attr); - ctor.defineProperty("MAX_VALUE", - ScriptRuntime.wrapNumber(Double.MAX_VALUE), - attr); - ctor.defineProperty("MIN_VALUE", - ScriptRuntime.wrapNumber(Double.MIN_VALUE), - attr); - - super.fillConstructorProperties(ctor); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=1; s="constructor"; break; - case Id_toString: arity=1; s="toString"; break; - case Id_toLocaleString: arity=1; s="toLocaleString"; break; - case Id_toSource: arity=0; s="toSource"; break; - case Id_valueOf: arity=0; s="valueOf"; break; - case Id_toFixed: arity=1; s="toFixed"; break; - case Id_toExponential: arity=1; s="toExponential"; break; - case Id_toPrecision: arity=1; s="toPrecision"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(NUMBER_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(NUMBER_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - if (id == Id_constructor) { - double val = (args.length >= 1) - ? ScriptRuntime.toNumber(args[0]) : 0.0; - if (thisObj == null) { - // new Number(val) creates a new Number object. - return new NativeNumber(val); - } - // Number(val) converts val to a number value. - return ScriptRuntime.wrapNumber(val); - } - - // The rest of Number.prototype methods require thisObj to be Number - - if (!(thisObj instanceof NativeNumber)) - throw incompatibleCallError(f); - double value = ((NativeNumber)thisObj).doubleValue; - - switch (id) { - - case Id_toString: - case Id_toLocaleString: - { - // toLocaleString is just an alias for toString for now - int base = (args.length == 0) - ? 10 : ScriptRuntime.toInt32(args[0]); - return ScriptRuntime.numberToString(value, base); - } - - case Id_toSource: - return "(new Number("+ScriptRuntime.toString(value)+"))"; - - case Id_valueOf: - return ScriptRuntime.wrapNumber(value); - - case Id_toFixed: - return num_to(value, args, DToA.DTOSTR_FIXED, - DToA.DTOSTR_FIXED, -20, 0); - - case Id_toExponential: - return num_to(value, args, DToA.DTOSTR_STANDARD_EXPONENTIAL, - DToA.DTOSTR_EXPONENTIAL, 0, 1); - - case Id_toPrecision: - return num_to(value, args, DToA.DTOSTR_STANDARD, - DToA.DTOSTR_PRECISION, 1, 0); - - default: throw new IllegalArgumentException(String.valueOf(id)); - } - } - - public String toString() { - return ScriptRuntime.numberToString(doubleValue, 10); - } - - private static String num_to(double val, - Object[] args, - int zeroArgMode, int oneArgMode, - int precisionMin, int precisionOffset) - { - int precision; - if (args.length == 0) { - precision = 0; - oneArgMode = zeroArgMode; - } else { - /* We allow a larger range of precision than - ECMA requires; this is permitted by ECMA. */ - precision = ScriptRuntime.toInt32(args[0]); - if (precision < precisionMin || precision > MAX_PRECISION) { - String msg = ScriptRuntime.getMessage1( - "msg.bad.precision", ScriptRuntime.toString(args[0])); - throw ScriptRuntime.constructError("RangeError", msg); - } - } - StringBuffer sb = new StringBuffer(); - DToA.JS_dtostr(sb, oneArgMode, precision + precisionOffset, val); - return sb.toString(); - } - -// #string_id_map# - - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:15:50 EDT - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 7: c=s.charAt(0); - if (c=='t') { X="toFixed";id=Id_toFixed; } - else if (c=='v') { X="valueOf";id=Id_valueOf; } - break L; - case 8: c=s.charAt(3); - if (c=='o') { X="toSource";id=Id_toSource; } - else if (c=='t') { X="toString";id=Id_toString; } - break L; - case 11: c=s.charAt(0); - if (c=='c') { X="constructor";id=Id_constructor; } - else if (c=='t') { X="toPrecision";id=Id_toPrecision; } - break L; - case 13: X="toExponential";id=Id_toExponential; break L; - case 14: X="toLocaleString";id=Id_toLocaleString; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_constructor = 1, - Id_toString = 2, - Id_toLocaleString = 3, - Id_toSource = 4, - Id_valueOf = 5, - Id_toFixed = 6, - Id_toExponential = 7, - Id_toPrecision = 8, - MAX_PROTOTYPE_ID = 8; - -// #/string_id_map# - - private double doubleValue; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeObject.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeObject.java deleted file mode 100644 index 19aff63..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeObject.java +++ /dev/null @@ -1,316 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Bob Jervis - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class implements the Object native object. - * See ECMA 15.2. - * @author Norris Boyd - */ -public class NativeObject extends IdScriptableObject -{ - static final long serialVersionUID = -6345305608474346996L; - - private static final Object OBJECT_TAG = new Object(); - - static void init(Scriptable scope, boolean sealed) - { - NativeObject obj = new NativeObject(); - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - public String getClassName() - { - return "Object"; - } - - public String toString() - { - return ScriptRuntime.defaultObjectToString(this); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=1; s="constructor"; break; - case Id_toString: arity=0; s="toString"; break; - case Id_toLocaleString: arity=0; s="toLocaleString"; break; - case Id_valueOf: arity=0; s="valueOf"; break; - case Id_hasOwnProperty: arity=1; s="hasOwnProperty"; break; - case Id_propertyIsEnumerable: - arity=1; s="propertyIsEnumerable"; break; - case Id_isPrototypeOf: arity=1; s="isPrototypeOf"; break; - case Id_toSource: arity=0; s="toSource"; break; - case Id___defineGetter__: - arity=2; s="__defineGetter__"; break; - case Id___defineSetter__: - arity=2; s="__defineSetter__"; break; - case Id___lookupGetter__: - arity=1; s="__lookupGetter__"; break; - case Id___lookupSetter__: - arity=1; s="__lookupSetter__"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(OBJECT_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(OBJECT_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case Id_constructor: { - if (thisObj != null) { - // BaseFunction.construct will set up parent, proto - return f.construct(cx, scope, args); - } - if (args.length == 0 || args[0] == null - || args[0] == Undefined.instance) - { - return new NativeObject(); - } - return ScriptRuntime.toObject(cx, scope, args[0]); - } - - case Id_toLocaleString: // For now just alias toString - case Id_toString: { - if (cx.hasFeature(Context.FEATURE_TO_STRING_AS_SOURCE)) { - String s = ScriptRuntime.defaultObjectToSource(cx, scope, - thisObj, args); - int L = s.length(); - if (L != 0 && s.charAt(0) == '(' && s.charAt(L - 1) == ')') { - // Strip () that surrounds toSource - s = s.substring(1, L - 1); - } - return s; - } - return ScriptRuntime.defaultObjectToString(thisObj); - } - - case Id_valueOf: - return thisObj; - - case Id_hasOwnProperty: { - boolean result; - if (args.length == 0) { - result = false; - } else { - String s = ScriptRuntime.toStringIdOrIndex(cx, args[0]); - if (s == null) { - int index = ScriptRuntime.lastIndexResult(cx); - result = thisObj.has(index, thisObj); - } else { - result = thisObj.has(s, thisObj); - } - } - return ScriptRuntime.wrapBoolean(result); - } - - case Id_propertyIsEnumerable: { - boolean result; - if (args.length == 0) { - result = false; - } else { - String s = ScriptRuntime.toStringIdOrIndex(cx, args[0]); - if (s == null) { - int index = ScriptRuntime.lastIndexResult(cx); - result = thisObj.has(index, thisObj); - if (result && thisObj instanceof ScriptableObject) { - ScriptableObject so = (ScriptableObject)thisObj; - int attrs = so.getAttributes(index); - result = ((attrs & ScriptableObject.DONTENUM) == 0); - } - } else { - result = thisObj.has(s, thisObj); - if (result && thisObj instanceof ScriptableObject) { - ScriptableObject so = (ScriptableObject)thisObj; - int attrs = so.getAttributes(s); - result = ((attrs & ScriptableObject.DONTENUM) == 0); - } - } - } - return ScriptRuntime.wrapBoolean(result); - } - - case Id_isPrototypeOf: { - boolean result = false; - if (args.length != 0 && args[0] instanceof Scriptable) { - Scriptable v = (Scriptable) args[0]; - do { - v = v.getPrototype(); - if (v == thisObj) { - result = true; - break; - } - } while (v != null); - } - return ScriptRuntime.wrapBoolean(result); - } - - case Id_toSource: - return ScriptRuntime.defaultObjectToSource(cx, scope, thisObj, - args); - case Id___defineGetter__: - case Id___defineSetter__: - { - if (args.length < 2 || !(args[1] instanceof Callable)) { - Object badArg = (args.length >= 2 ? args[1] - : Undefined.instance); - throw ScriptRuntime.notFunctionError(badArg); - } - if (!(thisObj instanceof ScriptableObject)) { - throw Context.reportRuntimeError2( - "msg.extend.scriptable", - thisObj.getClass().getName(), - String.valueOf(args[0])); - } - ScriptableObject so = (ScriptableObject)thisObj; - String name = ScriptRuntime.toStringIdOrIndex(cx, args[0]); - int index = (name != null ? 0 - : ScriptRuntime.lastIndexResult(cx)); - Callable getterOrSetter = (Callable)args[1]; - boolean isSetter = (id == Id___defineSetter__); - so.setGetterOrSetter(name, index, getterOrSetter, isSetter); - if (so instanceof NativeArray) - ((NativeArray)so).setDenseOnly(false); - } - return Undefined.instance; - - case Id___lookupGetter__: - case Id___lookupSetter__: - { - if (args.length < 1 || - !(thisObj instanceof ScriptableObject)) - return Undefined.instance; - - ScriptableObject so = (ScriptableObject)thisObj; - String name = ScriptRuntime.toStringIdOrIndex(cx, args[0]); - int index = (name != null ? 0 - : ScriptRuntime.lastIndexResult(cx)); - boolean isSetter = (id == Id___lookupSetter__); - Object gs; - for (;;) { - gs = so.getGetterOrSetter(name, index, isSetter); - if (gs != null) - break; - // If there is no getter or setter for the object itself, - // how about the prototype? - Scriptable v = so.getPrototype(); - if (v == null) - break; - if (v instanceof ScriptableObject) - so = (ScriptableObject)v; - else - break; - } - if (gs != null) - return gs; - } - return Undefined.instance; - - default: - throw new IllegalArgumentException(String.valueOf(id)); - } - } - -// #string_id_map# - - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:15:55 EDT - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 7: X="valueOf";id=Id_valueOf; break L; - case 8: c=s.charAt(3); - if (c=='o') { X="toSource";id=Id_toSource; } - else if (c=='t') { X="toString";id=Id_toString; } - break L; - case 11: X="constructor";id=Id_constructor; break L; - case 13: X="isPrototypeOf";id=Id_isPrototypeOf; break L; - case 14: c=s.charAt(0); - if (c=='h') { X="hasOwnProperty";id=Id_hasOwnProperty; } - else if (c=='t') { X="toLocaleString";id=Id_toLocaleString; } - break L; - case 16: c=s.charAt(2); - if (c=='d') { - c=s.charAt(8); - if (c=='G') { X="__defineGetter__";id=Id___defineGetter__; } - else if (c=='S') { X="__defineSetter__";id=Id___defineSetter__; } - } - else if (c=='l') { - c=s.charAt(8); - if (c=='G') { X="__lookupGetter__";id=Id___lookupGetter__; } - else if (c=='S') { X="__lookupSetter__";id=Id___lookupSetter__; } - } - break L; - case 20: X="propertyIsEnumerable";id=Id_propertyIsEnumerable; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_constructor = 1, - Id_toString = 2, - Id_toLocaleString = 3, - Id_valueOf = 4, - Id_hasOwnProperty = 5, - Id_propertyIsEnumerable = 6, - Id_isPrototypeOf = 7, - Id_toSource = 8, - Id___defineGetter__ = 9, - Id___defineSetter__ = 10, - Id___lookupGetter__ = 11, - Id___lookupSetter__ = 12, - MAX_PROTOTYPE_ID = 12; - -// #/string_id_map# -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeScript.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeScript.java deleted file mode 100644 index 7b5191e..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeScript.java +++ /dev/null @@ -1,221 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Roger Lawrence - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * The JavaScript Script object. - * - * Note that the C version of the engine uses XDR as the format used - * by freeze and thaw. Since this depends on the internal format of - * structures in the C runtime, we cannot duplicate it. - * - * Since we cannot replace 'this' as a result of the compile method, - * will forward requests to execute to the nonnull 'script' field. - * - * @since 1.3 - * @author Norris Boyd - */ - -class NativeScript extends BaseFunction -{ - static final long serialVersionUID = -6795101161980121700L; - - private static final Object SCRIPT_TAG = new Object(); - - static void init(Scriptable scope, boolean sealed) - { - NativeScript obj = new NativeScript(null); - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - private NativeScript(Script script) - { - this.script = script; - } - - /** - * Returns the name of this JavaScript class, "Script". - */ - public String getClassName() - { - return "Script"; - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - if (script != null) { - return script.exec(cx, scope); - } - return Undefined.instance; - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) - { - throw Context.reportRuntimeError0("msg.script.is.not.constructor"); - } - - public int getLength() - { - return 0; - } - - public int getArity() - { - return 0; - } - - String decompile(int indent, int flags) - { - if (script instanceof NativeFunction) { - return ((NativeFunction)script).decompile(indent, flags); - } - return super.decompile(indent, flags); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=1; s="constructor"; break; - case Id_toString: arity=0; s="toString"; break; - case Id_exec: arity=0; s="exec"; break; - case Id_compile: arity=1; s="compile"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(SCRIPT_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(SCRIPT_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case Id_constructor: { - String source = (args.length == 0) - ? "" - : ScriptRuntime.toString(args[0]); - Script script = compile(cx, source); - NativeScript nscript = new NativeScript(script); - ScriptRuntime.setObjectProtoAndParent(nscript, scope); - return nscript; - } - - case Id_toString: { - NativeScript real = realThis(thisObj, f); - Script realScript = real.script; - if (realScript == null) { return ""; } - return cx.decompileScript(realScript, 0); - } - - case Id_exec: { - throw Context.reportRuntimeError1( - "msg.cant.call.indirect", "exec"); - } - - case Id_compile: { - NativeScript real = realThis(thisObj, f); - String source = ScriptRuntime.toString(args, 0); - real.script = compile(cx, source); - return real; - } - } - throw new IllegalArgumentException(String.valueOf(id)); - } - - private static NativeScript realThis(Scriptable thisObj, IdFunctionObject f) - { - if (!(thisObj instanceof NativeScript)) - throw incompatibleCallError(f); - return (NativeScript)thisObj; - } - - private static Script compile(Context cx, String source) - { - int[] linep = { 0 }; - String filename = Context.getSourcePositionFromStack(linep); - if (filename == null) { - filename = "<Script object>"; - linep[0] = 1; - } - ErrorReporter reporter; - reporter = DefaultErrorReporter.forEval(cx.getErrorReporter()); - return cx.compileString(source, null, reporter, filename, - linep[0], null); - } - -// #string_id_map# - - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:16:01 EDT - L0: { id = 0; String X = null; - L: switch (s.length()) { - case 4: X="exec";id=Id_exec; break L; - case 7: X="compile";id=Id_compile; break L; - case 8: X="toString";id=Id_toString; break L; - case 11: X="constructor";id=Id_constructor; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_constructor = 1, - Id_toString = 2, - Id_compile = 3, - Id_exec = 4, - MAX_PROTOTYPE_ID = 4; - -// #/string_id_map# - - private Script script; -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeString.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeString.java deleted file mode 100644 index 972415d..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeString.java +++ /dev/null @@ -1,983 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Tom Beauvais - * Norris Boyd - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.text.Collator; - -/** - * This class implements the String native object. - * - * See ECMA 15.5. - * - * String methods for dealing with regular expressions are - * ported directly from C. Latest port is from version 1.40.12.19 - * in the JSFUN13_BRANCH. - * - * @author Mike McCabe - * @author Norris Boyd - */ -final class NativeString extends IdScriptableObject -{ - static final long serialVersionUID = 920268368584188687L; - - private static final Object STRING_TAG = new Object(); - - static void init(Scriptable scope, boolean sealed) - { - NativeString obj = new NativeString(""); - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - private NativeString(String s) { - string = s; - } - - public String getClassName() { - return "String"; - } - - private static final int - Id_length = 1, - MAX_INSTANCE_ID = 1; - - protected int getMaxInstanceId() - { - return MAX_INSTANCE_ID; - } - - protected int findInstanceIdInfo(String s) - { - if (s.equals("length")) { - return instanceIdInfo(DONTENUM | READONLY | PERMANENT, Id_length); - } - return super.findInstanceIdInfo(s); - } - - protected String getInstanceIdName(int id) - { - if (id == Id_length) { return "length"; } - return super.getInstanceIdName(id); - } - - protected Object getInstanceIdValue(int id) - { - if (id == Id_length) { - return ScriptRuntime.wrapInt(string.length()); - } - return super.getInstanceIdValue(id); - } - - protected void fillConstructorProperties(IdFunctionObject ctor) - { - addIdFunctionProperty(ctor, STRING_TAG, ConstructorId_fromCharCode, - "fromCharCode", 1); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_charAt, "charAt", 2); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_charCodeAt, "charCodeAt", 2); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_indexOf, "indexOf", 2); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_lastIndexOf, "lastIndexOf", 2); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_split, "split", 3); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_substring, "substring", 3); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_toLowerCase, "toLowerCase", 1); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_toUpperCase, "toUpperCase", 1); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_substr, "substr", 3); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_concat, "concat", 2); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_slice, "slice", 3); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_equalsIgnoreCase, "equalsIgnoreCase", 2); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_match, "match", 2); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_search, "search", 2); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_replace, "replace", 2); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_localeCompare, "localeCompare", 2); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_toLocaleLowerCase, "toLocaleLowerCase", 1); - addIdFunctionProperty(ctor, STRING_TAG, - ConstructorId_fromCharCode, "fromCharCode", 1); - super.fillConstructorProperties(ctor); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=1; s="constructor"; break; - case Id_toString: arity=0; s="toString"; break; - case Id_toSource: arity=0; s="toSource"; break; - case Id_valueOf: arity=0; s="valueOf"; break; - case Id_charAt: arity=1; s="charAt"; break; - case Id_charCodeAt: arity=1; s="charCodeAt"; break; - case Id_indexOf: arity=1; s="indexOf"; break; - case Id_lastIndexOf: arity=1; s="lastIndexOf"; break; - case Id_split: arity=2; s="split"; break; - case Id_substring: arity=2; s="substring"; break; - case Id_toLowerCase: arity=0; s="toLowerCase"; break; - case Id_toUpperCase: arity=0; s="toUpperCase"; break; - case Id_substr: arity=2; s="substr"; break; - case Id_concat: arity=1; s="concat"; break; - case Id_slice: arity=2; s="slice"; break; - case Id_bold: arity=0; s="bold"; break; - case Id_italics: arity=0; s="italics"; break; - case Id_fixed: arity=0; s="fixed"; break; - case Id_strike: arity=0; s="strike"; break; - case Id_small: arity=0; s="small"; break; - case Id_big: arity=0; s="big"; break; - case Id_blink: arity=0; s="blink"; break; - case Id_sup: arity=0; s="sup"; break; - case Id_sub: arity=0; s="sub"; break; - case Id_fontsize: arity=0; s="fontsize"; break; - case Id_fontcolor: arity=0; s="fontcolor"; break; - case Id_link: arity=0; s="link"; break; - case Id_anchor: arity=0; s="anchor"; break; - case Id_equals: arity=1; s="equals"; break; - case Id_equalsIgnoreCase: arity=1; s="equalsIgnoreCase"; break; - case Id_match: arity=1; s="match"; break; - case Id_search: arity=1; s="search"; break; - case Id_replace: arity=1; s="replace"; break; - case Id_localeCompare: arity=1; s="localeCompare"; break; - case Id_toLocaleLowerCase: arity=0; s="toLocaleLowerCase"; break; - case Id_toLocaleUpperCase: arity=0; s="toLocaleUpperCase"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(STRING_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(STRING_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - again: - for(;;) { - switch (id) { - case ConstructorId_charAt: - case ConstructorId_charCodeAt: - case ConstructorId_indexOf: - case ConstructorId_lastIndexOf: - case ConstructorId_split: - case ConstructorId_substring: - case ConstructorId_toLowerCase: - case ConstructorId_toUpperCase: - case ConstructorId_substr: - case ConstructorId_concat: - case ConstructorId_slice: - case ConstructorId_equalsIgnoreCase: - case ConstructorId_match: - case ConstructorId_search: - case ConstructorId_replace: - case ConstructorId_localeCompare: - case ConstructorId_toLocaleLowerCase: { - thisObj = ScriptRuntime.toObject(scope, - ScriptRuntime.toString(args[0])); - Object[] newArgs = new Object[args.length-1]; - for (int i=0; i < newArgs.length; i++) - newArgs[i] = args[i+1]; - args = newArgs; - id = -id; - continue again; - } - - case ConstructorId_fromCharCode: { - int N = args.length; - if (N < 1) - return ""; - StringBuffer sb = new StringBuffer(N); - for (int i = 0; i != N; ++i) { - sb.append(ScriptRuntime.toUint16(args[i])); - } - return sb.toString(); - } - - case Id_constructor: { - String s = (args.length >= 1) - ? ScriptRuntime.toString(args[0]) : ""; - if (thisObj == null) { - // new String(val) creates a new String object. - return new NativeString(s); - } - // String(val) converts val to a string value. - return s; - } - - case Id_toString: - case Id_valueOf: - // ECMA 15.5.4.2: 'the toString function is not generic. - return realThis(thisObj, f).string; - - case Id_toSource: { - String s = realThis(thisObj, f).string; - return "(new String(\""+ScriptRuntime.escapeString(s)+"\"))"; - } - - case Id_charAt: - case Id_charCodeAt: { - // See ECMA 15.5.4.[4,5] - String target = ScriptRuntime.toString(thisObj); - double pos = ScriptRuntime.toInteger(args, 0); - if (pos < 0 || pos >= target.length()) { - if (id == Id_charAt) return ""; - else return ScriptRuntime.NaNobj; - } - char c = target.charAt((int)pos); - if (id == Id_charAt) return String.valueOf(c); - else return ScriptRuntime.wrapInt(c); - } - - case Id_indexOf: - return ScriptRuntime.wrapInt(js_indexOf( - ScriptRuntime.toString(thisObj), args)); - - case Id_lastIndexOf: - return ScriptRuntime.wrapInt(js_lastIndexOf( - ScriptRuntime.toString(thisObj), args)); - - case Id_split: - return js_split(cx, scope, ScriptRuntime.toString(thisObj), - args); - - case Id_substring: - return js_substring(cx, ScriptRuntime.toString(thisObj), args); - - case Id_toLowerCase: - // See ECMA 15.5.4.11 - return ScriptRuntime.toString(thisObj).toLowerCase(); - - case Id_toUpperCase: - // See ECMA 15.5.4.12 - return ScriptRuntime.toString(thisObj).toUpperCase(); - - case Id_substr: - return js_substr(ScriptRuntime.toString(thisObj), args); - - case Id_concat: - return js_concat(ScriptRuntime.toString(thisObj), args); - - case Id_slice: - return js_slice(ScriptRuntime.toString(thisObj), args); - - case Id_bold: - return tagify(thisObj, "b", null, null); - - case Id_italics: - return tagify(thisObj, "i", null, null); - - case Id_fixed: - return tagify(thisObj, "tt", null, null); - - case Id_strike: - return tagify(thisObj, "strike", null, null); - - case Id_small: - return tagify(thisObj, "small", null, null); - - case Id_big: - return tagify(thisObj, "big", null, null); - - case Id_blink: - return tagify(thisObj, "blink", null, null); - - case Id_sup: - return tagify(thisObj, "sup", null, null); - - case Id_sub: - return tagify(thisObj, "sub", null, null); - - case Id_fontsize: - return tagify(thisObj, "font", "size", args); - - case Id_fontcolor: - return tagify(thisObj, "font", "color", args); - - case Id_link: - return tagify(thisObj, "a", "href", args); - - case Id_anchor: - return tagify(thisObj, "a", "name", args); - - case Id_equals: - case Id_equalsIgnoreCase: { - String s1 = ScriptRuntime.toString(thisObj); - String s2 = ScriptRuntime.toString(args, 0); - return ScriptRuntime.wrapBoolean( - (id == Id_equals) ? s1.equals(s2) - : s1.equalsIgnoreCase(s2)); - } - - case Id_match: - case Id_search: - case Id_replace: - { - int actionType; - if (id == Id_match) { - actionType = RegExpProxy.RA_MATCH; - } else if (id == Id_search) { - actionType = RegExpProxy.RA_SEARCH; - } else { - actionType = RegExpProxy.RA_REPLACE; - } - return ScriptRuntime.checkRegExpProxy(cx). - action(cx, scope, thisObj, args, actionType); - } - // ECMA-262 1 5.5.4.9 - case Id_localeCompare: - { - // For now, create and configure a collator instance. I can't - // actually imagine that this'd be slower than caching them - // a la ClassCache, so we aren't trying to outsmart ourselves - // with a caching mechanism for now. - Collator collator = Collator.getInstance(cx.getLocale()); - collator.setStrength(Collator.IDENTICAL); - collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); - return ScriptRuntime.wrapNumber(collator.compare( - ScriptRuntime.toString(thisObj), - ScriptRuntime.toString(args, 0))); - } - case Id_toLocaleLowerCase: - { - return ScriptRuntime.toString(thisObj) - .toLowerCase(cx.getLocale()); - } - case Id_toLocaleUpperCase: - { - return ScriptRuntime.toString(thisObj) - .toUpperCase(cx.getLocale()); - } - } - throw new IllegalArgumentException(String.valueOf(id)); - } - } - - private static NativeString realThis(Scriptable thisObj, IdFunctionObject f) - { - if (!(thisObj instanceof NativeString)) - throw incompatibleCallError(f); - return (NativeString)thisObj; - } - - /* - * HTML composition aids. - */ - private static String tagify(Object thisObj, String tag, - String attribute, Object[] args) - { - String str = ScriptRuntime.toString(thisObj); - StringBuffer result = new StringBuffer(); - result.append('<'); - result.append(tag); - if (attribute != null) { - result.append(' '); - result.append(attribute); - result.append("=\""); - result.append(ScriptRuntime.toString(args, 0)); - result.append('"'); - } - result.append('>'); - result.append(str); - result.append("</"); - result.append(tag); - result.append('>'); - return result.toString(); - } - - public String toString() { - return string; - } - - /* Make array-style property lookup work for strings. - * XXX is this ECMA? A version check is probably needed. In js too. - */ - public Object get(int index, Scriptable start) { - if (0 <= index && index < string.length()) { - return string.substring(index, index + 1); - } - return super.get(index, start); - } - - public void put(int index, Scriptable start, Object value) { - if (0 <= index && index < string.length()) { - return; - } - super.put(index, start, value); - } - - /* - * - * See ECMA 15.5.4.6. Uses Java String.indexOf() - * OPT to add - BMH searching from jsstr.c. - */ - private static int js_indexOf(String target, Object[] args) { - String search = ScriptRuntime.toString(args, 0); - double begin = ScriptRuntime.toInteger(args, 1); - - if (begin > target.length()) { - return -1; - } else { - if (begin < 0) - begin = 0; - return target.indexOf(search, (int)begin); - } - } - - /* - * - * See ECMA 15.5.4.7 - * - */ - private static int js_lastIndexOf(String target, Object[] args) { - String search = ScriptRuntime.toString(args, 0); - double end = ScriptRuntime.toNumber(args, 1); - - if (end != end || end > target.length()) - end = target.length(); - else if (end < 0) - end = 0; - - return target.lastIndexOf(search, (int)end); - } - - /* - * Used by js_split to find the next split point in target, - * starting at offset ip and looking either for the given - * separator substring, or for the next re match. ip and - * matchlen must be reference variables (assumed to be arrays of - * length 1) so they can be updated in the leading whitespace or - * re case. - * - * Return -1 on end of string, >= 0 for a valid index of the next - * separator occurrence if found, or the string length if no - * separator is found. - */ - private static int find_split(Context cx, Scriptable scope, String target, - String separator, int version, - RegExpProxy reProxy, Scriptable re, - int[] ip, int[] matchlen, boolean[] matched, - String[][] parensp) - { - int i = ip[0]; - int length = target.length(); - - /* - * Perl4 special case for str.split(' '), only if the user has selected - * JavaScript1.2 explicitly. Split on whitespace, and skip leading w/s. - * Strange but true, apparently modeled after awk. - */ - if (version == Context.VERSION_1_2 && - re == null && separator.length() == 1 && separator.charAt(0) == ' ') - { - /* Skip leading whitespace if at front of str. */ - if (i == 0) { - while (i < length && Character.isWhitespace(target.charAt(i))) - i++; - ip[0] = i; - } - - /* Don't delimit whitespace at end of string. */ - if (i == length) - return -1; - - /* Skip over the non-whitespace chars. */ - while (i < length - && !Character.isWhitespace(target.charAt(i))) - i++; - - /* Now skip the next run of whitespace. */ - int j = i; - while (j < length && Character.isWhitespace(target.charAt(j))) - j++; - - /* Update matchlen to count delimiter chars. */ - matchlen[0] = j - i; - return i; - } - - /* - * Stop if past end of string. If at end of string, we will - * return target length, so that - * - * "ab,".split(',') => new Array("ab", "") - * - * and the resulting array converts back to the string "ab," - * for symmetry. NB: This differs from perl, which drops the - * trailing empty substring if the LIMIT argument is omitted. - */ - if (i > length) - return -1; - - /* - * Match a regular expression against the separator at or - * above index i. Return -1 at end of string instead of - * trying for a match, so we don't get stuck in a loop. - */ - if (re != null) { - return reProxy.find_split(cx, scope, target, separator, re, - ip, matchlen, matched, parensp); - } - - /* - * Deviate from ECMA by never splitting an empty string by any separator - * string into a non-empty array (an array of length 1 that contains the - * empty string). - */ - if (version != Context.VERSION_DEFAULT && version < Context.VERSION_1_3 - && length == 0) - return -1; - - /* - * Special case: if sep is the empty string, split str into - * one character substrings. Let our caller worry about - * whether to split once at end of string into an empty - * substring. - * - * For 1.2 compatibility, at the end of the string, we return the length as - * the result, and set the separator length to 1 -- this allows the caller - * to include an additional null string at the end of the substring list. - */ - if (separator.length() == 0) { - if (version == Context.VERSION_1_2) { - if (i == length) { - matchlen[0] = 1; - return i; - } - return i + 1; - } - return (i == length) ? -1 : i + 1; - } - - /* Punt to j.l.s.indexOf; return target length if separator is - * not found. - */ - if (ip[0] >= length) - return length; - - i = target.indexOf(separator, ip[0]); - - return (i != -1) ? i : length; - } - - /* - * See ECMA 15.5.4.8. Modified to match JS 1.2 - optionally takes - * a limit argument and accepts a regular expression as the split - * argument. - */ - private static Object js_split(Context cx, Scriptable scope, - String target, Object[] args) - { - // create an empty Array to return; - Scriptable top = getTopLevelScope(scope); - Scriptable result = ScriptRuntime.newObject(cx, top, "Array", null); - - // return an array consisting of the target if no separator given - // don't check against undefined, because we want - // 'fooundefinedbar'.split(void 0) to split to ['foo', 'bar'] - if (args.length < 1) { - result.put(0, result, target); - return result; - } - - // Use the second argument as the split limit, if given. - boolean limited = (args.length > 1) && (args[1] != Undefined.instance); - long limit = 0; // Initialize to avoid warning. - if (limited) { - /* Clamp limit between 0 and 1 + string length. */ - limit = ScriptRuntime.toUint32(args[1]); - if (limit > target.length()) - limit = 1 + target.length(); - } - - String separator = null; - int[] matchlen = new int[1]; - Scriptable re = null; - RegExpProxy reProxy = null; - if (args[0] instanceof Scriptable) { - reProxy = ScriptRuntime.getRegExpProxy(cx); - if (reProxy != null) { - Scriptable test = (Scriptable)args[0]; - if (reProxy.isRegExp(test)) { - re = test; - } - } - } - if (re == null) { - separator = ScriptRuntime.toString(args[0]); - matchlen[0] = separator.length(); - } - - // split target with separator or re - int[] ip = { 0 }; - int match; - int len = 0; - boolean[] matched = { false }; - String[][] parens = { null }; - int version = cx.getLanguageVersion(); - while ((match = find_split(cx, scope, target, separator, version, - reProxy, re, ip, matchlen, matched, parens)) - >= 0) - { - if ((limited && len >= limit) || (match > target.length())) - break; - - String substr; - if (target.length() == 0) - substr = target; - else - substr = target.substring(ip[0], match); - - result.put(len, result, substr); - len++; - /* - * Imitate perl's feature of including parenthesized substrings - * that matched part of the delimiter in the new array, after the - * split substring that was delimited. - */ - if (re != null && matched[0] == true) { - int size = parens[0].length; - for (int num = 0; num < size; num++) { - if (limited && len >= limit) - break; - result.put(len, result, parens[0][num]); - len++; - } - matched[0] = false; - } - ip[0] = match + matchlen[0]; - - if (version < Context.VERSION_1_3 - && version != Context.VERSION_DEFAULT) - { - /* - * Deviate from ECMA to imitate Perl, which omits a final - * split unless a limit argument is given and big enough. - */ - if (!limited && ip[0] == target.length()) - break; - } - } - return result; - } - - /* - * See ECMA 15.5.4.15 - */ - private static String js_substring(Context cx, String target, - Object[] args) - { - int length = target.length(); - double start = ScriptRuntime.toInteger(args, 0); - double end; - - if (start < 0) - start = 0; - else if (start > length) - start = length; - - if (args.length <= 1 || args[1] == Undefined.instance) { - end = length; - } else { - end = ScriptRuntime.toInteger(args[1]); - if (end < 0) - end = 0; - else if (end > length) - end = length; - - // swap if end < start - if (end < start) { - if (cx.getLanguageVersion() != Context.VERSION_1_2) { - double temp = start; - start = end; - end = temp; - } else { - // Emulate old JDK1.0 java.lang.String.substring() - end = start; - } - } - } - return target.substring((int)start, (int)end); - } - - int getLength() { - return string.length(); - } - - /* - * Non-ECMA methods. - */ - private static String js_substr(String target, Object[] args) { - if (args.length < 1) - return target; - - double begin = ScriptRuntime.toInteger(args[0]); - double end; - int length = target.length(); - - if (begin < 0) { - begin += length; - if (begin < 0) - begin = 0; - } else if (begin > length) { - begin = length; - } - - if (args.length == 1) { - end = length; - } else { - end = ScriptRuntime.toInteger(args[1]); - if (end < 0) - end = 0; - end += begin; - if (end > length) - end = length; - } - - return target.substring((int)begin, (int)end); - } - - /* - * Python-esque sequence operations. - */ - private static String js_concat(String target, Object[] args) { - int N = args.length; - if (N == 0) { return target; } - else if (N == 1) { - String arg = ScriptRuntime.toString(args[0]); - return target.concat(arg); - } - - // Find total capacity for the final string to avoid unnecessary - // re-allocations in StringBuffer - int size = target.length(); - String[] argsAsStrings = new String[N]; - for (int i = 0; i != N; ++i) { - String s = ScriptRuntime.toString(args[i]); - argsAsStrings[i] = s; - size += s.length(); - } - - StringBuffer result = new StringBuffer(size); - result.append(target); - for (int i = 0; i != N; ++i) { - result.append(argsAsStrings[i]); - } - return result.toString(); - } - - private static String js_slice(String target, Object[] args) { - if (args.length != 0) { - double begin = ScriptRuntime.toInteger(args[0]); - double end; - int length = target.length(); - if (begin < 0) { - begin += length; - if (begin < 0) - begin = 0; - } else if (begin > length) { - begin = length; - } - - if (args.length == 1) { - end = length; - } else { - end = ScriptRuntime.toInteger(args[1]); - if (end < 0) { - end += length; - if (end < 0) - end = 0; - } else if (end > length) { - end = length; - } - if (end < begin) - end = begin; - } - return target.substring((int)begin, (int)end); - } - return target; - } - -// #string_id_map# - - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2007-05-01 22:11:49 EDT - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 3: c=s.charAt(2); - if (c=='b') { if (s.charAt(0)=='s' && s.charAt(1)=='u') {id=Id_sub; break L0;} } - else if (c=='g') { if (s.charAt(0)=='b' && s.charAt(1)=='i') {id=Id_big; break L0;} } - else if (c=='p') { if (s.charAt(0)=='s' && s.charAt(1)=='u') {id=Id_sup; break L0;} } - break L; - case 4: c=s.charAt(0); - if (c=='b') { X="bold";id=Id_bold; } - else if (c=='l') { X="link";id=Id_link; } - break L; - case 5: switch (s.charAt(4)) { - case 'd': X="fixed";id=Id_fixed; break L; - case 'e': X="slice";id=Id_slice; break L; - case 'h': X="match";id=Id_match; break L; - case 'k': X="blink";id=Id_blink; break L; - case 'l': X="small";id=Id_small; break L; - case 't': X="split";id=Id_split; break L; - } break L; - case 6: switch (s.charAt(1)) { - case 'e': X="search";id=Id_search; break L; - case 'h': X="charAt";id=Id_charAt; break L; - case 'n': X="anchor";id=Id_anchor; break L; - case 'o': X="concat";id=Id_concat; break L; - case 'q': X="equals";id=Id_equals; break L; - case 't': X="strike";id=Id_strike; break L; - case 'u': X="substr";id=Id_substr; break L; - } break L; - case 7: switch (s.charAt(1)) { - case 'a': X="valueOf";id=Id_valueOf; break L; - case 'e': X="replace";id=Id_replace; break L; - case 'n': X="indexOf";id=Id_indexOf; break L; - case 't': X="italics";id=Id_italics; break L; - } break L; - case 8: c=s.charAt(4); - if (c=='r') { X="toString";id=Id_toString; } - else if (c=='s') { X="fontsize";id=Id_fontsize; } - else if (c=='u') { X="toSource";id=Id_toSource; } - break L; - case 9: c=s.charAt(0); - if (c=='f') { X="fontcolor";id=Id_fontcolor; } - else if (c=='s') { X="substring";id=Id_substring; } - break L; - case 10: X="charCodeAt";id=Id_charCodeAt; break L; - case 11: switch (s.charAt(2)) { - case 'L': X="toLowerCase";id=Id_toLowerCase; break L; - case 'U': X="toUpperCase";id=Id_toUpperCase; break L; - case 'n': X="constructor";id=Id_constructor; break L; - case 's': X="lastIndexOf";id=Id_lastIndexOf; break L; - } break L; - case 13: X="localeCompare";id=Id_localeCompare; break L; - case 16: X="equalsIgnoreCase";id=Id_equalsIgnoreCase; break L; - case 17: c=s.charAt(8); - if (c=='L') { X="toLocaleLowerCase";id=Id_toLocaleLowerCase; } - else if (c=='U') { X="toLocaleUpperCase";id=Id_toLocaleUpperCase; } - break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - ConstructorId_fromCharCode = -1, - - Id_constructor = 1, - Id_toString = 2, - Id_toSource = 3, - Id_valueOf = 4, - Id_charAt = 5, - Id_charCodeAt = 6, - Id_indexOf = 7, - Id_lastIndexOf = 8, - Id_split = 9, - Id_substring = 10, - Id_toLowerCase = 11, - Id_toUpperCase = 12, - Id_substr = 13, - Id_concat = 14, - Id_slice = 15, - Id_bold = 16, - Id_italics = 17, - Id_fixed = 18, - Id_strike = 19, - Id_small = 20, - Id_big = 21, - Id_blink = 22, - Id_sup = 23, - Id_sub = 24, - Id_fontsize = 25, - Id_fontcolor = 26, - Id_link = 27, - Id_anchor = 28, - Id_equals = 29, - Id_equalsIgnoreCase = 30, - Id_match = 31, - Id_search = 32, - Id_replace = 33, - Id_localeCompare = 34, - Id_toLocaleLowerCase = 35, - Id_toLocaleUpperCase = 36, - MAX_PROTOTYPE_ID = 36; - -// #/string_id_map# - - private static final int - ConstructorId_charAt = -Id_charAt, - ConstructorId_charCodeAt = -Id_charCodeAt, - ConstructorId_indexOf = -Id_indexOf, - ConstructorId_lastIndexOf = -Id_lastIndexOf, - ConstructorId_split = -Id_split, - ConstructorId_substring = -Id_substring, - ConstructorId_toLowerCase = -Id_toLowerCase, - ConstructorId_toUpperCase = -Id_toUpperCase, - ConstructorId_substr = -Id_substr, - ConstructorId_concat = -Id_concat, - ConstructorId_slice = -Id_slice, - ConstructorId_equalsIgnoreCase = -Id_equalsIgnoreCase, - ConstructorId_match = -Id_match, - ConstructorId_search = -Id_search, - ConstructorId_replace = -Id_replace, - ConstructorId_localeCompare = -Id_localeCompare, - ConstructorId_toLocaleLowerCase = -Id_toLocaleLowerCase; - - private String string; -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeWith.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeWith.java deleted file mode 100644 index 83683b2..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NativeWith.java +++ /dev/null @@ -1,207 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Serializable; - -/** - * This class implements the object lookup required for the - * <code>with</code> statement. - * It simply delegates every action to its prototype except - * for operations on its parent. - */ -public class NativeWith implements Scriptable, IdFunctionCall, Serializable { - - private static final long serialVersionUID = 1L; - - static void init(Scriptable scope, boolean sealed) - { - NativeWith obj = new NativeWith(); - - obj.setParentScope(scope); - obj.setPrototype(ScriptableObject.getObjectPrototype(scope)); - - IdFunctionObject ctor = new IdFunctionObject(obj, FTAG, Id_constructor, - "With", 0, scope); - ctor.markAsConstructor(obj); - if (sealed) { - ctor.sealObject(); - } - ctor.exportAsScopeProperty(); - } - - private NativeWith() { - } - - protected NativeWith(Scriptable parent, Scriptable prototype) { - this.parent = parent; - this.prototype = prototype; - } - - public String getClassName() { - return "With"; - } - - public boolean has(String id, Scriptable start) - { - return prototype.has(id, prototype); - } - - public boolean has(int index, Scriptable start) - { - return prototype.has(index, prototype); - } - - public Object get(String id, Scriptable start) - { - if (start == this) - start = prototype; - return prototype.get(id, start); - } - - public Object get(int index, Scriptable start) - { - if (start == this) - start = prototype; - return prototype.get(index, start); - } - - public void put(String id, Scriptable start, Object value) - { - if (start == this) - start = prototype; - prototype.put(id, start, value); - } - - public void put(int index, Scriptable start, Object value) - { - if (start == this) - start = prototype; - prototype.put(index, start, value); - } - - public void delete(String id) - { - prototype.delete(id); - } - - public void delete(int index) - { - prototype.delete(index); - } - - public Scriptable getPrototype() { - return prototype; - } - - public void setPrototype(Scriptable prototype) { - this.prototype = prototype; - } - - public Scriptable getParentScope() { - return parent; - } - - public void setParentScope(Scriptable parent) { - this.parent = parent; - } - - public Object[] getIds() { - return prototype.getIds(); - } - - public Object getDefaultValue(Class typeHint) { - return prototype.getDefaultValue(typeHint); - } - - public boolean hasInstance(Scriptable value) { - return prototype.hasInstance(value); - } - - /** - * Must return null to continue looping or the final collection result. - */ - protected Object updateDotQuery(boolean value) - { - // NativeWith itself does not support it - throw new IllegalStateException(); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (f.hasTag(FTAG)) { - if (f.methodId() == Id_constructor) { - throw Context.reportRuntimeError1("msg.cant.call.indirect", "With"); - } - } - throw f.unknown(); - } - - static boolean isWithFunction(Object functionObj) - { - if (functionObj instanceof IdFunctionObject) { - IdFunctionObject f = (IdFunctionObject)functionObj; - return f.hasTag(FTAG) && f.methodId() == Id_constructor; - } - return false; - } - - static Object newWithSpecial(Context cx, Scriptable scope, Object[] args) - { - ScriptRuntime.checkDeprecated(cx, "With"); - scope = ScriptableObject.getTopLevelScope(scope); - NativeWith thisObj = new NativeWith(); - thisObj.setPrototype(args.length == 0 - ? ScriptableObject.getClassPrototype(scope, - "Object") - : ScriptRuntime.toObject(cx, scope, args[0])); - thisObj.setParentScope(scope); - return thisObj; - } - - private static final Object FTAG = new Object(); - - private static final int - Id_constructor = 1; - - protected Scriptable prototype; - protected Scriptable parent; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Node.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Node.java deleted file mode 100644 index 4298388..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Node.java +++ /dev/null @@ -1,1394 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Roshan James - * Roger Lawrence - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.util.Map; -import java.util.LinkedHashMap; -import java.util.Iterator; -import java.util.Collections; - -/** - * This class implements the root of the intermediate representation. - * - * @author Norris Boyd - * @author Mike McCabe - */ - -public class Node -{ - public static final int - FUNCTION_PROP = 1, - LOCAL_PROP = 2, - LOCAL_BLOCK_PROP = 3, - REGEXP_PROP = 4, - CASEARRAY_PROP = 5, - /* - the following properties are defined and manipulated by the - optimizer - - TARGETBLOCK_PROP - the block referenced by a branch node - VARIABLE_PROP - the variable referenced by a BIND or NAME node - ISNUMBER_PROP - this node generates code on Number children and - delivers a Number result (as opposed to Objects) - DIRECTCALL_PROP - this call node should emit code to test the function - object against the known class and call diret if it - matches. - */ - - TARGETBLOCK_PROP = 6, - VARIABLE_PROP = 7, - ISNUMBER_PROP = 8, - DIRECTCALL_PROP = 9, - SPECIALCALL_PROP = 10, - SKIP_INDEXES_PROP = 11, // array of skipped indexes of array literal - OBJECT_IDS_PROP = 12, // array of properties for object literal - INCRDECR_PROP = 13, // pre or post type of increment/decerement - CATCH_SCOPE_PROP = 14, // index of catch scope block in catch - LABEL_ID_PROP = 15, // label id: code generation uses it - MEMBER_TYPE_PROP = 16, // type of element access operation - NAME_PROP = 17, // property name - CONTROL_BLOCK_PROP = 18, // flags a control block that can drop off - PARENTHESIZED_PROP = 19, // expression is parenthesized - GENERATOR_END_PROP = 20, - DESTRUCTURING_ARRAY_LENGTH = 21, - DESTRUCTURING_NAMES= 22, - LAST_PROP = 22; - - // values of ISNUMBER_PROP to specify - // which of the children are Number types - public static final int - BOTH = 0, - LEFT = 1, - RIGHT = 2; - - public static final int // values for SPECIALCALL_PROP - NON_SPECIALCALL = 0, - SPECIALCALL_EVAL = 1, - SPECIALCALL_WITH = 2; - - public static final int // flags for INCRDECR_PROP - DECR_FLAG = 0x1, - POST_FLAG = 0x2; - - public static final int // flags for MEMBER_TYPE_PROP - PROPERTY_FLAG = 0x1, // property access: element is valid name - ATTRIBUTE_FLAG = 0x2, // x.@y or x..@y - DESCENDANTS_FLAG = 0x4; // x..y or x..@i - - private static class NumberNode extends Node - { - NumberNode(double number) - { - super(Token.NUMBER); - this.number = number; - } - - double number; - } - - private static class StringNode extends Node - { - StringNode(int type, String str) { - super(type); - this.str = str; - } - - String str; - Node.Scope scope; - } - - public static class Jump extends Node - { - public Jump(int type) - { - super(type); - } - - Jump(int type, int lineno) - { - super(type, lineno); - } - - Jump(int type, Node child) - { - super(type, child); - } - - Jump(int type, Node child, int lineno) - { - super(type, child, lineno); - } - - public final Jump getJumpStatement() - { - if (!(type == Token.BREAK || type == Token.CONTINUE)) Kit.codeBug(); - return jumpNode; - } - - public final void setJumpStatement(Jump jumpStatement) - { - if (!(type == Token.BREAK || type == Token.CONTINUE)) Kit.codeBug(); - if (jumpStatement == null) Kit.codeBug(); - if (this.jumpNode != null) Kit.codeBug(); //only once - this.jumpNode = jumpStatement; - } - - public final Node getDefault() - { - if (!(type == Token.SWITCH)) Kit.codeBug(); - return target2; - } - - public final void setDefault(Node defaultTarget) - { - if (!(type == Token.SWITCH)) Kit.codeBug(); - if (defaultTarget.type != Token.TARGET) Kit.codeBug(); - if (target2 != null) Kit.codeBug(); //only once - target2 = defaultTarget; - } - - public final Node getFinally() - { - if (!(type == Token.TRY)) Kit.codeBug(); - return target2; - } - - public final void setFinally(Node finallyTarget) - { - if (!(type == Token.TRY)) Kit.codeBug(); - if (finallyTarget.type != Token.TARGET) Kit.codeBug(); - if (target2 != null) Kit.codeBug(); //only once - target2 = finallyTarget; - } - - public final Jump getLoop() - { - if (!(type == Token.LABEL)) Kit.codeBug(); - return jumpNode; - } - - public final void setLoop(Jump loop) - { - if (!(type == Token.LABEL)) Kit.codeBug(); - if (loop == null) Kit.codeBug(); - if (jumpNode != null) Kit.codeBug(); //only once - jumpNode = loop; - } - - public final Node getContinue() - { - if (type != Token.LOOP) Kit.codeBug(); - return target2; - } - - public final void setContinue(Node continueTarget) - { - if (type != Token.LOOP) Kit.codeBug(); - if (continueTarget.type != Token.TARGET) Kit.codeBug(); - if (target2 != null) Kit.codeBug(); //only once - target2 = continueTarget; - } - - public Node target; - private Node target2; - private Jump jumpNode; - } - - static class Symbol { - Symbol(int declType, String name) { - this.declType = declType; - this.name = name; - this.index = -1; - } - /** - * One of Token.FUNCTION, Token.LP (for parameters), Token.VAR, - * Token.LET, or Token.CONST - */ - int declType; - int index; - String name; - Node.Scope containingTable; - } - - static class Scope extends Jump { - public Scope(int nodeType) { - super(nodeType); - } - - public Scope(int nodeType, int lineno) { - super(nodeType, lineno); - } - - public Scope(int nodeType, Node n, int lineno) { - super(nodeType, n, lineno); - } - - /* - * Creates a new scope node, moving symbol table information - * from "scope" to the new node, and making "scope" a nested - * scope contained by the new node. - * Useful for injecting a new scope in a scope chain. - */ - public static Scope splitScope(Scope scope) { - Scope result = new Scope(scope.getType()); - result.symbolTable = scope.symbolTable; - scope.symbolTable = null; - result.parent = scope.parent; - scope.parent = result; - result.top = scope.top; - return result; - } - - public static void joinScopes(Scope source, Scope dest) { - source.ensureSymbolTable(); - dest.ensureSymbolTable(); - if (!Collections.disjoint(source.symbolTable.keySet(), - dest.symbolTable.keySet())) - { - throw Kit.codeBug(); - } - dest.symbolTable.putAll(source.symbolTable); - } - - public void setParent(Scope parent) { - this.parent = parent; - this.top = parent == null ? (ScriptOrFnNode)this : parent.top; - } - - public Scope getParentScope() { - return parent; - } - - public Scope getDefiningScope(String name) { - for (Scope sn=this; sn != null; sn = sn.parent) { - if (sn.symbolTable == null) - continue; - if (sn.symbolTable.containsKey(name)) - return sn; - } - return null; - } - - public Symbol getSymbol(String name) { - return symbolTable == null ? null : symbolTable.get(name); - } - - public void putSymbol(String name, Symbol symbol) { - ensureSymbolTable(); - symbolTable.put(name, symbol); - symbol.containingTable = this; - top.addSymbol(symbol); - } - - public Map<String,Symbol> getSymbolTable() { - return symbolTable; - } - - private void ensureSymbolTable() { - if (symbolTable == null) { - symbolTable = new LinkedHashMap<String,Symbol>(5); - } - } - - // Use LinkedHashMap so that the iteration order is the insertion order - protected LinkedHashMap<String,Symbol> symbolTable; - private Scope parent; - private ScriptOrFnNode top; - } - - private static class PropListItem - { - PropListItem next; - int type; - int intValue; - Object objectValue; - } - - - public Node(int nodeType) { - type = nodeType; - } - - public Node(int nodeType, Node child) { - type = nodeType; - first = last = child; - child.next = null; - } - - public Node(int nodeType, Node left, Node right) { - type = nodeType; - first = left; - last = right; - left.next = right; - right.next = null; - } - - public Node(int nodeType, Node left, Node mid, Node right) { - type = nodeType; - first = left; - last = right; - left.next = mid; - mid.next = right; - right.next = null; - } - - public Node(int nodeType, int line) { - type = nodeType; - lineno = line; - } - - public Node(int nodeType, Node child, int line) { - this(nodeType, child); - lineno = line; - } - - public Node(int nodeType, Node left, Node right, int line) { - this(nodeType, left, right); - lineno = line; - } - - public Node(int nodeType, Node left, Node mid, Node right, int line) { - this(nodeType, left, mid, right); - lineno = line; - } - - public static Node newNumber(double number) { - return new NumberNode(number); - } - - public static Node newString(String str) { - return new StringNode(Token.STRING, str); - } - - public static Node newString(int type, String str) { - return new StringNode(type, str); - } - - public int getType() { - return type; - } - - public void setType(int type) { - this.type = type; - } - - public boolean hasChildren() { - return first != null; - } - - public Node getFirstChild() { - return first; - } - - public Node getLastChild() { - return last; - } - - public Node getNext() { - return next; - } - - public Node getChildBefore(Node child) { - if (child == first) - return null; - Node n = first; - while (n.next != child) { - n = n.next; - if (n == null) - throw new RuntimeException("node is not a child"); - } - return n; - } - - public Node getLastSibling() { - Node n = this; - while (n.next != null) { - n = n.next; - } - return n; - } - - public void addChildToFront(Node child) { - child.next = first; - first = child; - if (last == null) { - last = child; - } - } - - public void addChildToBack(Node child) { - child.next = null; - if (last == null) { - first = last = child; - return; - } - last.next = child; - last = child; - } - - public void addChildrenToFront(Node children) { - Node lastSib = children.getLastSibling(); - lastSib.next = first; - first = children; - if (last == null) { - last = lastSib; - } - } - - public void addChildrenToBack(Node children) { - if (last != null) { - last.next = children; - } - last = children.getLastSibling(); - if (first == null) { - first = children; - } - } - - /** - * Add 'child' before 'node'. - */ - public void addChildBefore(Node newChild, Node node) { - if (newChild.next != null) - throw new RuntimeException( - "newChild had siblings in addChildBefore"); - if (first == node) { - newChild.next = first; - first = newChild; - return; - } - Node prev = getChildBefore(node); - addChildAfter(newChild, prev); - } - - /** - * Add 'child' after 'node'. - */ - public void addChildAfter(Node newChild, Node node) { - if (newChild.next != null) - throw new RuntimeException( - "newChild had siblings in addChildAfter"); - newChild.next = node.next; - node.next = newChild; - if (last == node) - last = newChild; - } - - public void removeChild(Node child) { - Node prev = getChildBefore(child); - if (prev == null) - first = first.next; - else - prev.next = child.next; - if (child == last) last = prev; - child.next = null; - } - - public void replaceChild(Node child, Node newChild) { - newChild.next = child.next; - if (child == first) { - first = newChild; - } else { - Node prev = getChildBefore(child); - prev.next = newChild; - } - if (child == last) - last = newChild; - child.next = null; - } - - public void replaceChildAfter(Node prevChild, Node newChild) { - Node child = prevChild.next; - newChild.next = child.next; - prevChild.next = newChild; - if (child == last) - last = newChild; - child.next = null; - } - - private static final String propToString(int propType) - { - if (Token.printTrees) { - // If Context.printTrees is false, the compiler - // can remove all these strings. - switch (propType) { - case FUNCTION_PROP: return "function"; - case LOCAL_PROP: return "local"; - case LOCAL_BLOCK_PROP: return "local_block"; - case REGEXP_PROP: return "regexp"; - case CASEARRAY_PROP: return "casearray"; - - case TARGETBLOCK_PROP: return "targetblock"; - case VARIABLE_PROP: return "variable"; - case ISNUMBER_PROP: return "isnumber"; - case DIRECTCALL_PROP: return "directcall"; - - case SPECIALCALL_PROP: return "specialcall"; - case SKIP_INDEXES_PROP: return "skip_indexes"; - case OBJECT_IDS_PROP: return "object_ids_prop"; - case INCRDECR_PROP: return "incrdecr_prop"; - case CATCH_SCOPE_PROP: return "catch_scope_prop"; - case LABEL_ID_PROP: return "label_id_prop"; - case MEMBER_TYPE_PROP: return "member_type_prop"; - case NAME_PROP: return "name_prop"; - case CONTROL_BLOCK_PROP: return "control_block_prop"; - case PARENTHESIZED_PROP: return "parenthesized_prop"; - case GENERATOR_END_PROP: return "generator_end"; - case DESTRUCTURING_ARRAY_LENGTH: - return "destructuring_array_length"; - case DESTRUCTURING_NAMES:return "destructuring_names"; - - default: Kit.codeBug(); - } - } - return null; - } - - private PropListItem lookupProperty(int propType) - { - PropListItem x = propListHead; - while (x != null && propType != x.type) { - x = x.next; - } - return x; - } - - private PropListItem ensureProperty(int propType) - { - PropListItem item = lookupProperty(propType); - if (item == null) { - item = new PropListItem(); - item.type = propType; - item.next = propListHead; - propListHead = item; - } - return item; - } - - public void removeProp(int propType) - { - PropListItem x = propListHead; - if (x != null) { - PropListItem prev = null; - while (x.type != propType) { - prev = x; - x = x.next; - if (x == null) { return; } - } - if (prev == null) { - propListHead = x.next; - } else { - prev.next = x.next; - } - } - } - - public Object getProp(int propType) - { - PropListItem item = lookupProperty(propType); - if (item == null) { return null; } - return item.objectValue; - } - - public int getIntProp(int propType, int defaultValue) - { - PropListItem item = lookupProperty(propType); - if (item == null) { return defaultValue; } - return item.intValue; - } - - public int getExistingIntProp(int propType) - { - PropListItem item = lookupProperty(propType); - if (item == null) { Kit.codeBug(); } - return item.intValue; - } - - public void putProp(int propType, Object prop) - { - if (prop == null) { - removeProp(propType); - } else { - PropListItem item = ensureProperty(propType); - item.objectValue = prop; - } - } - - public void putIntProp(int propType, int prop) - { - PropListItem item = ensureProperty(propType); - item.intValue = prop; - } - - public int getLineno() { - return lineno; - } - - /** Can only be called when <tt>getType() == Token.NUMBER</tt> */ - public final double getDouble() { - return ((NumberNode)this).number; - } - - public final void setDouble(double number) { - ((NumberNode)this).number = number; - } - - /** Can only be called when node has String context. */ - public final String getString() { - return ((StringNode)this).str; - } - - /** Can only be called when node has String context. */ - public final void setString(String s) { - if (s == null) Kit.codeBug(); - ((StringNode)this).str = s; - } - - /** Can only be called when node has String context. */ - public final Scope getScope() { - return ((StringNode)this).scope; - } - - /** Can only be called when node has String context. */ - public final void setScope(Scope s) { - if (s == null) Kit.codeBug(); - if (!(this instanceof StringNode)) { - throw Kit.codeBug(); - } - ((StringNode)this).scope = s; - } - - public static Node newTarget() - { - return new Node(Token.TARGET); - } - - public final int labelId() - { - if (type != Token.TARGET && type != Token.YIELD) Kit.codeBug(); - return getIntProp(LABEL_ID_PROP, -1); - } - - public void labelId(int labelId) - { - if (type != Token.TARGET && type != Token.YIELD) Kit.codeBug(); - putIntProp(LABEL_ID_PROP, labelId); - } - - - /** - * Does consistent-return analysis on the function body when strict mode is - * enabled. - * - * function (x) { return (x+1) } - * is ok, but - * function (x) { if (x < 0) return (x+1); } - * is not becuase the function can potentially return a value when the - * condition is satisfied and if not, the function does not explicitly - * return value. - * - * This extends to checking mismatches such as "return" and "return <value>" - * used in the same function. Warnings are not emitted if inconsistent - * returns exist in code that can be statically shown to be unreachable. - * Ex. - * function (x) { while (true) { ... if (..) { return value } ... } } - * emits no warning. However if the loop had a break statement, then a - * warning would be emitted. - * - * The consistency analysis looks at control structures such as loops, ifs, - * switch, try-catch-finally blocks, examines the reachable code paths and - * warns the user about an inconsistent set of termination possibilities. - * - * Caveat: Since the parser flattens many control structures into almost - * straight-line code with gotos, it makes such analysis hard. Hence this - * analyser is written to taken advantage of patterns of code generated by - * the parser (for loops, try blocks and such) and does not do a full - * control flow analysis of the gotos and break/continue statements. - * Future changes to the parser will affect this analysis. - */ - - /** - * These flags enumerate the possible ways a statement/function can - * terminate. These flags are used by endCheck() and by the Parser to - * detect inconsistent return usage. - * - * END_UNREACHED is reserved for code paths that are assumed to always be - * able to execute (example: throw, continue) - * - * END_DROPS_OFF indicates if the statement can transfer control to the - * next one. Statement such as return dont. A compound statement may have - * some branch that drops off control to the next statement. - * - * END_RETURNS indicates that the statement can return (without arguments) - * END_RETURNS_VALUE indicates that the statement can return a value. - * - * A compound statement such as - * if (condition) { - * return value; - * } - * Will be detected as (END_DROPS_OFF | END_RETURN_VALUE) by endCheck() - */ - static final int END_UNREACHED = 0; - static final int END_DROPS_OFF = 1; - static final int END_RETURNS = 2; - static final int END_RETURNS_VALUE = 4; - static final int END_YIELDS = 8; - - /** - * Checks that every return usage in a function body is consistent with the - * requirements of strict-mode. - * @return true if the function satisfies strict mode requirement. - */ - public boolean hasConsistentReturnUsage() - { - int n = endCheck(); - return (n & END_RETURNS_VALUE) == 0 || - (n & (END_DROPS_OFF|END_RETURNS|END_YIELDS)) == 0; - } - - /** - * Returns in the then and else blocks must be consistent with each other. - * If there is no else block, then the return statement can fall through. - * @return logical OR of END_* flags - */ - private int endCheckIf() - { - Node th, el; - int rv = END_UNREACHED; - - th = next; - el = ((Jump)this).target; - - rv = th.endCheck(); - - if (el != null) - rv |= el.endCheck(); - else - rv |= END_DROPS_OFF; - - return rv; - } - - /** - * Consistency of return statements is checked between the case statements. - * If there is no default, then the switch can fall through. If there is a - * default,we check to see if all code paths in the default return or if - * there is a code path that can fall through. - * @return logical OR of END_* flags - */ - private int endCheckSwitch() - { - Node n; - int rv = END_UNREACHED; - - // examine the cases - for (n = first.next; n != null; n = n.next) - { - if (n.type == Token.CASE) { - rv |= ((Jump)n).target.endCheck(); - } else - break; - } - - // we don't care how the cases drop into each other - rv &= ~END_DROPS_OFF; - - // examine the default - n = ((Jump)this).getDefault(); - if (n != null) - rv |= n.endCheck(); - else - rv |= END_DROPS_OFF; - - // remove the switch block - rv |= getIntProp(CONTROL_BLOCK_PROP, END_UNREACHED); - - return rv; - } - - /** - * If the block has a finally, return consistency is checked in the - * finally block. If all code paths in the finally returns, then the - * returns in the try-catch blocks don't matter. If there is a code path - * that does not return or if there is no finally block, the returns - * of the try and catch blocks are checked for mismatch. - * @return logical OR of END_* flags - */ - private int endCheckTry() - { - Node n; - int rv = END_UNREACHED; - - // check the finally if it exists - n = ((Jump)this).getFinally(); - if(n != null) { - rv = n.next.first.endCheck(); - } else { - rv = END_DROPS_OFF; - } - - // if the finally block always returns, then none of the returns - // in the try or catch blocks matter - if ((rv & END_DROPS_OFF) != 0) { - rv &= ~END_DROPS_OFF; - - // examine the try block - rv |= first.endCheck(); - - // check each catch block - n = ((Jump)this).target; - if (n != null) - { - // point to the first catch_scope - for (n = n.next.first; n != null; n = n.next.next) - { - // check the block of user code in the catch_scope - rv |= n.next.first.next.first.endCheck(); - } - } - } - - return rv; - } - - /** - * Return statement in the loop body must be consistent. The default - * assumption for any kind of a loop is that it will eventually terminate. - * The only exception is a loop with a constant true condition. Code that - * follows such a loop is examined only if one can statically determine - * that there is a break out of the loop. - * for(<> ; <>; <>) {} - * for(<> in <> ) {} - * while(<>) { } - * do { } while(<>) - * @return logical OR of END_* flags - */ - private int endCheckLoop() - { - Node n; - int rv = END_UNREACHED; - - // To find the loop body, we look at the second to last node of the - // loop node, which should be the predicate that the loop should - // satisfy. - // The target of the predicate is the loop-body for all 4 kinds of - // loops. - for (n = first; n.next != last; n = n.next) { - /* skip */ - } - if (n.type != Token.IFEQ) - return END_DROPS_OFF; - - // The target's next is the loop body block - rv = ((Jump)n).target.next.endCheck(); - - // check to see if the loop condition is true - if (n.first.type == Token.TRUE) - rv &= ~END_DROPS_OFF; - - // look for effect of breaks - rv |= getIntProp(CONTROL_BLOCK_PROP, END_UNREACHED); - - return rv; - } - - - /** - * A general block of code is examined statement by statement. If any - * statement (even compound ones) returns in all branches, then subsequent - * statements are not examined. - * @return logical OR of END_* flags - */ - private int endCheckBlock() - { - Node n; - int rv = END_DROPS_OFF; - - // check each statment and if the statement can continue onto the next - // one, then check the next statement - for (n=first; ((rv & END_DROPS_OFF) != 0) && n != null; n = n.next) - { - rv &= ~END_DROPS_OFF; - rv |= n.endCheck(); - } - return rv; - } - - /** - * A labelled statement implies that there maybe a break to the label. The - * function processes the labelled statement and then checks the - * CONTROL_BLOCK_PROP property to see if there is ever a break to the - * particular label. - * @return logical OR of END_* flags - */ - private int endCheckLabel() - { - int rv = END_UNREACHED; - - rv = next.endCheck(); - rv |= getIntProp(CONTROL_BLOCK_PROP, END_UNREACHED); - - return rv; - } - - /** - * When a break is encountered annotate the statement being broken - * out of by setting its CONTROL_BLOCK_PROP property. - * @return logical OR of END_* flags - */ - private int endCheckBreak() - { - Node n = ((Jump) this).jumpNode; - n.putIntProp(CONTROL_BLOCK_PROP, END_DROPS_OFF); - return END_UNREACHED; - } - - /** - * endCheck() examines the body of a function, doing a basic reachability - * analysis and returns a combination of flags END_* flags that indicate - * how the function execution can terminate. These constitute only the - * pessimistic set of termination conditions. It is possible that at - * runtime certain code paths will never be actually taken. Hence this - * analysis will flag errors in cases where there may not be errors. - * @return logical OR of END_* flags - */ - private int endCheck() - { - switch(type) - { - case Token.BREAK: - return endCheckBreak(); - - case Token.EXPR_VOID: - if (this.first != null) - return first.endCheck(); - return END_DROPS_OFF; - - case Token.YIELD: - return END_YIELDS; - - case Token.CONTINUE: - case Token.THROW: - return END_UNREACHED; - - case Token.RETURN: - if (this.first != null) - return END_RETURNS_VALUE; - else - return END_RETURNS; - - case Token.TARGET: - if (next != null) - return next.endCheck(); - else - return END_DROPS_OFF; - - case Token.LOOP: - return endCheckLoop(); - - case Token.LOCAL_BLOCK: - case Token.BLOCK: - // there are several special kinds of blocks - if (first == null) - return END_DROPS_OFF; - - switch(first.type) { - case Token.LABEL: - return first.endCheckLabel(); - - case Token.IFNE: - return first.endCheckIf(); - - case Token.SWITCH: - return first.endCheckSwitch(); - - case Token.TRY: - return first.endCheckTry(); - - default: - return endCheckBlock(); - } - - default: - return END_DROPS_OFF; - } - } - - public boolean hasSideEffects() - { - switch (type) { - case Token.EXPR_VOID: - case Token.COMMA: - if (last != null) - return last.hasSideEffects(); - else - return true; - - case Token.HOOK: - if (first == null || - first.next == null || - first.next.next == null) - Kit.codeBug(); - return first.next.hasSideEffects() && - first.next.next.hasSideEffects(); - - case Token.ERROR: // Avoid cascaded error messages - case Token.EXPR_RESULT: - case Token.ASSIGN: - case Token.ASSIGN_ADD: - case Token.ASSIGN_SUB: - case Token.ASSIGN_MUL: - case Token.ASSIGN_DIV: - case Token.ASSIGN_MOD: - case Token.ASSIGN_BITOR: - case Token.ASSIGN_BITXOR: - case Token.ASSIGN_BITAND: - case Token.ASSIGN_LSH: - case Token.ASSIGN_RSH: - case Token.ASSIGN_URSH: - case Token.ENTERWITH: - case Token.LEAVEWITH: - case Token.RETURN: - case Token.GOTO: - case Token.IFEQ: - case Token.IFNE: - case Token.NEW: - case Token.DELPROP: - case Token.SETNAME: - case Token.SETPROP: - case Token.SETELEM: - case Token.CALL: - case Token.THROW: - case Token.RETHROW: - case Token.SETVAR: - case Token.CATCH_SCOPE: - case Token.RETURN_RESULT: - case Token.SET_REF: - case Token.DEL_REF: - case Token.REF_CALL: - case Token.TRY: - case Token.SEMI: - case Token.INC: - case Token.DEC: - case Token.EXPORT: - case Token.IMPORT: - case Token.IF: - case Token.ELSE: - case Token.SWITCH: - case Token.WHILE: - case Token.DO: - case Token.FOR: - case Token.BREAK: - case Token.CONTINUE: - case Token.VAR: - case Token.CONST: - case Token.LET: - case Token.LETEXPR: - case Token.WITH: - case Token.WITHEXPR: - case Token.CATCH: - case Token.FINALLY: - case Token.BLOCK: - case Token.LABEL: - case Token.TARGET: - case Token.LOOP: - case Token.JSR: - case Token.SETPROP_OP: - case Token.SETELEM_OP: - case Token.LOCAL_BLOCK: - case Token.SET_REF_OP: - case Token.YIELD: - return true; - - default: - return false; - } - } - - public String toString() - { - if (Token.printTrees) { - StringBuffer sb = new StringBuffer(); - toString(new ObjToIntMap(), sb); - return sb.toString(); - } - return String.valueOf(type); - } - - private void toString(ObjToIntMap printIds, StringBuffer sb) - { - if (Token.printTrees) { - sb.append(Token.name(type)); - if (this instanceof StringNode) { - sb.append(' '); - sb.append(getString()); - Scope scope = getScope(); - if (scope != null) { - sb.append("[scope: "); - appendPrintId(scope, printIds, sb); - sb.append("]"); - } - } else if (this instanceof Node.Scope) { - if (this instanceof ScriptOrFnNode) { - ScriptOrFnNode sof = (ScriptOrFnNode)this; - if (this instanceof FunctionNode) { - FunctionNode fn = (FunctionNode)this; - sb.append(' '); - sb.append(fn.getFunctionName()); - } - sb.append(" [source name: "); - sb.append(sof.getSourceName()); - sb.append("] [encoded source length: "); - sb.append(sof.getEncodedSourceEnd() - - sof.getEncodedSourceStart()); - sb.append("] [base line: "); - sb.append(sof.getBaseLineno()); - sb.append("] [end line: "); - sb.append(sof.getEndLineno()); - sb.append(']'); - } - if (((Node.Scope)this).symbolTable != null) { - sb.append(" [scope "); - appendPrintId(this, printIds, sb); - sb.append(": "); - Iterator iter = ((Node.Scope) this).symbolTable.keySet() - .iterator(); - while (iter.hasNext()) { - sb.append(iter.next()); - sb.append(" "); - } - sb.append("]"); - } - } else if (this instanceof Jump) { - Jump jump = (Jump)this; - if (type == Token.BREAK || type == Token.CONTINUE) { - sb.append(" [label: "); - appendPrintId(jump.getJumpStatement(), printIds, sb); - sb.append(']'); - } else if (type == Token.TRY) { - Node catchNode = jump.target; - Node finallyTarget = jump.getFinally(); - if (catchNode != null) { - sb.append(" [catch: "); - appendPrintId(catchNode, printIds, sb); - sb.append(']'); - } - if (finallyTarget != null) { - sb.append(" [finally: "); - appendPrintId(finallyTarget, printIds, sb); - sb.append(']'); - } - } else if (type == Token.LABEL || type == Token.LOOP - || type == Token.SWITCH) - { - sb.append(" [break: "); - appendPrintId(jump.target, printIds, sb); - sb.append(']'); - if (type == Token.LOOP) { - sb.append(" [continue: "); - appendPrintId(jump.getContinue(), printIds, sb); - sb.append(']'); - } - } else { - sb.append(" [target: "); - appendPrintId(jump.target, printIds, sb); - sb.append(']'); - } - } else if (type == Token.NUMBER) { - sb.append(' '); - sb.append(getDouble()); - } else if (type == Token.TARGET) { - sb.append(' '); - appendPrintId(this, printIds, sb); - } - if (lineno != -1) { - sb.append(' '); - sb.append(lineno); - } - - for (PropListItem x = propListHead; x != null; x = x.next) { - int type = x.type; - sb.append(" ["); - sb.append(propToString(type)); - sb.append(": "); - String value; - switch (type) { - case TARGETBLOCK_PROP : // can't add this as it recurses - value = "target block property"; - break; - case LOCAL_BLOCK_PROP : // can't add this as it is dull - value = "last local block"; - break; - case ISNUMBER_PROP: - switch (x.intValue) { - case BOTH: - value = "both"; - break; - case RIGHT: - value = "right"; - break; - case LEFT: - value = "left"; - break; - default: - throw Kit.codeBug(); - } - break; - case SPECIALCALL_PROP: - switch (x.intValue) { - case SPECIALCALL_EVAL: - value = "eval"; - break; - case SPECIALCALL_WITH: - value = "with"; - break; - default: - // NON_SPECIALCALL should not be stored - throw Kit.codeBug(); - } - break; - case OBJECT_IDS_PROP: { - Object[] a = (Object[]) x.objectValue; - value = "["; - for (int i=0; i < a.length; i++) { - value += a[i].toString(); - if (i+1 < a.length) - value += ", "; - } - value += "]"; - break; - } - default : - Object obj = x.objectValue; - if (obj != null) { - value = obj.toString(); - } else { - value = String.valueOf(x.intValue); - } - break; - } - sb.append(value); - sb.append(']'); - } - } - } - - public String toStringTree(ScriptOrFnNode treeTop) { - if (Token.printTrees) { - StringBuffer sb = new StringBuffer(); - toStringTreeHelper(treeTop, this, null, 0, sb); - return sb.toString(); - } - return null; - } - - private static void toStringTreeHelper(ScriptOrFnNode treeTop, Node n, - ObjToIntMap printIds, - int level, StringBuffer sb) - { - if (Token.printTrees) { - if (printIds == null) { - printIds = new ObjToIntMap(); - generatePrintIds(treeTop, printIds); - } - for (int i = 0; i != level; ++i) { - sb.append(" "); - } - n.toString(printIds, sb); - sb.append('\n'); - for (Node cursor = n.getFirstChild(); cursor != null; - cursor = cursor.getNext()) - { - if (cursor.getType() == Token.FUNCTION) { - int fnIndex = cursor.getExistingIntProp(Node.FUNCTION_PROP); - FunctionNode fn = treeTop.getFunctionNode(fnIndex); - toStringTreeHelper(fn, fn, null, level + 1, sb); - } else { - toStringTreeHelper(treeTop, cursor, printIds, level + 1, sb); - } - } - } - } - - private static void generatePrintIds(Node n, ObjToIntMap map) - { - if (Token.printTrees) { - map.put(n, map.size()); - for (Node cursor = n.getFirstChild(); cursor != null; - cursor = cursor.getNext()) - { - generatePrintIds(cursor, map); - } - } - } - - private static void appendPrintId(Node n, ObjToIntMap printIds, - StringBuffer sb) - { - if (Token.printTrees) { - if (n != null) { - int id = printIds.get(n, -1); - sb.append('#'); - if (id != -1) { - sb.append(id + 1); - } else { - sb.append("<not_available>"); - } - } - } - } - - int type; // type of the node; Token.NAME for example - Node next; // next sibling - private Node first; // first element of a linked list of children - private Node last; // last element of a linked list of children - protected int lineno = -1; - - /*APPJET*/public int statementEndLineNum = -1; - - /** - * Linked list of properties. Since vast majority of nodes would have - * no more then 2 properties, linked list saves memory and provides - * fast lookup. If this does not holds, propListHead can be replaced - * by UintMap. - */ - private PropListItem propListHead; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NodeTransformer.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NodeTransformer.java deleted file mode 100644 index 201c6f2..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/NodeTransformer.java +++ /dev/null @@ -1,565 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Bob Jervis - * Roger Lawrence - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.util.ArrayList; -import java.util.List; - -/** - * This class transforms a tree to a lower-level representation for codegen. - * - * @see Node - * @author Norris Boyd - */ - -public class NodeTransformer -{ - - public NodeTransformer() - { - } - - public final void transform(ScriptOrFnNode tree) - { - transformCompilationUnit(tree); - for (int i = 0; i != tree.getFunctionCount(); ++i) { - FunctionNode fn = tree.getFunctionNode(i); - transform(fn); - } - } - - private void transformCompilationUnit(ScriptOrFnNode tree) - { - loops = new ObjArray(); - loopEnds = new ObjArray(); - - // to save against upchecks if no finally blocks are used. - hasFinally = false; - - // Flatten all only if we are not using scope objects for block scope - boolean createScopeObjects = tree.getType() != Token.FUNCTION || - ((FunctionNode)tree).requiresActivation(); - tree.flattenSymbolTable(!createScopeObjects); - - //uncomment to print tree before transformation - //if (Token.printTrees) System.out.println(tree.toStringTree(tree)); - transformCompilationUnit_r(tree, tree, tree, createScopeObjects); - } - - private void transformCompilationUnit_r(final ScriptOrFnNode tree, - final Node parent, - Node.Scope scope, - boolean createScopeObjects) - { - Node node = null; - siblingLoop: - for (;;) { - Node previous = null; - if (node == null) { - node = parent.getFirstChild(); - } else { - previous = node; - node = node.getNext(); - } - if (node == null) { - break; - } - - int type = node.getType(); - if (createScopeObjects && - (type == Token.BLOCK || type == Token.LOOP || - type == Token.ARRAYCOMP) && - (node instanceof Node.Scope)) - { - Node.Scope newScope = (Node.Scope) node; - if (newScope.symbolTable != null) { - // transform to let statement so we get a with statement - // created to contain scoped let variables - Node let = new Node(type == Token.ARRAYCOMP ? Token.LETEXPR - : Token.LET); - Node innerLet = new Node(Token.LET); - let.addChildToBack(innerLet); - for (String name: newScope.symbolTable.keySet()) { - innerLet.addChildToBack(Node.newString(Token.NAME, name)); - } - newScope.symbolTable = null; // so we don't transform again - Node oldNode = node; - node = replaceCurrent(parent, previous, node, let); - type = node.getType(); - let.addChildToBack(oldNode); - } - } - - switch (type) { - - case Token.LABEL: - case Token.SWITCH: - case Token.LOOP: - loops.push(node); - loopEnds.push(((Node.Jump)node).target); - break; - - case Token.WITH: - { - loops.push(node); - Node leave = node.getNext(); - if (leave.getType() != Token.LEAVEWITH) { - Kit.codeBug(); - } - loopEnds.push(leave); - break; - } - - case Token.TRY: - { - Node.Jump jump = (Node.Jump)node; - Node finallytarget = jump.getFinally(); - if (finallytarget != null) { - hasFinally = true; - loops.push(node); - loopEnds.push(finallytarget); - } - break; - } - - case Token.TARGET: - case Token.LEAVEWITH: - if (!loopEnds.isEmpty() && loopEnds.peek() == node) { - loopEnds.pop(); - loops.pop(); - } - break; - - case Token.YIELD: - ((FunctionNode)tree).addResumptionPoint(node); - break; - - case Token.RETURN: - { - boolean isGenerator = tree.getType() == Token.FUNCTION - && ((FunctionNode)tree).isGenerator(); - if (isGenerator) { - node.putIntProp(Node.GENERATOR_END_PROP, 1); - } - /* If we didn't support try/finally, it wouldn't be - * necessary to put LEAVEWITH nodes here... but as - * we do need a series of JSR FINALLY nodes before - * each RETURN, we need to ensure that each finally - * block gets the correct scope... which could mean - * that some LEAVEWITH nodes are necessary. - */ - if (!hasFinally) - break; // skip the whole mess. - Node unwindBlock = null; - for (int i=loops.size()-1; i >= 0; i--) { - Node n = (Node) loops.get(i); - int elemtype = n.getType(); - if (elemtype == Token.TRY || elemtype == Token.WITH) { - Node unwind; - if (elemtype == Token.TRY) { - Node.Jump jsrnode = new Node.Jump(Token.JSR); - Node jsrtarget = ((Node.Jump)n).getFinally(); - jsrnode.target = jsrtarget; - unwind = jsrnode; - } else { - unwind = new Node(Token.LEAVEWITH); - } - if (unwindBlock == null) { - unwindBlock = new Node(Token.BLOCK, - node.getLineno()); - } - unwindBlock.addChildToBack(unwind); - } - } - if (unwindBlock != null) { - Node returnNode = node; - Node returnExpr = returnNode.getFirstChild(); - node = replaceCurrent(parent, previous, node, unwindBlock); - if (returnExpr == null || isGenerator) { - unwindBlock.addChildToBack(returnNode); - } else { - Node store = new Node(Token.EXPR_RESULT, returnExpr); - unwindBlock.addChildToFront(store); - returnNode = new Node(Token.RETURN_RESULT); - unwindBlock.addChildToBack(returnNode); - // transform return expression - transformCompilationUnit_r(tree, store, scope, - createScopeObjects); - } - // skip transformCompilationUnit_r to avoid infinite loop - continue siblingLoop; - } - break; - } - - case Token.BREAK: - case Token.CONTINUE: - { - Node.Jump jump = (Node.Jump)node; - Node.Jump jumpStatement = jump.getJumpStatement(); - if (jumpStatement == null) Kit.codeBug(); - - for (int i = loops.size(); ;) { - if (i == 0) { - // Parser/IRFactory ensure that break/continue - // always has a jump statement associated with it - // which should be found - throw Kit.codeBug(); - } - --i; - Node n = (Node) loops.get(i); - if (n == jumpStatement) { - break; - } - - int elemtype = n.getType(); - if (elemtype == Token.WITH) { - Node leave = new Node(Token.LEAVEWITH); - previous = addBeforeCurrent(parent, previous, node, - leave); - } else if (elemtype == Token.TRY) { - Node.Jump tryNode = (Node.Jump)n; - Node.Jump jsrFinally = new Node.Jump(Token.JSR); - jsrFinally.target = tryNode.getFinally(); - previous = addBeforeCurrent(parent, previous, node, - jsrFinally); - } - } - - if (type == Token.BREAK) { - jump.target = jumpStatement.target; - } else { - jump.target = jumpStatement.getContinue(); - } - jump.setType(Token.GOTO); - - break; - } - - case Token.CALL: - visitCall(node, tree); - break; - - case Token.NEW: - visitNew(node, tree); - break; - - case Token.LETEXPR: - case Token.LET: { - Node child = node.getFirstChild(); - if (child.getType() == Token.LET) { - // We have a let statement or expression rather than a - // let declaration - boolean createWith = tree.getType() != Token.FUNCTION - || ((FunctionNode)tree).requiresActivation(); - node = visitLet(createWith, parent, previous, node); - break; - } else { - // fall through to process let declaration... - } - } - /* fall through */ - case Token.CONST: - case Token.VAR: - { - Node result = new Node(Token.BLOCK); - for (Node cursor = node.getFirstChild(); cursor != null;) { - // Move cursor to next before createAssignment gets chance - // to change n.next - Node n = cursor; - cursor = cursor.getNext(); - if (n.getType() == Token.NAME) { - if (!n.hasChildren()) - continue; - Node init = n.getFirstChild(); - n.removeChild(init); - n.setType(Token.BINDNAME); - n = new Node(type == Token.CONST ? - Token.SETCONST : - Token.SETNAME, - n, init); - } else { - // May be a destructuring assignment already transformed - // to a LETEXPR - if (n.getType() != Token.LETEXPR) - throw Kit.codeBug(); - } - Node pop = new Node(Token.EXPR_VOID, n, node.getLineno()); - result.addChildToBack(pop); - } - node = replaceCurrent(parent, previous, node, result); - break; - } - - case Token.TYPEOFNAME: { - Node.Scope defining = scope.getDefiningScope(node.getString()); - if (defining != null) { - node.setScope(defining); - } - } - break; - - case Token.TYPEOF: - case Token.IFNE: { - /* We want to suppress warnings for undefined property o.p - * for the following constructs: typeof o.p, if (o.p), - * if (!o.p), if (o.p == undefined), if (undefined == o.p) - */ - Node child = node.getFirstChild(); - if (type == Token.IFNE) { - while (child.getType() == Token.NOT) { - child = child.getFirstChild(); - } - if (child.getType() == Token.EQ || - child.getType() == Token.NE) - { - Node first = child.getFirstChild(); - Node last = child.getLastChild(); - if (first.getType() == Token.NAME && - first.getString().equals("undefined")) - child = last; - else if (last.getType() == Token.NAME && - last.getString().equals("undefined")) - child = first; - } - } - if (child.getType() == Token.GETPROP) - child.setType(Token.GETPROPNOWARN); - break; - } - - case Token.NAME: - case Token.SETNAME: - case Token.SETCONST: - case Token.DELPROP: - { - // Turn name to var for faster access if possible - if (createScopeObjects) { - break; - } - Node nameSource; - if (type == Token.NAME) { - nameSource = node; - } else { - nameSource = node.getFirstChild(); - if (nameSource.getType() != Token.BINDNAME) { - if (type == Token.DELPROP) { - break; - } - throw Kit.codeBug(); - } - } - if (nameSource.getScope() != null) { - break; // already have a scope set - } - String name = nameSource.getString(); - Node.Scope defining = scope.getDefiningScope(name); - if (defining != null) { - nameSource.setScope(defining); - if (type == Token.NAME) { - node.setType(Token.GETVAR); - } else if (type == Token.SETNAME) { - node.setType(Token.SETVAR); - nameSource.setType(Token.STRING); - } else if (type == Token.SETCONST) { - node.setType(Token.SETCONSTVAR); - nameSource.setType(Token.STRING); - } else if (type == Token.DELPROP) { - // Local variables are by definition permanent - Node n = new Node(Token.FALSE); - node = replaceCurrent(parent, previous, node, n); - } else { - throw Kit.codeBug(); - } - } - break; - } - } - - transformCompilationUnit_r(tree, node, - node instanceof Node.Scope ? (Node.Scope)node : scope, - createScopeObjects); - } - } - - protected void visitNew(Node node, ScriptOrFnNode tree) { - } - - protected void visitCall(Node node, ScriptOrFnNode tree) { - } - - protected Node visitLet(boolean createWith, Node parent, Node previous, - Node scopeNode) - { - Node vars = scopeNode.getFirstChild(); - Node body = vars.getNext(); - scopeNode.removeChild(vars); - scopeNode.removeChild(body); - boolean isExpression = scopeNode.getType() == Token.LETEXPR; - Node result; - Node newVars; - if (createWith) { - result = new Node(isExpression ? Token.WITHEXPR : Token.BLOCK); - result = replaceCurrent(parent, previous, scopeNode, result); - ArrayList<Object> list = new ArrayList<Object>(); - Node objectLiteral = new Node(Token.OBJECTLIT); - for (Node v=vars.getFirstChild(); v != null; v = v.getNext()) { - Node current = v; - if (current.getType() == Token.LETEXPR) { - // destructuring in let expr, e.g. let ([x, y] = [3, 4]) {} - List<?> destructuringNames = (List<?>) - current.getProp(Node.DESTRUCTURING_NAMES); - Node c = current.getFirstChild(); - if (c.getType() != Token.LET) throw Kit.codeBug(); - // Add initialization code to front of body - if (isExpression) { - body = new Node(Token.COMMA, c.getNext(), body); - } else { - body = new Node(Token.BLOCK, - new Node(Token.EXPR_VOID, c.getNext()), - body); - } - // Update "list" and "objectLiteral" for the variables - // defined in the destructuring assignment - if (destructuringNames != null) { - list.addAll(destructuringNames); - for (int i=0; i < destructuringNames.size(); i++) { - objectLiteral.addChildToBack( - new Node(Token.VOID, Node.newNumber(0.0))); - } - } - current = c.getFirstChild(); // should be a NAME, checked below - } - if (current.getType() != Token.NAME) throw Kit.codeBug(); - list.add(ScriptRuntime.getIndexObject(current.getString())); - Node init = current.getFirstChild(); - if (init == null) { - init = new Node(Token.VOID, Node.newNumber(0.0)); - } - objectLiteral.addChildToBack(init); - } - objectLiteral.putProp(Node.OBJECT_IDS_PROP, list.toArray()); - newVars = new Node(Token.ENTERWITH, objectLiteral); - result.addChildToBack(newVars); - result.addChildToBack(new Node(Token.WITH, body)); - result.addChildToBack(new Node(Token.LEAVEWITH)); - } else { - result = new Node(isExpression ? Token.COMMA : Token.BLOCK); - result = replaceCurrent(parent, previous, scopeNode, result); - newVars = new Node(Token.COMMA); - for (Node v=vars.getFirstChild(); v != null; v = v.getNext()) { - Node current = v; - if (current.getType() == Token.LETEXPR) { - // destructuring in let expr, e.g. let ([x, y] = [3, 4]) {} - Node c = current.getFirstChild(); - if (c.getType() != Token.LET) throw Kit.codeBug(); - // Add initialization code to front of body - if (isExpression) { - body = new Node(Token.COMMA, c.getNext(), body); - } else { - body = new Node(Token.BLOCK, - new Node(Token.EXPR_VOID, c.getNext()), - body); - } - // We're removing the LETEXPR, so move the symbols - Node.Scope.joinScopes((Node.Scope)current, - (Node.Scope)scopeNode); - current = c.getFirstChild(); // should be a NAME, checked below - } - if (current.getType() != Token.NAME) throw Kit.codeBug(); - Node stringNode = Node.newString(current.getString()); - stringNode.setScope((Node.Scope)scopeNode); - Node init = current.getFirstChild(); - if (init == null) { - init = new Node(Token.VOID, Node.newNumber(0.0)); - } - newVars.addChildToBack(new Node(Token.SETVAR, stringNode, init)); - } - if (isExpression) { - result.addChildToBack(newVars); - scopeNode.setType(Token.COMMA); - result.addChildToBack(scopeNode); - scopeNode.addChildToBack(body); - } else { - result.addChildToBack(new Node(Token.EXPR_VOID, newVars)); - scopeNode.setType(Token.BLOCK); - result.addChildToBack(scopeNode); - scopeNode.addChildrenToBack(body); - } - } - return result; - } - - private static Node addBeforeCurrent(Node parent, Node previous, - Node current, Node toAdd) - { - if (previous == null) { - if (!(current == parent.getFirstChild())) Kit.codeBug(); - parent.addChildToFront(toAdd); - } else { - if (!(current == previous.getNext())) Kit.codeBug(); - parent.addChildAfter(toAdd, previous); - } - return toAdd; - } - - private static Node replaceCurrent(Node parent, Node previous, - Node current, Node replacement) - { - if (previous == null) { - if (!(current == parent.getFirstChild())) Kit.codeBug(); - parent.replaceChild(current, replacement); - } else if (previous.next == current) { - // Check cachedPrev.next == current is necessary due to possible - // tree mutations - parent.replaceChildAfter(previous, replacement); - } else { - parent.replaceChild(current, replacement); - } - return replacement; - } - - private ObjArray loops; - private ObjArray loopEnds; - private boolean hasFinally; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java deleted file mode 100644 index a9636a3..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java +++ /dev/null @@ -1,388 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Serializable; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -/** -Implementation of resizable array with focus on minimizing memory usage by storing few initial array elements in object fields. Can also be used as a stack. -*/ - -public class ObjArray implements Serializable -{ - static final long serialVersionUID = 4174889037736658296L; - - public ObjArray() { } - - public final boolean isSealed() - { - return sealed; - } - - public final void seal() - { - sealed = true; - } - - public final boolean isEmpty() - { - return size == 0; - } - - public final int size() - { - return size; - } - - public final void setSize(int newSize) - { - if (newSize < 0) throw new IllegalArgumentException(); - if (sealed) throw onSeledMutation(); - int N = size; - if (newSize < N) { - for (int i = newSize; i != N; ++i) { - setImpl(i, null); - } - } else if (newSize > N) { - if (newSize > FIELDS_STORE_SIZE) { - ensureCapacity(newSize); - } - } - size = newSize; - } - - public final Object get(int index) - { - if (!(0 <= index && index < size)) throw onInvalidIndex(index, size); - return getImpl(index); - } - - public final void set(int index, Object value) - { - if (!(0 <= index && index < size)) throw onInvalidIndex(index, size); - if (sealed) throw onSeledMutation(); - setImpl(index, value); - } - - private Object getImpl(int index) - { - switch (index) { - case 0: return f0; - case 1: return f1; - case 2: return f2; - case 3: return f3; - case 4: return f4; - } - return data[index - FIELDS_STORE_SIZE]; - } - - private void setImpl(int index, Object value) - { - switch (index) { - case 0: f0 = value; break; - case 1: f1 = value; break; - case 2: f2 = value; break; - case 3: f3 = value; break; - case 4: f4 = value; break; - default: data[index - FIELDS_STORE_SIZE] = value; - } - - } - - public int indexOf(Object obj) - { - int N = size; - for (int i = 0; i != N; ++i) { - Object current = getImpl(i); - if (current == obj || (current != null && current.equals(obj))) { - return i; - } - } - return -1; - } - - public int lastIndexOf(Object obj) - { - for (int i = size; i != 0;) { - --i; - Object current = getImpl(i); - if (current == obj || (current != null && current.equals(obj))) { - return i; - } - } - return -1; - } - - public final Object peek() - { - int N = size; - if (N == 0) throw onEmptyStackTopRead(); - return getImpl(N - 1); - } - - public final Object pop() - { - if (sealed) throw onSeledMutation(); - int N = size; - --N; - Object top; - switch (N) { - case -1: throw onEmptyStackTopRead(); - case 0: top = f0; f0 = null; break; - case 1: top = f1; f1 = null; break; - case 2: top = f2; f2 = null; break; - case 3: top = f3; f3 = null; break; - case 4: top = f4; f4 = null; break; - default: - top = data[N - FIELDS_STORE_SIZE]; - data[N - FIELDS_STORE_SIZE] = null; - } - size = N; - return top; - } - - public final void push(Object value) - { - add(value); - } - - public final void add(Object value) - { - if (sealed) throw onSeledMutation(); - int N = size; - if (N >= FIELDS_STORE_SIZE) { - ensureCapacity(N + 1); - } - size = N + 1; - setImpl(N, value); - } - - public final void add(int index, Object value) - { - int N = size; - if (!(0 <= index && index <= N)) throw onInvalidIndex(index, N + 1); - if (sealed) throw onSeledMutation(); - Object tmp; - switch (index) { - case 0: - if (N == 0) { f0 = value; break; } - tmp = f0; f0 = value; value = tmp; - case 1: - if (N == 1) { f1 = value; break; } - tmp = f1; f1 = value; value = tmp; - case 2: - if (N == 2) { f2 = value; break; } - tmp = f2; f2 = value; value = tmp; - case 3: - if (N == 3) { f3 = value; break; } - tmp = f3; f3 = value; value = tmp; - case 4: - if (N == 4) { f4 = value; break; } - tmp = f4; f4 = value; value = tmp; - - index = FIELDS_STORE_SIZE; - default: - ensureCapacity(N + 1); - if (index != N) { - System.arraycopy(data, index - FIELDS_STORE_SIZE, - data, index - FIELDS_STORE_SIZE + 1, - N - index); - } - data[index - FIELDS_STORE_SIZE] = value; - } - size = N + 1; - } - - public final void remove(int index) - { - int N = size; - if (!(0 <= index && index < N)) throw onInvalidIndex(index, N); - if (sealed) throw onSeledMutation(); - --N; - switch (index) { - case 0: - if (N == 0) { f0 = null; break; } - f0 = f1; - case 1: - if (N == 1) { f1 = null; break; } - f1 = f2; - case 2: - if (N == 2) { f2 = null; break; } - f2 = f3; - case 3: - if (N == 3) { f3 = null; break; } - f3 = f4; - case 4: - if (N == 4) { f4 = null; break; } - f4 = data[0]; - - index = FIELDS_STORE_SIZE; - default: - if (index != N) { - System.arraycopy(data, index - FIELDS_STORE_SIZE + 1, - data, index - FIELDS_STORE_SIZE, - N - index); - } - data[N - FIELDS_STORE_SIZE] = null; - } - size = N; - } - - public final void clear() - { - if (sealed) throw onSeledMutation(); - int N = size; - for (int i = 0; i != N; ++i) { - setImpl(i, null); - } - size = 0; - } - - public final Object[] toArray() - { - Object[] array = new Object[size]; - toArray(array, 0); - return array; - } - - public final void toArray(Object[] array) - { - toArray(array, 0); - } - - public final void toArray(Object[] array, int offset) - { - int N = size; - switch (N) { - default: - System.arraycopy(data, 0, array, offset + FIELDS_STORE_SIZE, - N - FIELDS_STORE_SIZE); - case 5: array[offset + 4] = f4; - case 4: array[offset + 3] = f3; - case 3: array[offset + 2] = f2; - case 2: array[offset + 1] = f1; - case 1: array[offset + 0] = f0; - case 0: break; - } - } - - private void ensureCapacity(int minimalCapacity) - { - int required = minimalCapacity - FIELDS_STORE_SIZE; - if (required <= 0) throw new IllegalArgumentException(); - if (data == null) { - int alloc = FIELDS_STORE_SIZE * 2; - if (alloc < required) { - alloc = required; - } - data = new Object[alloc]; - } else { - int alloc = data.length; - if (alloc < required) { - if (alloc <= FIELDS_STORE_SIZE) { - alloc = FIELDS_STORE_SIZE * 2; - } else { - alloc *= 2; - } - if (alloc < required) { - alloc = required; - } - Object[] tmp = new Object[alloc]; - if (size > FIELDS_STORE_SIZE) { - System.arraycopy(data, 0, tmp, 0, - size - FIELDS_STORE_SIZE); - } - data = tmp; - } - } - } - - private static RuntimeException onInvalidIndex(int index, int upperBound) - { - // \u2209 is "NOT ELEMENT OF" - String msg = index+" \u2209 [0, "+upperBound+')'; - throw new IndexOutOfBoundsException(msg); - } - - private static RuntimeException onEmptyStackTopRead() - { - throw new RuntimeException("Empty stack"); - } - - private static RuntimeException onSeledMutation() - { - throw new IllegalStateException("Attempt to modify sealed array"); - } - - private void writeObject(ObjectOutputStream os) throws IOException - { - os.defaultWriteObject(); - int N = size; - for (int i = 0; i != N; ++i) { - Object obj = getImpl(i); - os.writeObject(obj); - } - } - - private void readObject(ObjectInputStream is) - throws IOException, ClassNotFoundException - { - is.defaultReadObject(); // It reads size - int N = size; - if (N > FIELDS_STORE_SIZE) { - data = new Object[N - FIELDS_STORE_SIZE]; - } - for (int i = 0; i != N; ++i) { - Object obj = is.readObject(); - setImpl(i, obj); - } - } - -// Number of data elements - private int size; - - private boolean sealed; - - private static final int FIELDS_STORE_SIZE = 5; - private transient Object f0, f1, f2, f3, f4; - private transient Object[] data; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjToIntMap.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjToIntMap.java deleted file mode 100644 index 4aa7d23..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjToIntMap.java +++ /dev/null @@ -1,697 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Serializable; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -/** - * Map to associate objects to integers. - * The map does not synchronize any of its operation, so either use - * it from a single thread or do own synchronization or perform all mutation - * operations on one thread before passing the map to others - * - * @author Igor Bukanov - * - */ - -public class ObjToIntMap implements Serializable -{ - static final long serialVersionUID = -1542220580748809402L; - -// Map implementation via hashtable, -// follows "The Art of Computer Programming" by Donald E. Knuth - -// ObjToIntMap is a copy cat of ObjToIntMap with API adjusted to object keys - - public static class Iterator { - - Iterator(ObjToIntMap master) { - this.master = master; - } - - final void init(Object[] keys, int[] values, int keyCount) { - this.keys = keys; - this.values = values; - this.cursor = -1; - this.remaining = keyCount; - } - - public void start() { - master.initIterator(this); - next(); - } - - public boolean done() { - return remaining < 0; - } - - public void next() { - if (remaining == -1) Kit.codeBug(); - if (remaining == 0) { - remaining = -1; - cursor = -1; - }else { - for (++cursor; ; ++cursor) { - Object key = keys[cursor]; - if (key != null && key != DELETED) { - --remaining; - break; - } - } - } - } - - public Object getKey() { - Object key = keys[cursor]; - if (key == UniqueTag.NULL_VALUE) { key = null; } - return key; - } - - public int getValue() { - return values[cursor]; - } - - public void setValue(int value) { - values[cursor] = value; - } - - ObjToIntMap master; - private int cursor; - private int remaining; - private Object[] keys; - private int[] values; - } - - public ObjToIntMap() { - this(4); - } - - public ObjToIntMap(int keyCountHint) { - if (keyCountHint < 0) Kit.codeBug(); - // Table grow when number of stored keys >= 3/4 of max capacity - int minimalCapacity = keyCountHint * 4 / 3; - int i; - for (i = 2; (1 << i) < minimalCapacity; ++i) { } - power = i; - if (check && power < 2) Kit.codeBug(); - } - - public boolean isEmpty() { - return keyCount == 0; - } - - public int size() { - return keyCount; - } - - public boolean has(Object key) { - if (key == null) { key = UniqueTag.NULL_VALUE; } - return 0 <= findIndex(key); - } - - /** - * Get integer value assigned with key. - * @return key integer value or defaultValue if key is absent - */ - public int get(Object key, int defaultValue) { - if (key == null) { key = UniqueTag.NULL_VALUE; } - int index = findIndex(key); - if (0 <= index) { - return values[index]; - } - return defaultValue; - } - - /** - * Get integer value assigned with key. - * @return key integer value - * @throws RuntimeException if key does not exist - */ - public int getExisting(Object key) { - if (key == null) { key = UniqueTag.NULL_VALUE; } - int index = findIndex(key); - if (0 <= index) { - return values[index]; - } - // Key must exist - Kit.codeBug(); - return 0; - } - - public void put(Object key, int value) { - if (key == null) { key = UniqueTag.NULL_VALUE; } - int index = ensureIndex(key); - values[index] = value; - } - - /** - * If table already contains a key that equals to keyArg, return that key - * while setting its value to zero, otherwise add keyArg with 0 value to - * the table and return it. - */ - public Object intern(Object keyArg) { - boolean nullKey = false; - if (keyArg == null) { - nullKey = true; - keyArg = UniqueTag.NULL_VALUE; - } - int index = ensureIndex(keyArg); - values[index] = 0; - return (nullKey) ? null : keys[index]; - } - - public void remove(Object key) { - if (key == null) { key = UniqueTag.NULL_VALUE; } - int index = findIndex(key); - if (0 <= index) { - keys[index] = DELETED; - --keyCount; - } - } - - public void clear() { - int i = keys.length; - while (i != 0) { - keys[--i] = null; - } - keyCount = 0; - occupiedCount = 0; - } - - public Iterator newIterator() { - return new Iterator(this); - } - - // The sole purpose of the method is to avoid accessing private fields - // from the Iterator inner class to workaround JDK 1.1 compiler bug which - // generates code triggering VerifierError on recent JVMs - final void initIterator(Iterator i) { - i.init(keys, values, keyCount); - } - - /** Return array of present keys */ - public Object[] getKeys() { - Object[] array = new Object[keyCount]; - getKeys(array, 0); - return array; - } - - public void getKeys(Object[] array, int offset) { - int count = keyCount; - for (int i = 0; count != 0; ++i) { - Object key = keys[i]; - if (key != null && key != DELETED) { - if (key == UniqueTag.NULL_VALUE) { key = null; } - array[offset] = key; - ++offset; - --count; - } - } - } - - private static int tableLookupStep(int fraction, int mask, int power) { - int shift = 32 - 2 * power; - if (shift >= 0) { - return ((fraction >>> shift) & mask) | 1; - } - else { - return (fraction & (mask >>> -shift)) | 1; - } - } - - private int findIndex(Object key) { - if (keys != null) { - int hash = key.hashCode(); - int fraction = hash * A; - int index = fraction >>> (32 - power); - Object test = keys[index]; - if (test != null) { - int N = 1 << power; - if (test == key - || (values[N + index] == hash && test.equals(key))) - { - return index; - } - // Search in table after first failed attempt - int mask = N - 1; - int step = tableLookupStep(fraction, mask, power); - int n = 0; - for (;;) { - if (check) { - if (n >= occupiedCount) Kit.codeBug(); - ++n; - } - index = (index + step) & mask; - test = keys[index]; - if (test == null) { - break; - } - if (test == key - || (values[N + index] == hash && test.equals(key))) - { - return index; - } - } - } - } - return -1; - } - -// Insert key that is not present to table without deleted entries -// and enough free space - private int insertNewKey(Object key, int hash) { - if (check && occupiedCount != keyCount) Kit.codeBug(); - if (check && keyCount == 1 << power) Kit.codeBug(); - int fraction = hash * A; - int index = fraction >>> (32 - power); - int N = 1 << power; - if (keys[index] != null) { - int mask = N - 1; - int step = tableLookupStep(fraction, mask, power); - int firstIndex = index; - do { - if (check && keys[index] == DELETED) Kit.codeBug(); - index = (index + step) & mask; - if (check && firstIndex == index) Kit.codeBug(); - } while (keys[index] != null); - } - keys[index] = key; - values[N + index] = hash; - ++occupiedCount; - ++keyCount; - - return index; - } - - private void rehashTable() { - if (keys == null) { - if (check && keyCount != 0) Kit.codeBug(); - if (check && occupiedCount != 0) Kit.codeBug(); - int N = 1 << power; - keys = new Object[N]; - values = new int[2 * N]; - } - else { - // Check if removing deleted entries would free enough space - if (keyCount * 2 >= occupiedCount) { - // Need to grow: less then half of deleted entries - ++power; - } - int N = 1 << power; - Object[] oldKeys = keys; - int[] oldValues = values; - int oldN = oldKeys.length; - keys = new Object[N]; - values = new int[2 * N]; - - int remaining = keyCount; - occupiedCount = keyCount = 0; - for (int i = 0; remaining != 0; ++i) { - Object key = oldKeys[i]; - if (key != null && key != DELETED) { - int keyHash = oldValues[oldN + i]; - int index = insertNewKey(key, keyHash); - values[index] = oldValues[i]; - --remaining; - } - } - } - } - -// Ensure key index creating one if necessary - private int ensureIndex(Object key) { - int hash = key.hashCode(); - int index = -1; - int firstDeleted = -1; - if (keys != null) { - int fraction = hash * A; - index = fraction >>> (32 - power); - Object test = keys[index]; - if (test != null) { - int N = 1 << power; - if (test == key - || (values[N + index] == hash && test.equals(key))) - { - return index; - } - if (test == DELETED) { - firstDeleted = index; - } - - // Search in table after first failed attempt - int mask = N - 1; - int step = tableLookupStep(fraction, mask, power); - int n = 0; - for (;;) { - if (check) { - if (n >= occupiedCount) Kit.codeBug(); - ++n; - } - index = (index + step) & mask; - test = keys[index]; - if (test == null) { - break; - } - if (test == key - || (values[N + index] == hash && test.equals(key))) - { - return index; - } - if (test == DELETED && firstDeleted < 0) { - firstDeleted = index; - } - } - } - } - // Inserting of new key - if (check && keys != null && keys[index] != null) - Kit.codeBug(); - if (firstDeleted >= 0) { - index = firstDeleted; - } - else { - // Need to consume empty entry: check occupation level - if (keys == null || occupiedCount * 4 >= (1 << power) * 3) { - // Too litle unused entries: rehash - rehashTable(); - return insertNewKey(key, hash); - } - ++occupiedCount; - } - keys[index] = key; - values[(1 << power) + index] = hash; - ++keyCount; - return index; - } - - private void writeObject(ObjectOutputStream out) - throws IOException - { - out.defaultWriteObject(); - - int count = keyCount; - for (int i = 0; count != 0; ++i) { - Object key = keys[i]; - if (key != null && key != DELETED) { - --count; - out.writeObject(key); - out.writeInt(values[i]); - } - } - } - - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - - int writtenKeyCount = keyCount; - if (writtenKeyCount != 0) { - keyCount = 0; - int N = 1 << power; - keys = new Object[N]; - values = new int[2 * N]; - for (int i = 0; i != writtenKeyCount; ++i) { - Object key = in.readObject(); - int hash = key.hashCode(); - int index = insertNewKey(key, hash); - values[index] = in.readInt(); - } - } - } - -// A == golden_ratio * (1 << 32) = ((sqrt(5) - 1) / 2) * (1 << 32) -// See Knuth etc. - private static final int A = 0x9e3779b9; - - private static final Object DELETED = new Object(); - -// Structure of kyes and values arrays (N == 1 << power): -// keys[0 <= i < N]: key value or null or DELETED mark -// values[0 <= i < N]: value of key at keys[i] -// values[N <= i < 2*N]: hash code of key at keys[i-N] - - private transient Object[] keys; - private transient int[] values; - - private int power; - private int keyCount; - private transient int occupiedCount; // == keyCount + deleted_count - -// If true, enables consitency checks - private static final boolean check = false; - -/* TEST START - - public static void main(String[] args) { - if (!check) { - System.err.println("Set check to true and re-run"); - throw new RuntimeException("Set check to true and re-run"); - } - - ObjToIntMap map; - map = new ObjToIntMap(0); - testHash(map, 3); - map = new ObjToIntMap(0); - testHash(map, 10 * 1000); - map = new ObjToIntMap(); - testHash(map, 10 * 1000); - map = new ObjToIntMap(30 * 1000); - testHash(map, 10 * 100); - map.clear(); - testHash(map, 4); - map = new ObjToIntMap(0); - testHash(map, 10 * 100); - } - - private static void testHash(ObjToIntMap map, int N) { - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(i); - check(-1 == map.get(key, -1)); - map.put(key, i); - check(i == map.get(key, -1)); - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(i); - map.put(key, i); - check(i == map.get(key, -1)); - } - - check(map.size() == N); - - System.out.print("."); System.out.flush(); - Object[] keys = map.getKeys(); - check(keys.length == N); - for (int i = 0; i != N; ++i) { - Object key = keys[i]; - check(map.has(key)); - } - - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(i); - check(i == map.get(key, -1)); - } - - int Nsqrt = -1; - for (int i = 0; ; ++i) { - if (i * i >= N) { - Nsqrt = i; - break; - } - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(i * i); - map.put(key, i); - check(i == map.get(key, -1)); - } - - check(map.size() == 2 * N - Nsqrt); - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(i * i); - check(i == map.get(key, -1)); - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(-1 - i * i); - map.put(key, i); - check(i == map.get(key, -1)); - } - - check(map.size() == 3 * N - Nsqrt); - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(-1 - i * i); - map.remove(key); - check(!map.has(key)); - } - - check(map.size() == 2 * N - Nsqrt); - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(i * i); - check(i == map.get(key, -1)); - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(i); - int j = intSqrt(i); - if (j * j == i) { - check(j == map.get(key, -1)); - }else { - check(i == map.get(key, -1)); - } - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(i * i); - map.remove(key); - check(-2 == map.get(key, -2)); - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(i); - map.put(key, i); - check(i == map.get(key, -2)); - } - - check(map.size() == N); - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - Object key = testKey(i); - check(i == map.get(key, -1)); - } - - System.out.print("."); System.out.flush(); - ObjToIntMap copy = (ObjToIntMap)writeAndRead(map); - check(copy.size() == N); - - for (int i = 0; i != N; ++i) { - Object key = testKey(i); - check(i == copy.get(key, -1)); - } - - System.out.print("."); System.out.flush(); - checkSameMaps(copy, map); - - System.out.println(); System.out.flush(); - } - - private static void checkSameMaps(ObjToIntMap map1, ObjToIntMap map2) { - check(map1.size() == map2.size()); - Object[] keys = map1.getKeys(); - check(keys.length == map1.size()); - for (int i = 0; i != keys.length; ++i) { - check(map1.get(keys[i], -1) == map2.get(keys[i], -1)); - } - } - - private static void check(boolean condition) { - if (!condition) Kit.codeBug(); - } - - private static Object[] testPool; - - private static Object testKey(int i) { - int MAX_POOL = 100; - if (0 <= i && i < MAX_POOL) { - if (testPool != null && testPool[i] != null) { - return testPool[i]; - } - } - Object x = new Double(i + 0.5); - if (0 <= i && i < MAX_POOL) { - if (testPool == null) { - testPool = new Object[MAX_POOL]; - } - testPool[i] = x; - } - return x; - } - - private static int intSqrt(int i) { - int approx = (int)Math.sqrt(i) + 1; - while (approx * approx > i) { - --approx; - } - return approx; - } - - private static Object writeAndRead(Object obj) { - try { - java.io.ByteArrayOutputStream - bos = new java.io.ByteArrayOutputStream(); - java.io.ObjectOutputStream - out = new java.io.ObjectOutputStream(bos); - out.writeObject(obj); - out.close(); - byte[] data = bos.toByteArray(); - java.io.ByteArrayInputStream - bis = new java.io.ByteArrayInputStream(data); - java.io.ObjectInputStream - in = new java.io.ObjectInputStream(bis); - Object result = in.readObject(); - in.close(); - return result; - }catch (Exception ex) { - throw new RuntimeException("Unexpected"); - } - } - -// TEST END */ - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Parser.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Parser.java deleted file mode 100644 index 80cb937..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Parser.java +++ /dev/null @@ -1,2554 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Mike Ang - * Igor Bukanov - * Yuh-Ruey Chen - * Ethan Hugg - * Bob Jervis - * Terry Lucas - * Mike McCabe - * Milen Nankov - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Reader; -import java.io.IOException; -import java.util.Hashtable; - -/** - * This class implements the JavaScript parser. - * - * It is based on the C source files jsparse.c and jsparse.h - * in the jsref package. - * - * @see TokenStream - * - * @author Mike McCabe - * @author Brendan Eich - */ - -public class Parser -{ - // TokenInformation flags : currentFlaggedToken stores them together - // with token type - final static int - CLEAR_TI_MASK = 0xFFFF, // mask to clear token information bits - TI_AFTER_EOL = 1 << 16, // first token of the source line - TI_CHECK_LABEL = 1 << 17; // indicates to check for label - - CompilerEnvirons compilerEnv; - private ErrorReporter errorReporter; - /*APPJET*//*no longer:private*/ String sourceURI; - boolean calledByCompileFunction; - - /*APPJET*//*no longer:private*/ TokenStream ts; - private int currentFlaggedToken; - /*APPJET*//*no longer:private*/ int syntaxErrorCount; - - private IRFactory nf; - - private int nestingOfFunction; - - private Decompiler decompiler; - private String encodedSource; - -// The following are per function variables and should be saved/restored -// during function parsing. -// XXX Move to separated class? - ScriptOrFnNode currentScriptOrFn; - Node.Scope currentScope; - private int nestingOfWith; - private Hashtable labelSet; // map of label names into nodes - private ObjArray loopSet; - private ObjArray loopAndSwitchSet; - private boolean hasReturnValue; - private int endFlags; -// end of per function variables - - /*APPJET*/public int lastConsumedTokenLine = -1; - - public int getCurrentLineNumber() { - return ts.getLineno(); - } - - // Exception to unwind - private static class ParserException extends RuntimeException - { - static final long serialVersionUID = 5882582646773765630L; - } - - public Parser(CompilerEnvirons compilerEnv, ErrorReporter errorReporter) - { - this.compilerEnv = compilerEnv; - this.errorReporter = errorReporter; - } - - protected Decompiler createDecompiler(CompilerEnvirons compilerEnv) - { - return new Decompiler(); - } - - void addStrictWarning(String messageId, String messageArg) - { - if (compilerEnv.isStrictMode()) - addWarning(messageId, messageArg); - } - - void addWarning(String messageId, String messageArg) - { - String message = ScriptRuntime.getMessage1(messageId, messageArg); - if (compilerEnv.reportWarningAsError()) { - ++syntaxErrorCount; - errorReporter.error(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } else - errorReporter.warning(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } - - void addError(String messageId) - { - ++syntaxErrorCount; - String message = ScriptRuntime.getMessage0(messageId); - errorReporter.error(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } - - void addError(String messageId, String messageArg) - { - ++syntaxErrorCount; - String message = ScriptRuntime.getMessage1(messageId, messageArg); - errorReporter.error(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } - - RuntimeException reportError(String messageId) - { - addError(messageId); - - // Throw a ParserException exception to unwind the recursive descent - // parse. - throw new ParserException(); - } - - /*APPJET*//*added method*/ - RuntimeException reportError(String messageId, String messageArg) - { - addError(messageId, messageArg); - - // Throw a ParserException exception to unwind the recursive descent - // parse. - throw new ParserException(); - } - - /*APPJET*//*no longer: private*/int peekToken() - throws IOException - { - int tt = currentFlaggedToken; - if (tt == Token.EOF) { - tt = ts.getToken(); - if (tt == Token.EOL) { - do { - tt = ts.getToken(); - } while (tt == Token.EOL); - tt |= TI_AFTER_EOL; - } - currentFlaggedToken = tt; - } - return tt & CLEAR_TI_MASK; - } - - private int peekFlaggedToken() - throws IOException - { - peekToken(); - return currentFlaggedToken; - } - - /*APPJET*//*no longer:private*/ void consumeToken() - { - currentFlaggedToken = Token.EOF; - /*APPJET*/lastConsumedTokenLine = ts.getLineno(); - } - - private int nextToken() - throws IOException - { - int tt = peekToken(); - consumeToken(); - return tt; - } - - private int nextFlaggedToken() - throws IOException - { - peekToken(); - int ttFlagged = currentFlaggedToken; - consumeToken(); - return ttFlagged; - } - - private boolean matchToken(int toMatch) - throws IOException - { - int tt = peekToken(); - if (tt != toMatch) { - return false; - } - consumeToken(); - return true; - } - - private int peekTokenOrEOL() - throws IOException - { - int tt = peekToken(); - // Check for last peeked token flags - if ((currentFlaggedToken & TI_AFTER_EOL) != 0) { - tt = Token.EOL; - } - return tt; - } - - private void setCheckForLabel() - { - if ((currentFlaggedToken & CLEAR_TI_MASK) != Token.NAME) - throw Kit.codeBug(); - currentFlaggedToken |= TI_CHECK_LABEL; - } - - private void mustMatchToken(int toMatch, String messageId) - throws IOException, ParserException - { - if (!matchToken(toMatch)) { - reportError(messageId); - } - } - - /*APPJET*//*added method*/ - private void mustMatchToken(int toMatch, String messageId, String messageArg) - throws IOException, ParserException - { - if (!matchToken(toMatch)) { - reportError(messageId, messageArg); - } - } - - private void mustHaveXML() - { - if (!compilerEnv.isXmlAvailable()) { - reportError("msg.XML.not.available"); - } - } - - public String getEncodedSource() - { - return encodedSource; - } - - public boolean eof() - { - return ts.eof(); - } - - boolean insideFunction() - { - return nestingOfFunction != 0; - } - - void pushScope(Node node) { - Node.Scope scopeNode = (Node.Scope) node; - if (scopeNode.getParentScope() != null) throw Kit.codeBug(); - scopeNode.setParent(currentScope); - currentScope = scopeNode; - } - - void popScope() { - currentScope = currentScope.getParentScope(); - } - - private Node enterLoop(Node loopLabel, boolean doPushScope) - { - Node loop = nf.createLoopNode(loopLabel, ts.getLineno()); - if (loopSet == null) { - loopSet = new ObjArray(); - if (loopAndSwitchSet == null) { - loopAndSwitchSet = new ObjArray(); - } - } - loopSet.push(loop); - loopAndSwitchSet.push(loop); - if (doPushScope) { - pushScope(loop); - } - return loop; - } - - private void exitLoop(boolean doPopScope) - { - loopSet.pop(); - loopAndSwitchSet.pop(); - if (doPopScope) { - popScope(); - } - } - - private Node enterSwitch(Node switchSelector, int lineno) - { - Node switchNode = nf.createSwitch(switchSelector, lineno); - if (loopAndSwitchSet == null) { - loopAndSwitchSet = new ObjArray(); - } - loopAndSwitchSet.push(switchNode); - return switchNode; - } - - private void exitSwitch() - { - loopAndSwitchSet.pop(); - } - - /* - * Build a parse tree from the given sourceString. - * - * @return an Object representing the parsed - * program. If the parse fails, null will be returned. (The - * parse failure will result in a call to the ErrorReporter from - * CompilerEnvirons.) - */ - public ScriptOrFnNode parse(String sourceString, - String sourceURI, int lineno) - { - this.sourceURI = sourceURI; - this.ts = new TokenStream(this, null, sourceString, lineno); - try { - return parse(); - } catch (IOException ex) { - // Should never happen - throw new IllegalStateException(); - } - } - - /* - * Build a parse tree from the given sourceString. - * - * @return an Object representing the parsed - * program. If the parse fails, null will be returned. (The - * parse failure will result in a call to the ErrorReporter from - * CompilerEnvirons.) - */ - public ScriptOrFnNode parse(Reader sourceReader, - String sourceURI, int lineno) - throws IOException - { - this.sourceURI = sourceURI; - this.ts = new TokenStream(this, sourceReader, null, lineno); - return parse(); - } - - private ScriptOrFnNode parse() - throws IOException - { - this.decompiler = createDecompiler(compilerEnv); - this.nf = new IRFactory(this); - currentScriptOrFn = nf.createScript(); - currentScope = currentScriptOrFn; - int sourceStartOffset = decompiler.getCurrentOffset(); - this.encodedSource = null; - decompiler.addToken(Token.SCRIPT); - - this.currentFlaggedToken = Token.EOF; - this.syntaxErrorCount = 0; - - int baseLineno = ts.getLineno(); // line number where source starts - - /*APPJET*/lastConsumedTokenLine = baseLineno; - - /* so we have something to add nodes to until - * we've collected all the source */ - Node pn = nf.createLeaf(Token.BLOCK); - - try { - for (;;) { - int tt = peekToken(); - - if (tt <= Token.EOF) { - break; - } - - Node n; - if (tt == Token.FUNCTION) { - consumeToken(); - try { - n = function(calledByCompileFunction - ? FunctionNode.FUNCTION_EXPRESSION - : FunctionNode.FUNCTION_STATEMENT); - } catch (ParserException e) { - break; - } - } else { - n = statement(); - } - nf.addChildToBack(pn, n); - } - } catch (StackOverflowError ex) { - String msg = ScriptRuntime.getMessage0( - "msg.too.deep.parser.recursion"); - throw Context.reportRuntimeError(msg, sourceURI, - ts.getLineno(), null, 0); - } - - if (this.syntaxErrorCount != 0) { - String msg = String.valueOf(this.syntaxErrorCount); - msg = ScriptRuntime.getMessage1("msg.got.syntax.errors", msg); - throw errorReporter.runtimeError(msg, sourceURI, baseLineno, - null, 0); - } - - currentScriptOrFn.setSourceName(sourceURI); - currentScriptOrFn.setBaseLineno(baseLineno); - currentScriptOrFn.setEndLineno(ts.getLineno()); - - int sourceEndOffset = decompiler.getCurrentOffset(); - currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset, - sourceEndOffset); - - nf.initScript(currentScriptOrFn, pn); - - if (compilerEnv.isGeneratingSource()) { - encodedSource = decompiler.getEncodedSource(); - } - this.decompiler = null; // It helps GC - - return currentScriptOrFn; - } - - /* - * The C version of this function takes an argument list, - * which doesn't seem to be needed for tree generation... - * it'd only be useful for checking argument hiding, which - * I'm not doing anyway... - */ - private Node parseFunctionBody() - throws IOException - { - ++nestingOfFunction; - Node pn = nf.createBlock(ts.getLineno()); - try { - bodyLoop: for (;;) { - Node n; - int tt = peekToken(); - switch (tt) { - case Token.ERROR: - case Token.EOF: - case Token.RC: - break bodyLoop; - - case Token.FUNCTION: - consumeToken(); - n = function(FunctionNode.FUNCTION_STATEMENT); - break; - default: - n = statement(); - break; - } - nf.addChildToBack(pn, n); - } - } catch (ParserException e) { - // Ignore it - } finally { - --nestingOfFunction; - } - - return pn; - } - - private Node function(int functionType) - throws IOException, ParserException - { - int syntheticType = functionType; - int baseLineno = ts.getLineno(); // line number where source starts - - int functionSourceStart = decompiler.markFunctionStart(functionType); - String name; - Node memberExprNode = null; - if (matchToken(Token.NAME)) { - name = ts.getString(); - decompiler.addName(name); - if (!matchToken(Token.LP)) { - if (compilerEnv.isAllowMemberExprAsFunctionName()) { - // Extension to ECMA: if 'function <name>' does not follow - // by '(', assume <name> starts memberExpr - Node memberExprHead = nf.createName(name); - name = ""; - memberExprNode = memberExprTail(false, memberExprHead); - } - mustMatchToken(Token.LP, "msg.no.paren.parms"); - } - } else if (matchToken(Token.LP)) { - // Anonymous function - name = ""; - } else { - name = ""; - if (compilerEnv.isAllowMemberExprAsFunctionName()) { - // Note that memberExpr can not start with '(' like - // in function (1+2).toString(), because 'function (' already - // processed as anonymous function - memberExprNode = memberExpr(false); - } - mustMatchToken(Token.LP, "msg.no.paren.parms"); - } - - if (memberExprNode != null) { - syntheticType = FunctionNode.FUNCTION_EXPRESSION; - } - - if (syntheticType != FunctionNode.FUNCTION_EXPRESSION && - name.length() > 0) - { - // Function statements define a symbol in the enclosing scope - defineSymbol(Token.FUNCTION, name); - } - - boolean nested = insideFunction(); - - FunctionNode fnNode = nf.createFunction(name); - if (nested || nestingOfWith > 0) { - // 1. Nested functions are not affected by the dynamic scope flag - // as dynamic scope is already a parent of their scope. - // 2. Functions defined under the with statement also immune to - // this setup, in which case dynamic scope is ignored in favor - // of with object. - fnNode.itsIgnoreDynamicScope = true; - } - int functionIndex = currentScriptOrFn.addFunction(fnNode); - - int functionSourceEnd; - - ScriptOrFnNode savedScriptOrFn = currentScriptOrFn; - currentScriptOrFn = fnNode; - Node.Scope savedCurrentScope = currentScope; - currentScope = fnNode; - int savedNestingOfWith = nestingOfWith; - nestingOfWith = 0; - Hashtable savedLabelSet = labelSet; - labelSet = null; - ObjArray savedLoopSet = loopSet; - loopSet = null; - ObjArray savedLoopAndSwitchSet = loopAndSwitchSet; - loopAndSwitchSet = null; - boolean savedHasReturnValue = hasReturnValue; - int savedFunctionEndFlags = endFlags; - - Node destructuring = null; - Node body; - try { - decompiler.addToken(Token.LP); - if (!matchToken(Token.RP)) { - boolean first = true; - do { - if (!first) - decompiler.addToken(Token.COMMA); - first = false; - int tt = peekToken(); - if (tt == Token.LB || tt == Token.LC) { - // Destructuring assignment for parameters: add a - // dummy parameter name, and add a statement to the - // body to initialize variables from the destructuring - // assignment - if (destructuring == null) { - destructuring = new Node(Token.COMMA); - } - String parmName = currentScriptOrFn.getNextTempName(); - defineSymbol(Token.LP, parmName); - destructuring.addChildToBack( - nf.createDestructuringAssignment(Token.VAR, - primaryExpr(), nf.createName(parmName))); - } else { - mustMatchToken(Token.NAME, "msg.no.parm"); - String s = ts.getString(); - defineSymbol(Token.LP, s); - decompiler.addName(s); - } - } while (matchToken(Token.COMMA)); - - mustMatchToken(Token.RP, "msg.no.paren.after.parms"); - } - decompiler.addToken(Token.RP); - - mustMatchToken(Token.LC, "msg.no.brace.body"); - decompiler.addEOL(Token.LC); - body = parseFunctionBody(); - if (destructuring != null) { - body.addChildToFront( - new Node(Token.EXPR_VOID, destructuring, ts.getLineno())); - } - mustMatchToken(Token.RC, "msg.no.brace.after.body"); - - if (compilerEnv.isStrictMode() && !body.hasConsistentReturnUsage()) - { - String msg = name.length() > 0 ? "msg.no.return.value" - : "msg.anon.no.return.value"; - addStrictWarning(msg, name); - } - - if (syntheticType == FunctionNode.FUNCTION_EXPRESSION && - name.length() > 0 && currentScope.getSymbol(name) == null) - { - // Function expressions define a name only in the body of the - // function, and only if not hidden by a parameter name - defineSymbol(Token.FUNCTION, name); - } - - decompiler.addToken(Token.RC); - functionSourceEnd = decompiler.markFunctionEnd(functionSourceStart); - if (functionType != FunctionNode.FUNCTION_EXPRESSION) { - // Add EOL only if function is not part of expression - // since it gets SEMI + EOL from Statement in that case - decompiler.addToken(Token.EOL); - } - } - finally { - hasReturnValue = savedHasReturnValue; - endFlags = savedFunctionEndFlags; - loopAndSwitchSet = savedLoopAndSwitchSet; - loopSet = savedLoopSet; - labelSet = savedLabelSet; - nestingOfWith = savedNestingOfWith; - currentScriptOrFn = savedScriptOrFn; - currentScope = savedCurrentScope; - } - - fnNode.setEncodedSourceBounds(functionSourceStart, functionSourceEnd); - fnNode.setSourceName(sourceURI); - fnNode.setBaseLineno(baseLineno); - fnNode.setEndLineno(ts.getLineno()); - - Node pn = nf.initFunction(fnNode, functionIndex, body, syntheticType); - if (memberExprNode != null) { - pn = nf.createAssignment(Token.ASSIGN, memberExprNode, pn); - if (functionType != FunctionNode.FUNCTION_EXPRESSION) { - // XXX check JScript behavior: should it be createExprStatement? - pn = nf.createExprStatementNoReturn(pn, baseLineno); - } - } - return pn; - } - - private Node statements(Node scope) - throws IOException - { - Node pn = scope != null ? scope : nf.createBlock(ts.getLineno()); - - int tt; - while ((tt = peekToken()) > Token.EOF && tt != Token.RC) { - nf.addChildToBack(pn, statement()); - } - - return pn; - } - - private Node condition() - throws IOException, ParserException - { - mustMatchToken(Token.LP, "msg.no.paren.cond"); - decompiler.addToken(Token.LP); - Node pn = expr(false); - mustMatchToken(Token.RP, "msg.no.paren.after.cond"); - decompiler.addToken(Token.RP); - - // Report strict warning on code like "if (a = 7) ...". Suppress the - // warning if the condition is parenthesized, like "if ((a = 7)) ...". - if (pn.getProp(Node.PARENTHESIZED_PROP) == null && - (pn.getType() == Token.SETNAME || pn.getType() == Token.SETPROP || - pn.getType() == Token.SETELEM)) - { - addStrictWarning("msg.equal.as.assign", ""); - } - return pn; - } - - // match a NAME; return null if no match. - private Node matchJumpLabelName() - throws IOException, ParserException - { - Node label = null; - - int tt = peekTokenOrEOL(); - if (tt == Token.NAME) { - consumeToken(); - String name = ts.getString(); - decompiler.addName(name); - if (labelSet != null) { - label = (Node)labelSet.get(name); - } - if (label == null) { - reportError("msg.undef.label"); - } - } - - return label; - } - - private Node statement() - throws IOException - { - try { - Node pn = statementHelper(null); - if (pn != null) { - if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) - addStrictWarning("msg.no.side.effects", ""); - return pn; - } - } catch (ParserException e) { } - - // skip to end of statement - int lineno = ts.getLineno(); - guessingStatementEnd: for (;;) { - int tt = peekTokenOrEOL(); - consumeToken(); - switch (tt) { - case Token.ERROR: - case Token.EOF: - case Token.EOL: - case Token.SEMI: - break guessingStatementEnd; - } - } - return nf.createExprStatement(nf.createName("error"), lineno); - } - - /*APPJET*/ /*begin*/ - private Node statementHelper(Node statementLabel) - throws IOException, ParserException { - - Node pn = statementHelper0(statementLabel); - if (pn != null && pn.getType() != Token.BLOCK && pn.getType() != Token.LOOP) { - pn.statementEndLineNum = lastConsumedTokenLine; - } - return pn; - } - /*end*/ - - private Node statementHelper0(Node statementLabel) /*APPJET*/ - throws IOException, ParserException - { - Node pn = null; - int tt = peekToken(); - - switch (tt) { - case Token.IF: { - consumeToken(); - - decompiler.addToken(Token.IF); - int lineno = ts.getLineno(); - Node cond = condition(); - /*APPJET*/cond.lineno = lineno; - /*APPJET*/cond.statementEndLineNum = lastConsumedTokenLine; - decompiler.addEOL(Token.LC); - Node ifTrue = statement(); - Node ifFalse = null; - if (matchToken(Token.ELSE)) { - decompiler.addToken(Token.RC); - decompiler.addToken(Token.ELSE); - decompiler.addEOL(Token.LC); - ifFalse = statement(); - } - decompiler.addEOL(Token.RC); - pn = nf.createIf(cond, ifTrue, ifFalse, lineno); - return pn; - } - - case Token.SWITCH: { - consumeToken(); - - decompiler.addToken(Token.SWITCH); - int lineno = ts.getLineno(); - mustMatchToken(Token.LP, "msg.no.paren.switch"); - decompiler.addToken(Token.LP); - /*APPJET*/Node toSwitchOn = expr(false); - /*APPJET*/toSwitchOn.lineno = lineno; - /*APPJET*/toSwitchOn.statementEndLineNum = lastConsumedTokenLine; - pn = enterSwitch(toSwitchOn, lineno); /*APPJET*/ - try { - mustMatchToken(Token.RP, "msg.no.paren.after.switch"); - decompiler.addToken(Token.RP); - mustMatchToken(Token.LC, "msg.no.brace.switch"); - decompiler.addEOL(Token.LC); - - boolean hasDefault = false; - switchLoop: for (;;) { - tt = nextToken(); - Node caseExpression; - switch (tt) { - case Token.RC: - break switchLoop; - - case Token.CASE: - decompiler.addToken(Token.CASE); - caseExpression = expr(false); - mustMatchToken(Token.COLON, "msg.no.colon.case"); - decompiler.addEOL(Token.COLON); - break; - - case Token.DEFAULT: - if (hasDefault) { - reportError("msg.double.switch.default"); - } - decompiler.addToken(Token.DEFAULT); - hasDefault = true; - caseExpression = null; - mustMatchToken(Token.COLON, "msg.no.colon.case"); - decompiler.addEOL(Token.COLON); - break; - - default: - reportError("msg.bad.switch"); - break switchLoop; - } - - Node block = nf.createLeaf(Token.BLOCK); - while ((tt = peekToken()) != Token.RC - && tt != Token.CASE - && tt != Token.DEFAULT - && tt != Token.EOF) - { - nf.addChildToBack(block, statement()); - } - - // caseExpression == null => add default label - nf.addSwitchCase(pn, caseExpression, block); - } - decompiler.addEOL(Token.RC); - nf.closeSwitch(pn); - } finally { - exitSwitch(); - } - return pn; - } - - case Token.WHILE: { - consumeToken(); - decompiler.addToken(Token.WHILE); - - Node loop = enterLoop(statementLabel, true); - try { - /*APPJET*/int lineno = ts.getLineno(); - Node cond = condition(); - /*APPJET*/cond.lineno = lineno; - /*APPJET*/cond.statementEndLineNum = lastConsumedTokenLine; - decompiler.addEOL(Token.LC); - Node body = statement(); - decompiler.addEOL(Token.RC); - pn = nf.createWhile(loop, cond, body); - } finally { - exitLoop(true); - } - return pn; - } - - case Token.DO: { - consumeToken(); - decompiler.addToken(Token.DO); - decompiler.addEOL(Token.LC); - - Node loop = enterLoop(statementLabel, true); - try { - Node body = statement(); - decompiler.addToken(Token.RC); - mustMatchToken(Token.WHILE, "msg.no.while.do"); - decompiler.addToken(Token.WHILE); - Node cond = condition(); - pn = nf.createDoWhile(loop, body, cond); - } finally { - exitLoop(true); - } - // Always auto-insert semicolon to follow SpiderMonkey: - // It is required by ECMAScript but is ignored by the rest of - // world, see bug 238945 - matchToken(Token.SEMI); - decompiler.addEOL(Token.SEMI); - return pn; - } - - case Token.FOR: { - consumeToken(); - boolean isForEach = false; - decompiler.addToken(Token.FOR); - - Node loop = enterLoop(statementLabel, true); - try { - Node init; // Node init is also foo in 'foo in object' - Node cond; // Node cond is also object in 'foo in object' - Node incr = null; - Node body; - int declType = -1; - - // See if this is a for each () instead of just a for () - if (matchToken(Token.NAME)) { - decompiler.addName(ts.getString()); - if (ts.getString().equals("each")) { - isForEach = true; - } else { - reportError("msg.no.paren.for"); - } - } - - mustMatchToken(Token.LP, "msg.no.paren.for"); - decompiler.addToken(Token.LP); - tt = peekToken(); - if (tt == Token.SEMI) { - init = nf.createLeaf(Token.EMPTY); - } else { - if (tt == Token.VAR || tt == Token.LET) { - // set init to a var list or initial - consumeToken(); // consume the token - decompiler.addToken(tt); - init = variables(true, tt); - declType = tt; - } - else { - init = expr(true); - } - } - - if (matchToken(Token.IN)) { - decompiler.addToken(Token.IN); - // 'cond' is the object over which we're iterating - cond = expr(false); - } else { // ordinary for loop - mustMatchToken(Token.SEMI, "msg.no.semi.for"); - decompiler.addToken(Token.SEMI); - if (peekToken() == Token.SEMI) { - // no loop condition - cond = nf.createLeaf(Token.EMPTY); - } else { - cond = expr(false); - } - - mustMatchToken(Token.SEMI, "msg.no.semi.for.cond"); - decompiler.addToken(Token.SEMI); - if (peekToken() == Token.RP) { - incr = nf.createLeaf(Token.EMPTY); - } else { - incr = expr(false); - } - } - - mustMatchToken(Token.RP, "msg.no.paren.for.ctrl"); - decompiler.addToken(Token.RP); - decompiler.addEOL(Token.LC); - /*APPJET*/int parenEndLine = lastConsumedTokenLine; - body = statement(); - decompiler.addEOL(Token.RC); - - if (incr == null) { - // cond could be null if 'in obj' got eaten - // by the init node. - pn = nf.createForIn(declType, loop, init, cond, body, - isForEach); - } else { - pn = nf.createFor(loop, init, cond, incr, body); - } - /*APPJET*/ // use the LOOP object to hold the range of the paren'd expr - /*APPJET*/pn.statementEndLineNum = parenEndLine; - } finally { - exitLoop(true); - } - return pn; - } - - case Token.TRY: { - consumeToken(); - int lineno = ts.getLineno(); - - Node tryblock; - Node catchblocks = null; - Node finallyblock = null; - - decompiler.addToken(Token.TRY); - if (peekToken() != Token.LC) { - reportError("msg.no.brace.try"); - } - decompiler.addEOL(Token.LC); - tryblock = statement(); - decompiler.addEOL(Token.RC); - - catchblocks = nf.createLeaf(Token.BLOCK); - - boolean sawDefaultCatch = false; - int peek = peekToken(); - if (peek == Token.CATCH) { - while (matchToken(Token.CATCH)) { - if (sawDefaultCatch) { - reportError("msg.catch.unreachable"); - } - decompiler.addToken(Token.CATCH); - mustMatchToken(Token.LP, "msg.no.paren.catch"); - decompiler.addToken(Token.LP); - - mustMatchToken(Token.NAME, "msg.bad.catchcond"); - String varName = ts.getString(); - decompiler.addName(varName); - - Node catchCond = null; - if (matchToken(Token.IF)) { - decompiler.addToken(Token.IF); - catchCond = expr(false); - } else { - sawDefaultCatch = true; - } - - mustMatchToken(Token.RP, "msg.bad.catchcond"); - decompiler.addToken(Token.RP); - mustMatchToken(Token.LC, "msg.no.brace.catchblock"); - decompiler.addEOL(Token.LC); - - nf.addChildToBack(catchblocks, - nf.createCatch(varName, catchCond, - statements(null), - ts.getLineno())); - - mustMatchToken(Token.RC, "msg.no.brace.after.body"); - decompiler.addEOL(Token.RC); - } - } else if (peek != Token.FINALLY) { - mustMatchToken(Token.FINALLY, "msg.try.no.catchfinally"); - } - - if (matchToken(Token.FINALLY)) { - decompiler.addToken(Token.FINALLY); - decompiler.addEOL(Token.LC); - finallyblock = statement(); - decompiler.addEOL(Token.RC); - } - - pn = nf.createTryCatchFinally(tryblock, catchblocks, - finallyblock, lineno); - - return pn; - } - - case Token.THROW: { - consumeToken(); - if (peekTokenOrEOL() == Token.EOL) { - // ECMAScript does not allow new lines before throw expression, - // see bug 256617 - reportError("msg.bad.throw.eol"); - } - - int lineno = ts.getLineno(); - decompiler.addToken(Token.THROW); - pn = nf.createThrow(expr(false), lineno); - break; - } - - case Token.BREAK: { - consumeToken(); - int lineno = ts.getLineno(); - - decompiler.addToken(Token.BREAK); - - // matchJumpLabelName only matches if there is one - Node breakStatement = matchJumpLabelName(); - if (breakStatement == null) { - if (loopAndSwitchSet == null || loopAndSwitchSet.size() == 0) { - reportError("msg.bad.break"); - return null; - } - breakStatement = (Node)loopAndSwitchSet.peek(); - } - pn = nf.createBreak(breakStatement, lineno); - break; - } - - case Token.CONTINUE: { - consumeToken(); - int lineno = ts.getLineno(); - - decompiler.addToken(Token.CONTINUE); - - Node loop; - // matchJumpLabelName only matches if there is one - Node label = matchJumpLabelName(); - if (label == null) { - if (loopSet == null || loopSet.size() == 0) { - reportError("msg.continue.outside"); - return null; - } - loop = (Node)loopSet.peek(); - } else { - loop = nf.getLabelLoop(label); - if (loop == null) { - reportError("msg.continue.nonloop"); - return null; - } - } - pn = nf.createContinue(loop, lineno); - break; - } - - case Token.WITH: { - consumeToken(); - - decompiler.addToken(Token.WITH); - int lineno = ts.getLineno(); - mustMatchToken(Token.LP, "msg.no.paren.with"); - decompiler.addToken(Token.LP); - Node obj = expr(false); - /*APPJET*/obj.lineno = lineno; - /*APPJET*/obj.statementEndLineNum = lastConsumedTokenLine; - mustMatchToken(Token.RP, "msg.no.paren.after.with"); - decompiler.addToken(Token.RP); - decompiler.addEOL(Token.LC); - - ++nestingOfWith; - Node body; - try { - body = statement(); - } finally { - --nestingOfWith; - } - - decompiler.addEOL(Token.RC); - - pn = nf.createWith(obj, body, lineno); - return pn; - } - - case Token.CONST: - case Token.VAR: { - consumeToken(); - decompiler.addToken(tt); - pn = variables(false, tt); - break; - } - - case Token.LET: { - consumeToken(); - decompiler.addToken(Token.LET); - if (peekToken() == Token.LP) { - pn = let(true); - } else { - pn = variables(false, tt); - } - return pn; - } - - case Token.RETURN: - case Token.YIELD: { - pn = returnOrYield(tt, false); - break; - } - - case Token.DEBUGGER: - consumeToken(); - decompiler.addToken(Token.DEBUGGER); - pn = nf.createDebugger(ts.getLineno()); - break; - - case Token.LC: - consumeToken(); - if (statementLabel != null) { - decompiler.addToken(Token.LC); - } - Node scope = nf.createScopeNode(Token.BLOCK, ts.getLineno()); - pushScope(scope); - try { - statements(scope); - mustMatchToken(Token.RC, "msg.no.brace.block"); - if (statementLabel != null) { - decompiler.addEOL(Token.RC); - } - return scope; - } finally { - popScope(); - } - - case Token.ERROR: - // Fall thru, to have a node for error recovery to work on - case Token.SEMI: - consumeToken(); - pn = nf.createLeaf(Token.EMPTY); - return pn; - - case Token.FUNCTION: { - consumeToken(); - pn = function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT); - return pn; - } - - case Token.DEFAULT : - consumeToken(); - mustHaveXML(); - - decompiler.addToken(Token.DEFAULT); - int nsLine = ts.getLineno(); - - if (!(matchToken(Token.NAME) - && ts.getString().equals("xml"))) - { - reportError("msg.bad.namespace"); - } - decompiler.addName(" xml"); - - if (!(matchToken(Token.NAME) - && ts.getString().equals("namespace"))) - { - reportError("msg.bad.namespace"); - } - decompiler.addName(" namespace"); - - if (!matchToken(Token.ASSIGN)) { - reportError("msg.bad.namespace"); - } - decompiler.addToken(Token.ASSIGN); - - Node expr = expr(false); - pn = nf.createDefaultNamespace(expr, nsLine); - break; - - case Token.NAME: { - int lineno = ts.getLineno(); - String name = ts.getString(); - setCheckForLabel(); - pn = expr(false); - if (pn.getType() != Token.LABEL) { - pn = nf.createExprStatement(pn, lineno); - } else { - // Parsed the label: push back token should be - // colon that primaryExpr left untouched. - if (peekToken() != Token.COLON) Kit.codeBug(); - consumeToken(); - // depend on decompiling lookahead to guess that that - // last name was a label. - decompiler.addName(name); - decompiler.addEOL(Token.COLON); - - if (labelSet == null) { - labelSet = new Hashtable(); - } else if (labelSet.containsKey(name)) { - reportError("msg.dup.label"); - } - - boolean firstLabel; - if (statementLabel == null) { - firstLabel = true; - statementLabel = pn; - } else { - // Discard multiple label nodes and use only - // the first: it allows to simplify IRFactory - firstLabel = false; - } - labelSet.put(name, statementLabel); - try { - pn = statementHelper(statementLabel); - } finally { - labelSet.remove(name); - } - if (firstLabel) { - pn = nf.createLabeledStatement(statementLabel, pn); - } - return pn; - } - break; - } - - default: { - int lineno = ts.getLineno(); - pn = expr(false); - pn = nf.createExprStatement(pn, lineno); - break; - } - } - - int ttFlagged = peekFlaggedToken(); - switch (ttFlagged & CLEAR_TI_MASK) { - case Token.SEMI: - // Consume ';' as a part of expression - consumeToken(); - break; - case Token.ERROR: - case Token.EOF: - case Token.RC: - // Autoinsert ; - break; - default: - if ((ttFlagged & TI_AFTER_EOL) == 0) { - // Report error if no EOL or autoinsert ; otherwise - reportError("msg.no.semi.stmt"); - } - break; - } - decompiler.addEOL(Token.SEMI); - - return pn; - } - - /** - * Returns whether or not the bits in the mask have changed to all set. - * @param before bits before change - * @param after bits after change - * @param mask mask for bits - * @return true if all the bits in the mask are set in "after" but not - * "before" - */ - private static final boolean nowAllSet(int before, int after, int mask) - { - return ((before & mask) != mask) && ((after & mask) == mask); - } - - private Node returnOrYield(int tt, boolean exprContext) - throws IOException, ParserException - { - if (!insideFunction()) { - reportError(tt == Token.RETURN ? "msg.bad.return" - : "msg.bad.yield"); - } - consumeToken(); - decompiler.addToken(tt); - int lineno = ts.getLineno(); - - Node e; - /* This is ugly, but we don't want to require a semicolon. */ - switch (peekTokenOrEOL()) { - case Token.SEMI: - case Token.RC: - case Token.EOF: - case Token.EOL: - case Token.ERROR: - case Token.RB: - case Token.RP: - case Token.YIELD: - e = null; - break; - default: - e = expr(false); - break; - } - - int before = endFlags; - Node ret; - - if (tt == Token.RETURN) { - if (e == null ) { - endFlags |= Node.END_RETURNS; - } else { - endFlags |= Node.END_RETURNS_VALUE; - hasReturnValue = true; - } - ret = nf.createReturn(e, lineno); - - // see if we need a strict mode warning - if (nowAllSet(before, endFlags, - Node.END_RETURNS|Node.END_RETURNS_VALUE)) - { - addStrictWarning("msg.return.inconsistent", ""); - } - } else { - endFlags |= Node.END_YIELDS; - ret = nf.createYield(e, lineno); - if (!exprContext) - ret = new Node(Token.EXPR_VOID, ret, lineno); - } - - // see if we are mixing yields and value returns. - if (nowAllSet(before, endFlags, - Node.END_YIELDS|Node.END_RETURNS_VALUE)) - { - String name = ((FunctionNode)currentScriptOrFn).getFunctionName(); - if (name.length() == 0) - addError("msg.anon.generator.returns", ""); - else - addError("msg.generator.returns", name); - } - - return ret; - } - - /** - * Parse a 'var' or 'const' statement, or a 'var' init list in a for - * statement. - * @param inFor true if we are currently in the midst of the init - * clause of a for. - * @param inStatement true if called in a statement (as opposed to an - * expression) context - * @param declType A token value: either VAR, CONST, or LET depending on - * context. - * @return The parsed statement - * @throws IOException - * @throws ParserException - */ - private Node variables(boolean inFor, int declType) - throws IOException, ParserException - { - Node result = nf.createVariables(declType, ts.getLineno()); - boolean first = true; - for (;;) { - Node destructuring = null; - String s = null; - int tt = peekToken(); - if (tt == Token.LB || tt == Token.LC) { - // Destructuring assignment, e.g., var [a,b] = ... - destructuring = primaryExpr(); - } else { - // Simple variable name - mustMatchToken(Token.NAME, "msg.bad.var", - Token.name(declType).toLowerCase()); - s = ts.getString(); - - if (!first) - decompiler.addToken(Token.COMMA); - first = false; - - decompiler.addName(s); - defineSymbol(declType, s); - } - - Node init = null; - if (matchToken(Token.ASSIGN)) { - decompiler.addToken(Token.ASSIGN); - init = assignExpr(inFor); - } - - if (destructuring != null) { - if (init == null) { - if (!inFor) - reportError("msg.destruct.assign.no.init"); - nf.addChildToBack(result, destructuring); - } else { - nf.addChildToBack(result, - nf.createDestructuringAssignment(declType, - destructuring, init)); - } - } else { - Node name = nf.createName(s); - if (init != null) - nf.addChildToBack(name, init); - nf.addChildToBack(result, name); - } - - if (!matchToken(Token.COMMA)) - break; - } - return result; - } - - - private Node let(boolean isStatement) - throws IOException, ParserException - { - mustMatchToken(Token.LP, "msg.no.paren.after.let"); - decompiler.addToken(Token.LP); - Node result = nf.createScopeNode(Token.LET, ts.getLineno()); - pushScope(result); - try { - Node vars = variables(false, Token.LET); - nf.addChildToBack(result, vars); - mustMatchToken(Token.RP, "msg.no.paren.let"); - decompiler.addToken(Token.RP); - if (isStatement && peekToken() == Token.LC) { - // let statement - consumeToken(); - decompiler.addEOL(Token.LC); - nf.addChildToBack(result, statements(null)); - mustMatchToken(Token.RC, "msg.no.curly.let"); - decompiler.addToken(Token.RC); - } else { - // let expression - result.setType(Token.LETEXPR); - nf.addChildToBack(result, expr(false)); - if (isStatement) { - // let expression in statement context - result = nf.createExprStatement(result, ts.getLineno()); - } - } - } finally { - popScope(); - } - return result; - } - - void defineSymbol(int declType, String name) { - Node.Scope definingScope = currentScope.getDefiningScope(name); - Node.Scope.Symbol symbol = definingScope != null - ? definingScope.getSymbol(name) - : null; - boolean error = false; - if (symbol != null && (symbol.declType == Token.CONST || - declType == Token.CONST)) - { - error = true; - } else { - switch (declType) { - case Token.LET: - if (symbol != null && definingScope == currentScope) { - error = symbol.declType == Token.LET; - } - currentScope.putSymbol(name, - new Node.Scope.Symbol(declType, name)); - break; - - case Token.VAR: - case Token.CONST: - case Token.FUNCTION: - if (symbol != null) { - if (symbol.declType == Token.VAR) - addStrictWarning("msg.var.redecl", name); - else if (symbol.declType == Token.LP) { - addStrictWarning("msg.var.hides.arg", name); - } - } else { - currentScriptOrFn.putSymbol(name, - new Node.Scope.Symbol(declType, name)); - } - break; - - case Token.LP: - if (symbol != null) { - // must be duplicate parameter. Second parameter hides the - // first, so go ahead and add the second pararameter - addWarning("msg.dup.parms", name); - } - currentScriptOrFn.putSymbol(name, - new Node.Scope.Symbol(declType, name)); - break; - - default: - throw Kit.codeBug(); - } - } - if (error) { - addError(symbol.declType == Token.CONST ? "msg.const.redecl" : - symbol.declType == Token.LET ? "msg.let.redecl" : - symbol.declType == Token.VAR ? "msg.var.redecl" : - symbol.declType == Token.FUNCTION ? "msg.fn.redecl" : - "msg.parm.redecl", name); - } - } - - private Node expr(boolean inForInit) - throws IOException, ParserException - { - Node pn = assignExpr(inForInit); - while (matchToken(Token.COMMA)) { - decompiler.addToken(Token.COMMA); - if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) - addStrictWarning("msg.no.side.effects", ""); - if (peekToken() == Token.YIELD) { - reportError("msg.yield.parenthesized"); - } - pn = nf.createBinary(Token.COMMA, pn, assignExpr(inForInit)); - } - return pn; - } - - private Node assignExpr(boolean inForInit) - throws IOException, ParserException - { - int tt = peekToken(); - if (tt == Token.YIELD) { - consumeToken(); - return returnOrYield(tt, true); - } - Node pn = condExpr(inForInit); - - tt = peekToken(); - if (Token.FIRST_ASSIGN <= tt && tt <= Token.LAST_ASSIGN) { - consumeToken(); - decompiler.addToken(tt); - pn = nf.createAssignment(tt, pn, assignExpr(inForInit)); - } - - return pn; - } - - private Node condExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = orExpr(inForInit); - - if (matchToken(Token.HOOK)) { - decompiler.addToken(Token.HOOK); - Node ifTrue = assignExpr(false); - mustMatchToken(Token.COLON, "msg.no.colon.cond"); - decompiler.addToken(Token.COLON); - Node ifFalse = assignExpr(inForInit); - return nf.createCondExpr(pn, ifTrue, ifFalse); - } - - return pn; - } - - private Node orExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = andExpr(inForInit); - if (matchToken(Token.OR)) { - decompiler.addToken(Token.OR); - pn = nf.createBinary(Token.OR, pn, orExpr(inForInit)); - } - - return pn; - } - - private Node andExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = bitOrExpr(inForInit); - if (matchToken(Token.AND)) { - decompiler.addToken(Token.AND); - pn = nf.createBinary(Token.AND, pn, andExpr(inForInit)); - } - - return pn; - } - - private Node bitOrExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = bitXorExpr(inForInit); - while (matchToken(Token.BITOR)) { - decompiler.addToken(Token.BITOR); - pn = nf.createBinary(Token.BITOR, pn, bitXorExpr(inForInit)); - } - return pn; - } - - private Node bitXorExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = bitAndExpr(inForInit); - while (matchToken(Token.BITXOR)) { - decompiler.addToken(Token.BITXOR); - pn = nf.createBinary(Token.BITXOR, pn, bitAndExpr(inForInit)); - } - return pn; - } - - private Node bitAndExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = eqExpr(inForInit); - while (matchToken(Token.BITAND)) { - decompiler.addToken(Token.BITAND); - pn = nf.createBinary(Token.BITAND, pn, eqExpr(inForInit)); - } - return pn; - } - - private Node eqExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = relExpr(inForInit); - for (;;) { - int tt = peekToken(); - switch (tt) { - case Token.EQ: - case Token.NE: - case Token.SHEQ: - case Token.SHNE: - consumeToken(); - int decompilerToken = tt; - int parseToken = tt; - if (compilerEnv.getLanguageVersion() == Context.VERSION_1_2) { - // JavaScript 1.2 uses shallow equality for == and != . - // In addition, convert === and !== for decompiler into - // == and != since the decompiler is supposed to show - // canonical source and in 1.2 ===, !== are allowed - // only as an alias to ==, !=. - switch (tt) { - case Token.EQ: - parseToken = Token.SHEQ; - break; - case Token.NE: - parseToken = Token.SHNE; - break; - case Token.SHEQ: - decompilerToken = Token.EQ; - break; - case Token.SHNE: - decompilerToken = Token.NE; - break; - } - } - decompiler.addToken(decompilerToken); - pn = nf.createBinary(parseToken, pn, relExpr(inForInit)); - continue; - } - break; - } - return pn; - } - - private Node relExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = shiftExpr(); - for (;;) { - int tt = peekToken(); - switch (tt) { - case Token.IN: - if (inForInit) - break; - // fall through - case Token.INSTANCEOF: - case Token.LE: - case Token.LT: - case Token.GE: - case Token.GT: - consumeToken(); - decompiler.addToken(tt); - pn = nf.createBinary(tt, pn, shiftExpr()); - continue; - } - break; - } - return pn; - } - - private Node shiftExpr() - throws IOException, ParserException - { - Node pn = addExpr(); - for (;;) { - int tt = peekToken(); - switch (tt) { - case Token.LSH: - case Token.URSH: - case Token.RSH: - consumeToken(); - decompiler.addToken(tt); - pn = nf.createBinary(tt, pn, addExpr()); - continue; - } - break; - } - return pn; - } - - private Node addExpr() - throws IOException, ParserException - { - Node pn = mulExpr(); - for (;;) { - int tt = peekToken(); - if (tt == Token.ADD || tt == Token.SUB) { - consumeToken(); - decompiler.addToken(tt); - // flushNewLines - pn = nf.createBinary(tt, pn, mulExpr()); - continue; - } - break; - } - - return pn; - } - - private Node mulExpr() - throws IOException, ParserException - { - Node pn = unaryExpr(); - for (;;) { - int tt = peekToken(); - switch (tt) { - case Token.MUL: - case Token.DIV: - case Token.MOD: - consumeToken(); - decompiler.addToken(tt); - pn = nf.createBinary(tt, pn, unaryExpr()); - continue; - } - break; - } - - return pn; - } - - private Node unaryExpr() - throws IOException, ParserException - { - int tt; - - tt = peekToken(); - - switch(tt) { - case Token.VOID: - case Token.NOT: - case Token.BITNOT: - case Token.TYPEOF: - consumeToken(); - decompiler.addToken(tt); - return nf.createUnary(tt, unaryExpr()); - - case Token.ADD: - consumeToken(); - // Convert to special POS token in decompiler and parse tree - decompiler.addToken(Token.POS); - return nf.createUnary(Token.POS, unaryExpr()); - - case Token.SUB: - consumeToken(); - // Convert to special NEG token in decompiler and parse tree - decompiler.addToken(Token.NEG); - return nf.createUnary(Token.NEG, unaryExpr()); - - case Token.INC: - case Token.DEC: - consumeToken(); - decompiler.addToken(tt); - return nf.createIncDec(tt, false, memberExpr(true)); - - case Token.DELPROP: - consumeToken(); - decompiler.addToken(Token.DELPROP); - return nf.createUnary(Token.DELPROP, unaryExpr()); - - case Token.ERROR: - consumeToken(); - break; - - // XML stream encountered in expression. - case Token.LT: - if (compilerEnv.isXmlAvailable()) { - consumeToken(); - Node pn = xmlInitializer(); - return memberExprTail(true, pn); - } - // Fall thru to the default handling of RELOP - - default: - Node pn = memberExpr(true); - - // Don't look across a newline boundary for a postfix incop. - tt = peekTokenOrEOL(); - if (tt == Token.INC || tt == Token.DEC) { - consumeToken(); - decompiler.addToken(tt); - return nf.createIncDec(tt, true, pn); - } - return pn; - } - return nf.createName("error"); // Only reached on error.Try to continue. - - } - - private Node xmlInitializer() throws IOException - { - int tt = ts.getFirstXMLToken(); - if (tt != Token.XML && tt != Token.XMLEND) { - reportError("msg.syntax"); - return null; - } - - /* Make a NEW node to append to. */ - Node pnXML = nf.createLeaf(Token.NEW); - - String xml = ts.getString(); - boolean fAnonymous = xml.trim().startsWith("<>"); - - Node pn = nf.createName(fAnonymous ? "XMLList" : "XML"); - nf.addChildToBack(pnXML, pn); - - pn = null; - Node expr; - for (;;tt = ts.getNextXMLToken()) { - switch (tt) { - case Token.XML: - xml = ts.getString(); - decompiler.addName(xml); - mustMatchToken(Token.LC, "msg.syntax"); - decompiler.addToken(Token.LC); - expr = (peekToken() == Token.RC) - ? nf.createString("") - : expr(false); - mustMatchToken(Token.RC, "msg.syntax"); - decompiler.addToken(Token.RC); - if (pn == null) { - pn = nf.createString(xml); - } else { - pn = nf.createBinary(Token.ADD, pn, nf.createString(xml)); - } - if (ts.isXMLAttribute()) { - /* Need to put the result in double quotes */ - expr = nf.createUnary(Token.ESCXMLATTR, expr); - Node prepend = nf.createBinary(Token.ADD, - nf.createString("\""), - expr); - expr = nf.createBinary(Token.ADD, - prepend, - nf.createString("\"")); - } else { - expr = nf.createUnary(Token.ESCXMLTEXT, expr); - } - pn = nf.createBinary(Token.ADD, pn, expr); - break; - case Token.XMLEND: - xml = ts.getString(); - decompiler.addName(xml); - if (pn == null) { - pn = nf.createString(xml); - } else { - pn = nf.createBinary(Token.ADD, pn, nf.createString(xml)); - } - - nf.addChildToBack(pnXML, pn); - return pnXML; - default: - reportError("msg.syntax"); - return null; - } - } - } - - private void argumentList(Node listNode) - throws IOException, ParserException - { - boolean matched; - matched = matchToken(Token.RP); - if (!matched) { - boolean first = true; - do { - if (!first) - decompiler.addToken(Token.COMMA); - first = false; - if (peekToken() == Token.YIELD) { - reportError("msg.yield.parenthesized"); - } - nf.addChildToBack(listNode, assignExpr(false)); - } while (matchToken(Token.COMMA)); - - mustMatchToken(Token.RP, "msg.no.paren.arg"); - } - decompiler.addToken(Token.RP); - } - - private Node memberExpr(boolean allowCallSyntax) - throws IOException, ParserException - { - int tt; - - Node pn; - - /* Check for new expressions. */ - tt = peekToken(); - if (tt == Token.NEW) { - /* Eat the NEW token. */ - consumeToken(); - decompiler.addToken(Token.NEW); - - /* Make a NEW node to append to. */ - pn = nf.createCallOrNew(Token.NEW, memberExpr(false)); - - if (matchToken(Token.LP)) { - decompiler.addToken(Token.LP); - /* Add the arguments to pn, if any are supplied. */ - argumentList(pn); - } - - /* XXX there's a check in the C source against - * "too many constructor arguments" - how many - * do we claim to support? - */ - - /* Experimental syntax: allow an object literal to follow a new expression, - * which will mean a kind of anonymous class built with the JavaAdapter. - * the object literal will be passed as an additional argument to the constructor. - */ - tt = peekToken(); - if (tt == Token.LC) { - nf.addChildToBack(pn, primaryExpr()); - } - } else { - pn = primaryExpr(); - } - - return memberExprTail(allowCallSyntax, pn); - } - - private Node memberExprTail(boolean allowCallSyntax, Node pn) - throws IOException, ParserException - { - tailLoop: - for (;;) { - int tt = peekToken(); - switch (tt) { - - case Token.DOT: - case Token.DOTDOT: - { - int memberTypeFlags; - String s; - - consumeToken(); - decompiler.addToken(tt); - memberTypeFlags = 0; - if (tt == Token.DOTDOT) { - mustHaveXML(); - memberTypeFlags = Node.DESCENDANTS_FLAG; - } - if (!compilerEnv.isXmlAvailable()) { - mustMatchToken(Token.NAME, "msg.no.name.after.dot"); - s = ts.getString(); - decompiler.addName(s); - pn = nf.createPropertyGet(pn, null, s, memberTypeFlags); - break; - } - - tt = nextToken(); - switch (tt) { - - // needed for generator.throw(); - case Token.THROW: - decompiler.addName("throw"); - pn = propertyName(pn, "throw", memberTypeFlags); - break; - - // handles: name, ns::name, ns::*, ns::[expr] - case Token.NAME: - s = ts.getString(); - decompiler.addName(s); - pn = propertyName(pn, s, memberTypeFlags); - break; - - // handles: *, *::name, *::*, *::[expr] - case Token.MUL: - decompiler.addName("*"); - pn = propertyName(pn, "*", memberTypeFlags); - break; - - // handles: '@attr', '@ns::attr', '@ns::*', '@ns::*', - // '@::attr', '@::*', '@*', '@*::attr', '@*::*' - case Token.XMLATTR: - decompiler.addToken(Token.XMLATTR); - pn = attributeAccess(pn, memberTypeFlags); - break; - - default: - reportError("msg.no.name.after.dot"); - } - } - break; - - case Token.DOTQUERY: - consumeToken(); - mustHaveXML(); - decompiler.addToken(Token.DOTQUERY); - pn = nf.createDotQuery(pn, expr(false), ts.getLineno()); - mustMatchToken(Token.RP, "msg.no.paren"); - decompiler.addToken(Token.RP); - break; - - case Token.LB: - consumeToken(); - decompiler.addToken(Token.LB); - pn = nf.createElementGet(pn, null, expr(false), 0); - mustMatchToken(Token.RB, "msg.no.bracket.index"); - decompiler.addToken(Token.RB); - break; - - case Token.LP: - if (!allowCallSyntax) { - break tailLoop; - } - consumeToken(); - decompiler.addToken(Token.LP); - pn = nf.createCallOrNew(Token.CALL, pn); - /* Add the arguments to pn, if any are supplied. */ - argumentList(pn); - break; - - default: - break tailLoop; - } - } - return pn; - } - - /* - * Xml attribute expression: - * '@attr', '@ns::attr', '@ns::*', '@ns::*', '@*', '@*::attr', '@*::*' - */ - private Node attributeAccess(Node pn, int memberTypeFlags) - throws IOException - { - memberTypeFlags |= Node.ATTRIBUTE_FLAG; - int tt = nextToken(); - - switch (tt) { - // handles: @name, @ns::name, @ns::*, @ns::[expr] - case Token.NAME: - { - String s = ts.getString(); - decompiler.addName(s); - pn = propertyName(pn, s, memberTypeFlags); - } - break; - - // handles: @*, @*::name, @*::*, @*::[expr] - case Token.MUL: - decompiler.addName("*"); - pn = propertyName(pn, "*", memberTypeFlags); - break; - - // handles @[expr] - case Token.LB: - decompiler.addToken(Token.LB); - pn = nf.createElementGet(pn, null, expr(false), memberTypeFlags); - mustMatchToken(Token.RB, "msg.no.bracket.index"); - decompiler.addToken(Token.RB); - break; - - default: - reportError("msg.no.name.after.xmlAttr"); - pn = nf.createPropertyGet(pn, null, "?", memberTypeFlags); - break; - } - - return pn; - } - - /** - * Check if :: follows name in which case it becomes qualified name - */ - private Node propertyName(Node pn, String name, int memberTypeFlags) - throws IOException, ParserException - { - String namespace = null; - if (matchToken(Token.COLONCOLON)) { - decompiler.addToken(Token.COLONCOLON); - namespace = name; - - int tt = nextToken(); - switch (tt) { - // handles name::name - case Token.NAME: - name = ts.getString(); - decompiler.addName(name); - break; - - // handles name::* - case Token.MUL: - decompiler.addName("*"); - name = "*"; - break; - - // handles name::[expr] - case Token.LB: - decompiler.addToken(Token.LB); - pn = nf.createElementGet(pn, namespace, expr(false), - memberTypeFlags); - mustMatchToken(Token.RB, "msg.no.bracket.index"); - decompiler.addToken(Token.RB); - return pn; - - default: - reportError("msg.no.name.after.coloncolon"); - name = "?"; - } - } - - pn = nf.createPropertyGet(pn, namespace, name, memberTypeFlags); - return pn; - } - - private Node arrayComprehension(String arrayName, Node expr) - throws IOException, ParserException - { - if (nextToken() != Token.FOR) - throw Kit.codeBug(); // shouldn't be here if next token isn't 'for' - decompiler.addName(" "); // space after array literal expr - decompiler.addToken(Token.FOR); - boolean isForEach = false; - if (matchToken(Token.NAME)) { - decompiler.addName(ts.getString()); - if (ts.getString().equals("each")) { - isForEach = true; - } else { - reportError("msg.no.paren.for"); - } - } - mustMatchToken(Token.LP, "msg.no.paren.for"); - decompiler.addToken(Token.LP); - String name; - int tt = peekToken(); - if (tt == Token.LB || tt == Token.LC) { - // handle destructuring assignment - name = currentScriptOrFn.getNextTempName(); - defineSymbol(Token.LP, name); - expr = nf.createBinary(Token.COMMA, - nf.createAssignment(Token.ASSIGN, primaryExpr(), - nf.createName(name)), - expr); - } else if (tt == Token.NAME) { - consumeToken(); - name = ts.getString(); - decompiler.addName(name); - } else { - reportError("msg.bad.var"); - return nf.createNumber(0); - } - - Node init = nf.createName(name); - // Define as a let since we want the scope of the variable to - // be restricted to the array comprehension - defineSymbol(Token.LET, name); - - mustMatchToken(Token.IN, "msg.in.after.for.name"); - decompiler.addToken(Token.IN); - Node iterator = expr(false); - mustMatchToken(Token.RP, "msg.no.paren.for.ctrl"); - decompiler.addToken(Token.RP); - - Node body; - tt = peekToken(); - if (tt == Token.FOR) { - body = arrayComprehension(arrayName, expr); - } else { - Node call = nf.createCallOrNew(Token.CALL, - nf.createPropertyGet(nf.createName(arrayName), null, - "push", 0)); - call.addChildToBack(expr); - body = new Node(Token.EXPR_VOID, call, ts.getLineno()); - if (tt == Token.IF) { - consumeToken(); - decompiler.addToken(Token.IF); - int lineno = ts.getLineno(); - Node cond = condition(); - body = nf.createIf(cond, body, null, lineno); - } - mustMatchToken(Token.RB, "msg.no.bracket.arg"); - decompiler.addToken(Token.RB); - } - - Node loop = enterLoop(null, true); - try { - return nf.createForIn(Token.LET, loop, init, iterator, body, - isForEach); - } finally { - exitLoop(false); - } - } - - private Node primaryExpr() - throws IOException, ParserException - { - Node pn; - - int ttFlagged = nextFlaggedToken(); - int tt = ttFlagged & CLEAR_TI_MASK; - - switch(tt) { - - case Token.FUNCTION: - return function(FunctionNode.FUNCTION_EXPRESSION); - - case Token.LB: { - ObjArray elems = new ObjArray(); - int skipCount = 0; - int destructuringLen = 0; - decompiler.addToken(Token.LB); - boolean after_lb_or_comma = true; - for (;;) { - tt = peekToken(); - - if (tt == Token.COMMA) { - consumeToken(); - decompiler.addToken(Token.COMMA); - if (!after_lb_or_comma) { - after_lb_or_comma = true; - } else { - elems.add(null); - ++skipCount; - } - } else if (tt == Token.RB) { - consumeToken(); - decompiler.addToken(Token.RB); - // for ([a,] in obj) is legal, but for ([a] in obj) is - // not since we have both key and value supplied. The - // trick is that [a,] and [a] are equivalent in other - // array literal contexts. So we calculate a special - // length value just for destructuring assignment. - destructuringLen = elems.size() + - (after_lb_or_comma ? 1 : 0); - break; - } else if (skipCount == 0 && elems.size() == 1 && - tt == Token.FOR) - { - Node scopeNode = nf.createScopeNode(Token.ARRAYCOMP, - ts.getLineno()); - String tempName = currentScriptOrFn.getNextTempName(); - pushScope(scopeNode); - try { - defineSymbol(Token.LET, tempName); - Node expr = (Node) elems.get(0); - Node block = nf.createBlock(ts.getLineno()); - Node init = new Node(Token.EXPR_VOID, - nf.createAssignment(Token.ASSIGN, - nf.createName(tempName), - nf.createCallOrNew(Token.NEW, - nf.createName("Array"))), ts.getLineno()); - block.addChildToBack(init); - block.addChildToBack(arrayComprehension(tempName, - expr)); - scopeNode.addChildToBack(block); - scopeNode.addChildToBack(nf.createName(tempName)); - return scopeNode; - } finally { - popScope(); - } - } else { - if (!after_lb_or_comma) { - reportError("msg.no.bracket.arg"); - } - elems.add(assignExpr(false)); - after_lb_or_comma = false; - } - } - return nf.createArrayLiteral(elems, skipCount, destructuringLen); - } - - case Token.LC: { - ObjArray elems = new ObjArray(); - decompiler.addToken(Token.LC); - if (!matchToken(Token.RC)) { - - boolean first = true; - commaloop: - do { - Object property; - - if (!first) - decompiler.addToken(Token.COMMA); - else - first = false; - - tt = peekToken(); - switch(tt) { - case Token.NAME: - case Token.STRING: - consumeToken(); - // map NAMEs to STRINGs in object literal context - // but tell the decompiler the proper type - String s = ts.getString(); - if (tt == Token.NAME) { - if (s.equals("get") && - peekToken() == Token.NAME) { - decompiler.addToken(Token.GET); - consumeToken(); - s = ts.getString(); - decompiler.addName(s); - property = ScriptRuntime.getIndexObject(s); - if (!getterSetterProperty(elems, property, - true)) - break commaloop; - break; - } else if (s.equals("set") && - peekToken() == Token.NAME) { - decompiler.addToken(Token.SET); - consumeToken(); - s = ts.getString(); - decompiler.addName(s); - property = ScriptRuntime.getIndexObject(s); - if (!getterSetterProperty(elems, property, - false)) - break commaloop; - break; - } - decompiler.addName(s); - } else { - decompiler.addString(s); - } - property = ScriptRuntime.getIndexObject(s); - plainProperty(elems, property); - break; - - case Token.NUMBER: - consumeToken(); - double n = ts.getNumber(); - decompiler.addNumber(n); - property = ScriptRuntime.getIndexObject(n); - plainProperty(elems, property); - break; - - case Token.RC: - // trailing comma is OK. - break commaloop; - default: - reportError("msg.bad.prop"); - break commaloop; - } - } while (matchToken(Token.COMMA)); - - mustMatchToken(Token.RC, "msg.no.brace.prop"); - } - decompiler.addToken(Token.RC); - return nf.createObjectLiteral(elems); - } - - case Token.LET: - decompiler.addToken(Token.LET); - return let(false); - - case Token.LP: - - /* Brendan's IR-jsparse.c makes a new node tagged with - * TOK_LP here... I'm not sure I understand why. Isn't - * the grouping already implicit in the structure of the - * parse tree? also TOK_LP is already overloaded (I - * think) in the C IR as 'function call.' */ - decompiler.addToken(Token.LP); - pn = expr(false); - pn.putProp(Node.PARENTHESIZED_PROP, Boolean.TRUE); - decompiler.addToken(Token.RP); - mustMatchToken(Token.RP, "msg.no.paren"); - return pn; - - case Token.XMLATTR: - mustHaveXML(); - decompiler.addToken(Token.XMLATTR); - pn = attributeAccess(null, 0); - return pn; - - case Token.NAME: { - String name = ts.getString(); - if ((ttFlagged & TI_CHECK_LABEL) != 0) { - if (peekToken() == Token.COLON) { - // Do not consume colon, it is used as unwind indicator - // to return to statementHelper. - // XXX Better way? - return nf.createLabel(ts.getLineno()); - } - } - - decompiler.addName(name); - if (compilerEnv.isXmlAvailable()) { - pn = propertyName(null, name, 0); - } else { - pn = nf.createName(name); - } - return pn; - } - - case Token.NUMBER: { - double n = ts.getNumber(); - decompiler.addNumber(n); - return nf.createNumber(n); - } - - case Token.STRING: { - String s = ts.getString(); - decompiler.addString(s); - return nf.createString(s); - } - - case Token.DIV: - case Token.ASSIGN_DIV: { - // Got / or /= which should be treated as regexp in fact - ts.readRegExp(tt); - String flags = ts.regExpFlags; - ts.regExpFlags = null; - String re = ts.getString(); - decompiler.addRegexp(re, flags); - /*APPJET*/ - int index = currentScriptOrFn.addRegexp - (re, flags, getCurrentLineNumber()); - return nf.createRegExp(index); - } - - case Token.NULL: - case Token.THIS: - case Token.FALSE: - case Token.TRUE: - decompiler.addToken(tt); - return nf.createLeaf(tt); - - case Token.RESERVED: - reportError("msg.reserved.id"); - break; - - case Token.ERROR: - /* the scanner or one of its subroutines reported the error. */ - break; - - case Token.EOF: - reportError("msg.unexpected.eof"); - break; - - default: - reportError("msg.syntax"); - break; - } - return null; // should never reach here - } - - private void plainProperty(ObjArray elems, Object property) - throws IOException { - mustMatchToken(Token.COLON, "msg.no.colon.prop"); - - // OBJLIT is used as ':' in object literal for - // decompilation to solve spacing ambiguity. - decompiler.addToken(Token.OBJECTLIT); - elems.add(property); - elems.add(assignExpr(false)); - } - - private boolean getterSetterProperty(ObjArray elems, Object property, - boolean isGetter) throws IOException { - Node f = function(FunctionNode.FUNCTION_EXPRESSION); - if (f.getType() != Token.FUNCTION) { - reportError("msg.bad.prop"); - return false; - } - int fnIndex = f.getExistingIntProp(Node.FUNCTION_PROP); - FunctionNode fn = currentScriptOrFn.getFunctionNode(fnIndex); - if (fn.getFunctionName().length() != 0) { - reportError("msg.bad.prop"); - return false; - } - elems.add(property); - if (isGetter) { - elems.add(nf.createUnary(Token.GET, f)); - } else { - elems.add(nf.createUnary(Token.SET, f)); - } - return true; - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/PolicySecurityController.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/PolicySecurityController.java deleted file mode 100644 index c4d3d7e..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/PolicySecurityController.java +++ /dev/null @@ -1,223 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.lang.ref.SoftReference; -import java.lang.reflect.UndeclaredThrowableException; -import java.security.AccessController; -import java.security.CodeSource; -import java.security.Policy; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.security.SecureClassLoader; -import java.util.Map; -import java.util.WeakHashMap; - -import org.mozilla.classfile.ByteCode; -import org.mozilla.classfile.ClassFileWriter; - -/** - * A security controller relying on Java {@link Policy} in effect. When you use - * this security controller, your securityDomain objects must be instances of - * {@link CodeSource} representing the location from where you load your - * scripts. Any Java policy "grant" statements matching the URL and certificate - * in code sources will apply to the scripts. If you specify any certificates - * within your {@link CodeSource} objects, it is your responsibility to verify - * (or not) that the script source files are signed in whatever - * implementation-specific way you're using. - * @author Attila Szegedi - */ -public class PolicySecurityController extends SecurityController -{ - private static final byte[] secureCallerImplBytecode = loadBytecode(); - - // We're storing a CodeSource -> (ClassLoader -> SecureRenderer), since we - // need to have one renderer per class loader. We're using weak hash maps - // and soft references all the way, since we don't want to interfere with - // cleanup of either CodeSource or ClassLoader objects. - private static final Map callers = new WeakHashMap(); - - public Class getStaticSecurityDomainClassInternal() { - return CodeSource.class; - } - - private static class Loader extends SecureClassLoader - implements GeneratedClassLoader - { - private final CodeSource codeSource; - - Loader(ClassLoader parent, CodeSource codeSource) - { - super(parent); - this.codeSource = codeSource; - } - - public Class defineClass(String name, byte[] data) - { - return defineClass(name, data, 0, data.length, codeSource); - } - - public void linkClass(Class cl) - { - resolveClass(cl); - } - } - - public GeneratedClassLoader createClassLoader(final ClassLoader parent, - final Object securityDomain) - { - return (Loader)AccessController.doPrivileged( - new PrivilegedAction() - { - public Object run() - { - return new Loader(parent, (CodeSource)securityDomain); - } - }); - } - - public Object getDynamicSecurityDomain(Object securityDomain) - { - // No separate notion of dynamic security domain - just return what was - // passed in. - return securityDomain; - } - - public Object callWithDomain(final Object securityDomain, final Context cx, - Callable callable, Scriptable scope, Scriptable thisObj, - Object[] args) - { - // Run in doPrivileged as we might be checked for "getClassLoader" - // runtime permission - final ClassLoader classLoader = (ClassLoader)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return cx.getApplicationClassLoader(); - } - }); - final CodeSource codeSource = (CodeSource)securityDomain; - Map classLoaderMap; - synchronized(callers) - { - classLoaderMap = (Map)callers.get(codeSource); - if(classLoaderMap == null) - { - classLoaderMap = new WeakHashMap(); - callers.put(codeSource, classLoaderMap); - } - } - SecureCaller caller; - synchronized(classLoaderMap) - { - SoftReference ref = (SoftReference)classLoaderMap.get(classLoader); - if(ref != null) - { - caller = (SecureCaller)ref.get(); - } - else - { - caller = null; - } - if(caller == null) - { - try - { - // Run in doPrivileged as we'll be checked for - // "createClassLoader" runtime permission - caller = (SecureCaller)AccessController.doPrivileged( - new PrivilegedExceptionAction() - { - public Object run() throws Exception - { - Loader loader = new Loader(classLoader, - codeSource); - Class c = loader.defineClass( - SecureCaller.class.getName() + "Impl", - secureCallerImplBytecode); - return c.newInstance(); - } - }); - classLoaderMap.put(classLoader, new SoftReference(caller)); - } - catch(PrivilegedActionException ex) - { - throw new UndeclaredThrowableException(ex.getCause()); - } - } - } - return caller.call(callable, cx, scope, thisObj, args); - } - - public abstract static class SecureCaller - { - public abstract Object call(Callable callable, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args); - } - - - private static byte[] loadBytecode() - { - String secureCallerClassName = SecureCaller.class.getName(); - ClassFileWriter cfw = new ClassFileWriter( - secureCallerClassName + "Impl", secureCallerClassName, - "<generated>"); - cfw.startMethod("<init>", "()V", ClassFileWriter.ACC_PUBLIC); - cfw.addALoad(0); - cfw.addInvoke(ByteCode.INVOKESPECIAL, secureCallerClassName, - "<init>", "()V"); - cfw.add(ByteCode.RETURN); - cfw.stopMethod((short)1); - String callableCallSig = - "Lorg/mozilla/javascript/Context;" + - "Lorg/mozilla/javascript/Scriptable;" + - "Lorg/mozilla/javascript/Scriptable;" + - "[Ljava/lang/Object;)Ljava/lang/Object;"; - - cfw.startMethod("call", - "(Lorg/mozilla/javascript/Callable;" + callableCallSig, - (short)(ClassFileWriter.ACC_PUBLIC - | ClassFileWriter.ACC_FINAL)); - for(int i = 1; i < 6; ++i) { - cfw.addALoad(i); - } - cfw.addInvoke(ByteCode.INVOKEINTERFACE, - "org/mozilla/javascript/Callable", "call", - "(" + callableCallSig); - cfw.add(ByteCode.ARETURN); - cfw.stopMethod((short)6); - return cfw.toByteArray(); - } -}
\ No newline at end of file diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Ref.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Ref.java deleted file mode 100644 index 1e237bc..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Ref.java +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov, igor@fastmail.fm - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Serializable; - -/** - * Generic notion of reference object that know how to query/modify the - * target objects based on some property/index. - */ -public abstract class Ref implements Serializable -{ - public boolean has(Context cx) - { - return true; - } - - public abstract Object get(Context cx); - - public abstract Object set(Context cx, Object value); - - public boolean delete(Context cx) - { - return false; - } - -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/RefCallable.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/RefCallable.java deleted file mode 100644 index 6d4b61c..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/RefCallable.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov, igor@mir2.org - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * Object that can allows assignments to the result of function calls. - */ -public interface RefCallable extends Callable -{ - /** - * Perform function call in reference context. - * The args array reference should not be stored in any object that is - * can be GC-reachable after this method returns. If this is necessary, - * for example, to implement {@link Ref} methods, then store args.clone(), - * not args array itself. - * - * @param cx the current Context for this thread - * @param thisObj the JavaScript <code>this</code> object - * @param args the array of arguments - */ - public Ref refCall(Context cx, Scriptable thisObj, Object[] args); -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/RegExpProxy.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/RegExpProxy.java deleted file mode 100644 index ac29c6e..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/RegExpProxy.java +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * A proxy for the regexp package, so that the regexp package can be - * loaded optionally. - * - * @author Norris Boyd - */ -public interface RegExpProxy -{ - // Types of regexp actions - - public static final int RA_MATCH = 1; - public static final int RA_REPLACE = 2; - public static final int RA_SEARCH = 3; - - public boolean isRegExp(Scriptable obj); - - public Object compileRegExp(Context cx, String source, String flags); - - public Scriptable wrapRegExp(Context cx, Scriptable scope, - Object compiled); - - public Object action(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args, - int actionType); - - public int find_split(Context cx, Scriptable scope, String target, - String separator, Scriptable re, - int[] ip, int[] matchlen, - boolean[] matched, String[][] parensp); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/RhinoException.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/RhinoException.java deleted file mode 100644 index b7f4a4d..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/RhinoException.java +++ /dev/null @@ -1,306 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - - -package org.mozilla.javascript; - -import java.io.CharArrayWriter; -import java.io.File; -import java.io.FilenameFilter; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.util.List; -import java.util.ArrayList; - -/** - * The class of exceptions thrown by the JavaScript engine. - */ -public abstract class RhinoException extends RuntimeException -{ - RhinoException() - { - Evaluator e = Context.createInterpreter(); - if (e != null) - e.captureStackInfo(this); - } - - RhinoException(String details) - { - super(details); - Evaluator e = Context.createInterpreter(); - if (e != null) - e.captureStackInfo(this); - } - - public final String getMessage() - { - String details = details(); - if (sourceName == null || lineNumber <= 0) { - return details; - } - StringBuffer buf = new StringBuffer(details); - buf.append(" ("); - if (sourceName != null) { - buf.append(sourceName); - } - if (lineNumber > 0) { - buf.append('#'); - buf.append(lineNumber); - } - buf.append(')'); - return buf.toString(); - } - - public String details() - { - return super.getMessage(); - } - - /** - * Get the uri of the script source containing the error, or null - * if that information is not available. - */ - public final String sourceName() - { - return sourceName; - } - - /** - * Initialize the uri of the script source containing the error. - * - * @param sourceName the uri of the script source responsible for the error. - * It should not be <tt>null</tt>. - * - * @throws IllegalStateException if the method is called more then once. - */ - public final void initSourceName(String sourceName) - { - if (sourceName == null) throw new IllegalArgumentException(); - if (this.sourceName != null) throw new IllegalStateException(); - this.sourceName = sourceName; - } - - /** - * Returns the line number of the statement causing the error, - * or zero if not available. - */ - public final int lineNumber() - { - return lineNumber; - } - - /** - * Initialize the line number of the script statement causing the error. - * - * @param lineNumber the line number in the script source. - * It should be positive number. - * - * @throws IllegalStateException if the method is called more then once. - */ - public final void initLineNumber(int lineNumber) - { - if (lineNumber <= 0) throw new IllegalArgumentException(String.valueOf(lineNumber)); - if (this.lineNumber > 0) throw new IllegalStateException(); - this.lineNumber = lineNumber; - } - - /** - * The column number of the location of the error, or zero if unknown. - */ - public final int columnNumber() - { - return columnNumber; - } - - /** - * Initialize the column number of the script statement causing the error. - * - * @param columnNumber the column number in the script source. - * It should be positive number. - * - * @throws IllegalStateException if the method is called more then once. - */ - public final void initColumnNumber(int columnNumber) - { - if (columnNumber <= 0) throw new IllegalArgumentException(String.valueOf(columnNumber)); - if (this.columnNumber > 0) throw new IllegalStateException(); - this.columnNumber = columnNumber; - } - - /** - * The source text of the line causing the error, or null if unknown. - */ - public final String lineSource() - { - return lineSource; - } - - /** - * Initialize the text of the source line containing the error. - * - * @param lineSource the text of the source line responsible for the error. - * It should not be <tt>null</tt>. - * - * @throws IllegalStateException if the method is called more then once. - */ - public final void initLineSource(String lineSource) - { - if (lineSource == null) throw new IllegalArgumentException(); - if (this.lineSource != null) throw new IllegalStateException(); - this.lineSource = lineSource; - } - - final void recordErrorOrigin(String sourceName, int lineNumber, - String lineSource, int columnNumber) - { - // XXX: for compatibility allow for now -1 to mean 0 - if (lineNumber == -1) { - lineNumber = 0; - } - - if (sourceName != null) { - initSourceName(sourceName); - } - if (lineNumber != 0) { - initLineNumber(lineNumber); - } - if (lineSource != null) { - initLineSource(lineSource); - } - if (columnNumber != 0) { - initColumnNumber(columnNumber); - } - } - - private String generateStackTrace() - { - // Get stable reference to work properly with concurrent access - CharArrayWriter writer = new CharArrayWriter(); - super.printStackTrace(new PrintWriter(writer)); - String origStackTrace = writer.toString(); - Evaluator e = Context.createInterpreter(); - if (e != null) - return e.getPatchedStack(this, origStackTrace); - return null; - } - - /** - * Get a string representing the script stack of this exception. - * If optimization is enabled, this corresponds to all java stack elements - * with a source name ending with ".js". - * @return a script stack dump - * @since 1.6R6 - */ - public String getScriptStackTrace() - { - return getScriptStackTrace(new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.endsWith(".js"); - } - }); - } - - /** - * Get a string representing the script stack of this exception. - * If optimization is enabled, this corresponds to all java stack elements - * with a source name matching the <code>filter</code>. - * @param filter the file name filter to determine whether a file is a - * script file - * @return a script stack dump - * @since 1.6R6 - */ - public String getScriptStackTrace(FilenameFilter filter) - { - List interpreterStack; - Evaluator interpreter = Context.createInterpreter(); - if (interpreter != null) - interpreterStack = interpreter.getScriptStack(this); - else - interpreterStack = new ArrayList(); - int interpreterStackIndex = 0; - StringBuffer buffer = new StringBuffer(); - String lineSeparator = SecurityUtilities.getSystemProperty("line.separator"); - StackTraceElement[] stack = getStackTrace(); - for (int i = 0; i < stack.length; i++) { - StackTraceElement e = stack[i]; - String name = e.getFileName(); - if (e.getLineNumber() > -1 && name != null && - filter.accept(null, name)) - { - buffer.append("\tat "); - buffer.append(e.getFileName()); - buffer.append(':'); - buffer.append(e.getLineNumber()); - buffer.append(lineSeparator); - } else if (interpreterStack != null && - "org.mozilla.javascript.Interpreter".equals(e.getClassName()) && - "interpretLoop".equals(e.getMethodName())) - { - buffer.append(interpreterStack.get(interpreterStackIndex++)); - } - } - return buffer.toString(); - } - - public void printStackTrace(PrintWriter s) - { - if (interpreterStackInfo == null) { - super.printStackTrace(s); - } else { - s.print(generateStackTrace()); - } - } - - public void printStackTrace(PrintStream s) - { - if (interpreterStackInfo == null) { - super.printStackTrace(s); - } else { - s.print(generateStackTrace()); - } - } - - private String sourceName; - private int lineNumber; - private String lineSource; - private int columnNumber; - - Object interpreterStackInfo; - int[] interpreterLineData; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Script.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Script.java deleted file mode 100644 index 4721ead..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Script.java +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * All compiled scripts implement this interface. - * <p> - * This class encapsulates script execution relative to an - * object scope. - * @since 1.3 - * @author Norris Boyd - */ - -public interface Script { - - /** - * Execute the script. - * <p> - * The script is executed in a particular runtime Context, which - * must be associated with the current thread. - * The script is executed relative to a scope--definitions and - * uses of global top-level variables and functions will access - * properties of the scope object. For compliant ECMA - * programs, the scope must be an object that has been initialized - * as a global object using <code>Context.initStandardObjects</code>. - * <p> - * - * @param cx the Context associated with the current thread - * @param scope the scope to execute relative to - * @return the result of executing the script - * @see org.mozilla.javascript.Context#initStandardObjects() - */ - public Object exec(Context cx, Scriptable scope); - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptOrFnNode.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptOrFnNode.java deleted file mode 100644 index 9ea6d1f..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptOrFnNode.java +++ /dev/null @@ -1,241 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * Bob Jervis - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.util.ArrayList; - -public class ScriptOrFnNode extends Node.Scope { - - public ScriptOrFnNode(int nodeType) { - super(nodeType); - symbols = new ArrayList(4); - setParent(null); - } - - public final String getSourceName() { return sourceName; } - - public final void setSourceName(String sourceName) { - this.sourceName = sourceName; - } - - public final int getEncodedSourceStart() { return encodedSourceStart; } - - public final int getEncodedSourceEnd() { return encodedSourceEnd; } - - public final void setEncodedSourceBounds(int start, int end) { - this.encodedSourceStart = start; - this.encodedSourceEnd = end; - } - - public final int getBaseLineno() { return this.lineno; } - - public final void setBaseLineno(int lineno) { - // One time action - if (lineno < 0 || this.lineno >= 0) Kit.codeBug(); - this.lineno = lineno; - } - - public final int getEndLineno() { return endLineno; } - - public final void setEndLineno(int lineno) { - // One time action - if (lineno < 0 || endLineno >= 0) Kit.codeBug(); - endLineno = lineno; - } - - public final int getFunctionCount() { - if (functions == null) { return 0; } - return functions.size(); - } - - public final FunctionNode getFunctionNode(int i) { - return (FunctionNode)functions.get(i); - } - - public final int addFunction(FunctionNode fnNode) { - if (fnNode == null) Kit.codeBug(); - if (functions == null) { functions = new ObjArray(); } - functions.add(fnNode); - return functions.size() - 1; - } - - public final int getRegexpCount() { - if (regexps == null) { return 0; } - return regexps.size() / 2; - } - - public final String getRegexpString(int index) { - return (String)regexps.get(index * 2); - } - - public final String getRegexpFlags(int index) { - return (String)regexps.get(index * 2 + 1); - } - - /*APPJET*/public final int getRegexpLineno(int index) { - return (Integer)regexpLinenos.get(index); - } - - public final int addRegexp(String string, String flags, /*APPJET*/ - int lineno) { - if (string == null) Kit.codeBug(); - if (regexps == null) { - /*APPJET*/ - regexps = new ObjArray(); - regexpLinenos = new ObjArray(); - } - regexps.add(string); - regexps.add(flags); - /*APPJET*/regexpLinenos.add(lineno); - return regexps.size() / 2 - 1; - } - - public int getIndexForNameNode(Node nameNode) { - if (variableNames == null) throw Kit.codeBug(); - Node.Scope node = nameNode.getScope(); - Symbol symbol = node == null ? null - : node.getSymbol(nameNode.getString()); - if (symbol == null) - return -1; - return symbol.index; - } - - public final String getParamOrVarName(int index) { - if (variableNames == null) throw Kit.codeBug(); - return variableNames[index]; - } - - public final int getParamCount() { - return paramCount; - } - - public final int getParamAndVarCount() { - if (variableNames == null) throw Kit.codeBug(); - return symbols.size(); - } - - public final String[] getParamAndVarNames() { - if (variableNames == null) throw Kit.codeBug(); - return variableNames; - } - - public final boolean[] getParamAndVarConst() { - if (variableNames == null) throw Kit.codeBug(); - return isConsts; - } - - void addSymbol(Symbol symbol) { - if (variableNames != null) throw Kit.codeBug(); - if (symbol.declType == Token.LP) { - paramCount++; - } - symbols.add(symbol); - } - - /** - * Assign every symbol a unique integer index. Generate arrays of variable - * names and constness that can be indexed by those indices. - * - * @param flattenAllTables if true, flatten all symbol tables, included - * nested block scope symbol tables. If false, just flatten the script's - * or function's symbol table. - */ - void flattenSymbolTable(boolean flattenAllTables) { - if (!flattenAllTables) { - ArrayList newSymbols = new ArrayList(); - if (this.symbolTable != null) { - // Just replace "symbols" with the symbols in this object's - // symbol table. Can't just work from symbolTable map since - // we need to retain duplicate parameters. - for (int i=0; i < symbols.size(); i++) { - Symbol symbol = (Symbol) symbols.get(i); - if (symbol.containingTable == this) { - newSymbols.add(symbol); - } - } - } - symbols = newSymbols; - } - variableNames = new String[symbols.size()]; - isConsts = new boolean[symbols.size()]; - for (int i=0; i < symbols.size(); i++) { - Symbol symbol = (Symbol) symbols.get(i); - variableNames[i] = symbol.name; - isConsts[i] = symbol.declType == Token.CONST; - symbol.index = i; - } - } - - public final Object getCompilerData() - { - return compilerData; - } - - public final void setCompilerData(Object data) - { - if (data == null) throw new IllegalArgumentException(); - // Can only call once - if (compilerData != null) throw new IllegalStateException(); - compilerData = data; - } - - public String getNextTempName() - { - return "$" + tempNumber++; - } - - private int encodedSourceStart; - private int encodedSourceEnd; - private String sourceName; - private int endLineno = -1; - - private ObjArray functions; - private ObjArray regexps; - /*APPJET*/ private ObjArray regexpLinenos; - - private ArrayList symbols; - private int paramCount = 0; - private String[] variableNames; - private boolean[] isConsts; - - private Object compilerData; - private int tempNumber = 0; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptRuntime.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptRuntime.java deleted file mode 100644 index f879581..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptRuntime.java +++ /dev/null @@ -1,3830 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Patrick Beard - * Norris Boyd - * Igor Bukanov - * Ethan Hugg - * Bob Jervis - * Roger Lawrence - * Terry Lucas - * Frank Mitchell - * Milen Nankov - * Hannes Wallnoefer - * Andrew Wason - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Serializable; -import java.lang.reflect.*; -import java.text.MessageFormat; -import java.util.Locale; -import java.util.ResourceBundle; - -import org.mozilla.javascript.xml.XMLObject; -import org.mozilla.javascript.xml.XMLLib; - -/** - * This is the class that implements the runtime. - * - * @author Norris Boyd - */ - -public class ScriptRuntime { - - /** - * No instances should be created. - */ - protected ScriptRuntime() { - } - - private static class NoSuchMethodShim implements Callable { - String methodName; - Callable noSuchMethodMethod; - - NoSuchMethodShim(Callable noSuchMethodMethod, String methodName) - { - this.noSuchMethodMethod = noSuchMethodMethod; - this.methodName = methodName; - } - /** - * Perform the call. - * - * @param cx the current Context for this thread - * @param scope the scope to use to resolve properties. - * @param thisObj the JavaScript <code>this</code> object - * @param args the array of arguments - * @return the result of the call - */ - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - Object[] nestedArgs = new Object[2]; - - nestedArgs[0] = methodName; - nestedArgs[1] = newArrayLiteral(args, null, cx, scope); - return noSuchMethodMethod.call(cx, scope, thisObj, nestedArgs); - } - - } - /* - * There's such a huge space (and some time) waste for the Foo.class - * syntax: the compiler sticks in a test of a static field in the - * enclosing class for null and the code for creating the class value. - * It has to do this since the reference has to get pushed off until - * execution time (i.e. can't force an early load), but for the - * 'standard' classes - especially those in java.lang, we can trust - * that they won't cause problems by being loaded early. - */ - - public final static Class - BooleanClass = Kit.classOrNull("java.lang.Boolean"), - ByteClass = Kit.classOrNull("java.lang.Byte"), - CharacterClass = Kit.classOrNull("java.lang.Character"), - ClassClass = Kit.classOrNull("java.lang.Class"), - DoubleClass = Kit.classOrNull("java.lang.Double"), - FloatClass = Kit.classOrNull("java.lang.Float"), - IntegerClass = Kit.classOrNull("java.lang.Integer"), - LongClass = Kit.classOrNull("java.lang.Long"), - NumberClass = Kit.classOrNull("java.lang.Number"), - ObjectClass = Kit.classOrNull("java.lang.Object"), - ShortClass = Kit.classOrNull("java.lang.Short"), - StringClass = Kit.classOrNull("java.lang.String"), - DateClass = Kit.classOrNull("java.util.Date"); - - public final static Class - ContextClass - = Kit.classOrNull("org.mozilla.javascript.Context"), - ContextFactoryClass - = Kit.classOrNull("org.mozilla.javascript.ContextFactory"), - FunctionClass - = Kit.classOrNull("org.mozilla.javascript.Function"), - ScriptableClass - = Kit.classOrNull("org.mozilla.javascript.Scriptable"), - ScriptableObjectClass - = Kit.classOrNull("org.mozilla.javascript.ScriptableObject"); - - private static final String[] lazilyNames = { - "RegExp", "org.mozilla.javascript.regexp.NativeRegExp", - "Packages", "org.mozilla.javascript.NativeJavaTopPackage", - "java", "org.mozilla.javascript.NativeJavaTopPackage", - "javax", "org.mozilla.javascript.NativeJavaTopPackage", - "org", "org.mozilla.javascript.NativeJavaTopPackage", - "com", "org.mozilla.javascript.NativeJavaTopPackage", - "edu", "org.mozilla.javascript.NativeJavaTopPackage", - "net", "org.mozilla.javascript.NativeJavaTopPackage", - "getClass", "org.mozilla.javascript.NativeJavaTopPackage", - "JavaAdapter", "org.mozilla.javascript.JavaAdapter", - "JavaImporter", "org.mozilla.javascript.ImporterTopLevel", - "Continuation", "org.mozilla.javascript.continuations.Continuation", - // TODO Grotesque hack using literal string (xml) just to minimize - // changes for now - "XML", "(xml)", - "XMLList", "(xml)", - "Namespace", "(xml)", - "QName", "(xml)", - }; - - private static final Object LIBRARY_SCOPE_KEY = new Object(); - - public static boolean isRhinoRuntimeType(Class cl) - { - if (cl.isPrimitive()) { - return (cl != Character.TYPE); - } else { - return (cl == StringClass || cl == BooleanClass - || NumberClass.isAssignableFrom(cl) - || ScriptableClass.isAssignableFrom(cl)); - } - } - - public static ScriptableObject initStandardObjects(Context cx, - ScriptableObject scope, - boolean sealed) - { - if (scope == null) { - scope = new NativeObject(); - } - scope.associateValue(LIBRARY_SCOPE_KEY, scope); - (new ClassCache()).associate(scope); - - BaseFunction.init(scope, sealed); - NativeObject.init(scope, sealed); - - Scriptable objectProto = ScriptableObject.getObjectPrototype(scope); - - // Function.prototype.__proto__ should be Object.prototype - Scriptable functionProto = ScriptableObject.getFunctionPrototype(scope); - functionProto.setPrototype(objectProto); - - // Set the prototype of the object passed in if need be - if (scope.getPrototype() == null) - scope.setPrototype(objectProto); - - // must precede NativeGlobal since it's needed therein - NativeError.init(scope, sealed); - NativeGlobal.init(cx, scope, sealed); - - NativeArray.init(scope, sealed); - if (cx.getOptimizationLevel() > 0) { - // When optimizing, attempt to fulfill all requests for new Array(N) - // with a higher threshold before switching to a sparse - // representation - NativeArray.setMaximumInitialCapacity(200000); - } - NativeString.init(scope, sealed); - NativeBoolean.init(scope, sealed); - NativeNumber.init(scope, sealed); - NativeDate.init(scope, sealed); - NativeMath.init(scope, sealed); - - NativeWith.init(scope, sealed); - NativeCall.init(scope, sealed); - NativeScript.init(scope, sealed); - - NativeIterator.init(scope, sealed); // Also initializes NativeGenerator - - boolean withXml = cx.hasFeature(Context.FEATURE_E4X) && - cx.getE4xImplementationFactory() != null; - - for (int i = 0; i != lazilyNames.length; i += 2) { - String topProperty = lazilyNames[i]; - String className = lazilyNames[i + 1]; - if (!withXml && className.equals("(xml)")) { - continue; - } else if (withXml && className.equals("(xml)")) { - className = cx.getE4xImplementationFactory(). - getImplementationClassName(); - } - new LazilyLoadedCtor(scope, topProperty, className, sealed); - } - - return scope; - } - - public static ScriptableObject getLibraryScopeOrNull(Scriptable scope) - { - ScriptableObject libScope; - libScope = (ScriptableObject)ScriptableObject. - getTopScopeValue(scope, LIBRARY_SCOPE_KEY); - return libScope; - } - - // It is public so NativeRegExp can access it. - public static boolean isJSLineTerminator(int c) - { - // Optimization for faster check for eol character: - // they do not have 0xDFD0 bits set - if ((c & 0xDFD0) != 0) { - return false; - } - return c == '\n' || c == '\r' || c == 0x2028 || c == 0x2029; - } - - public static Boolean wrapBoolean(boolean b) - { - return b ? Boolean.TRUE : Boolean.FALSE; - } - - public static Integer wrapInt(int i) - { - return new Integer(i); - } - - public static Number wrapNumber(double x) - { - if (x != x) { - return ScriptRuntime.NaNobj; - } - return new Double(x); - } - - /** - * Convert the value to a boolean. - * - * See ECMA 9.2. - */ - public static boolean toBoolean(Object val) - { - for (;;) { - if (val instanceof Boolean) - return ((Boolean) val).booleanValue(); - if (val == null || val == Undefined.instance) - return false; - if (val instanceof String) - return ((String) val).length() != 0; - if (val instanceof Number) { - double d = ((Number) val).doubleValue(); - return (d == d && d != 0.0); - } - if (val instanceof Scriptable) { - if (val instanceof ScriptableObject && - ((ScriptableObject) val).avoidObjectDetection()) - { - return false; - } - if (Context.getContext().isVersionECMA1()) { - // pure ECMA - return true; - } - // ECMA extension - val = ((Scriptable) val).getDefaultValue(BooleanClass); - if (val instanceof Scriptable) - throw errorWithClassName("msg.primitive.expected", val); - continue; - } - warnAboutNonJSObject(val); - return true; - } - } - - /** - * Convert the value to a number. - * - * See ECMA 9.3. - */ - public static double toNumber(Object val) - { - for (;;) { - if (val instanceof Number) - return ((Number) val).doubleValue(); - if (val == null) - return +0.0; - if (val == Undefined.instance) - return NaN; - if (val instanceof String) - return toNumber((String) val); - if (val instanceof Boolean) - return ((Boolean) val).booleanValue() ? 1 : +0.0; - if (val instanceof Scriptable) { - val = ((Scriptable) val).getDefaultValue(NumberClass); - if (val instanceof Scriptable) - throw errorWithClassName("msg.primitive.expected", val); - continue; - } - warnAboutNonJSObject(val); - return NaN; - } - } - - public static double toNumber(Object[] args, int index) { - return (index < args.length) ? toNumber(args[index]) : NaN; - } - - // Can not use Double.NaN defined as 0.0d / 0.0 as under the Microsoft VM, - // versions 2.01 and 3.0P1, that causes some uses (returns at least) of - // Double.NaN to be converted to 1.0. - // So we use ScriptRuntime.NaN instead of Double.NaN. - public static final double - NaN = Double.longBitsToDouble(0x7ff8000000000000L); - - // A similar problem exists for negative zero. - public static final double - negativeZero = Double.longBitsToDouble(0x8000000000000000L); - - public static final Double NaNobj = new Double(NaN); - - /* - * Helper function for toNumber, parseInt, and TokenStream.getToken. - */ - static double stringToNumber(String s, int start, int radix) { - char digitMax = '9'; - char lowerCaseBound = 'a'; - char upperCaseBound = 'A'; - int len = s.length(); - if (radix < 10) { - digitMax = (char) ('0' + radix - 1); - } - if (radix > 10) { - lowerCaseBound = (char) ('a' + radix - 10); - upperCaseBound = (char) ('A' + radix - 10); - } - int end; - double sum = 0.0; - for (end=start; end < len; end++) { - char c = s.charAt(end); - int newDigit; - if ('0' <= c && c <= digitMax) - newDigit = c - '0'; - else if ('a' <= c && c < lowerCaseBound) - newDigit = c - 'a' + 10; - else if ('A' <= c && c < upperCaseBound) - newDigit = c - 'A' + 10; - else - break; - sum = sum*radix + newDigit; - } - if (start == end) { - return NaN; - } - if (sum >= 9007199254740992.0) { - if (radix == 10) { - /* If we're accumulating a decimal number and the number - * is >= 2^53, then the result from the repeated multiply-add - * above may be inaccurate. Call Java to get the correct - * answer. - */ - try { - return Double.valueOf(s.substring(start, end)).doubleValue(); - } catch (NumberFormatException nfe) { - return NaN; - } - } else if (radix == 2 || radix == 4 || radix == 8 || - radix == 16 || radix == 32) - { - /* The number may also be inaccurate for one of these bases. - * This happens if the addition in value*radix + digit causes - * a round-down to an even least significant mantissa bit - * when the first dropped bit is a one. If any of the - * following digits in the number (which haven't been added - * in yet) are nonzero then the correct action would have - * been to round up instead of down. An example of this - * occurs when reading the number 0x1000000000000081, which - * rounds to 0x1000000000000000 instead of 0x1000000000000100. - */ - int bitShiftInChar = 1; - int digit = 0; - - final int SKIP_LEADING_ZEROS = 0; - final int FIRST_EXACT_53_BITS = 1; - final int AFTER_BIT_53 = 2; - final int ZEROS_AFTER_54 = 3; - final int MIXED_AFTER_54 = 4; - - int state = SKIP_LEADING_ZEROS; - int exactBitsLimit = 53; - double factor = 0.0; - boolean bit53 = false; - // bit54 is the 54th bit (the first dropped from the mantissa) - boolean bit54 = false; - - for (;;) { - if (bitShiftInChar == 1) { - if (start == end) - break; - digit = s.charAt(start++); - if ('0' <= digit && digit <= '9') - digit -= '0'; - else if ('a' <= digit && digit <= 'z') - digit -= 'a' - 10; - else - digit -= 'A' - 10; - bitShiftInChar = radix; - } - bitShiftInChar >>= 1; - boolean bit = (digit & bitShiftInChar) != 0; - - switch (state) { - case SKIP_LEADING_ZEROS: - if (bit) { - --exactBitsLimit; - sum = 1.0; - state = FIRST_EXACT_53_BITS; - } - break; - case FIRST_EXACT_53_BITS: - sum *= 2.0; - if (bit) - sum += 1.0; - --exactBitsLimit; - if (exactBitsLimit == 0) { - bit53 = bit; - state = AFTER_BIT_53; - } - break; - case AFTER_BIT_53: - bit54 = bit; - factor = 2.0; - state = ZEROS_AFTER_54; - break; - case ZEROS_AFTER_54: - if (bit) { - state = MIXED_AFTER_54; - } - // fallthrough - case MIXED_AFTER_54: - factor *= 2; - break; - } - } - switch (state) { - case SKIP_LEADING_ZEROS: - sum = 0.0; - break; - case FIRST_EXACT_53_BITS: - case AFTER_BIT_53: - // do nothing - break; - case ZEROS_AFTER_54: - // x1.1 -> x1 + 1 (round up) - // x0.1 -> x0 (round down) - if (bit54 & bit53) - sum += 1.0; - sum *= factor; - break; - case MIXED_AFTER_54: - // x.100...1.. -> x + 1 (round up) - // x.0anything -> x (round down) - if (bit54) - sum += 1.0; - sum *= factor; - break; - } - } - /* We don't worry about inaccurate numbers for any other base. */ - } - return sum; - } - - - /** - * ToNumber applied to the String type - * - * See ECMA 9.3.1 - */ - public static double toNumber(String s) { - int len = s.length(); - int start = 0; - char startChar; - for (;;) { - if (start == len) { - // Empty or contains only whitespace - return +0.0; - } - startChar = s.charAt(start); - if (!Character.isWhitespace(startChar)) - break; - start++; - } - - if (startChar == '0') { - if (start + 2 < len) { - int c1 = s.charAt(start + 1); - if (c1 == 'x' || c1 == 'X') { - // A hexadecimal number - return stringToNumber(s, start + 2, 16); - } - } - } else if (startChar == '+' || startChar == '-') { - if (start + 3 < len && s.charAt(start + 1) == '0') { - int c2 = s.charAt(start + 2); - if (c2 == 'x' || c2 == 'X') { - // A hexadecimal number with sign - double val = stringToNumber(s, start + 3, 16); - return startChar == '-' ? -val : val; - } - } - } - - int end = len - 1; - char endChar; - while (Character.isWhitespace(endChar = s.charAt(end))) - end--; - if (endChar == 'y') { - // check for "Infinity" - if (startChar == '+' || startChar == '-') - start++; - if (start + 7 == end && s.regionMatches(start, "Infinity", 0, 8)) - return startChar == '-' - ? Double.NEGATIVE_INFINITY - : Double.POSITIVE_INFINITY; - return NaN; - } - // A non-hexadecimal, non-infinity number: - // just try a normal floating point conversion - String sub = s.substring(start, end+1); - if (MSJVM_BUG_WORKAROUNDS) { - // The MS JVM will accept non-conformant strings - // rather than throwing a NumberFormatException - // as it should. - for (int i=sub.length()-1; i >= 0; i--) { - char c = sub.charAt(i); - if (('0' <= c && c <= '9') || c == '.' || - c == 'e' || c == 'E' || - c == '+' || c == '-') - continue; - return NaN; - } - } - try { - return Double.valueOf(sub).doubleValue(); - } catch (NumberFormatException ex) { - return NaN; - } - } - - /** - * Helper function for builtin objects that use the varargs form. - * ECMA function formal arguments are undefined if not supplied; - * this function pads the argument array out to the expected - * length, if necessary. - */ - public static Object[] padArguments(Object[] args, int count) { - if (count < args.length) - return args; - - int i; - Object[] result = new Object[count]; - for (i = 0; i < args.length; i++) { - result[i] = args[i]; - } - - for (; i < count; i++) { - result[i] = Undefined.instance; - } - - return result; - } - - /* Work around Microsoft Java VM bugs. */ - private final static boolean MSJVM_BUG_WORKAROUNDS = true; - - public static String escapeString(String s) - { - return escapeString(s, '"'); - } - - /** - * For escaping strings printed by object and array literals; not quite - * the same as 'escape.' - */ - public static String escapeString(String s, char escapeQuote) - { - if (!(escapeQuote == '"' || escapeQuote == '\'')) Kit.codeBug(); - StringBuffer sb = null; - - for(int i = 0, L = s.length(); i != L; ++i) { - int c = s.charAt(i); - - if (' ' <= c && c <= '~' && c != escapeQuote && c != '\\') { - // an ordinary print character (like C isprint()) and not " - // or \ . - if (sb != null) { - sb.append((char)c); - } - continue; - } - if (sb == null) { - sb = new StringBuffer(L + 3); - sb.append(s); - sb.setLength(i); - } - - int escape = -1; - switch (c) { - case '\b': escape = 'b'; break; - case '\f': escape = 'f'; break; - case '\n': escape = 'n'; break; - case '\r': escape = 'r'; break; - case '\t': escape = 't'; break; - case 0xb: escape = 'v'; break; // Java lacks \v. - case ' ': escape = ' '; break; - case '\\': escape = '\\'; break; - } - if (escape >= 0) { - // an \escaped sort of character - sb.append('\\'); - sb.append((char)escape); - } else if (c == escapeQuote) { - sb.append('\\'); - sb.append(escapeQuote); - } else { - int hexSize; - if (c < 256) { - // 2-digit hex - sb.append("\\x"); - hexSize = 2; - } else { - // Unicode. - sb.append("\\u"); - hexSize = 4; - } - // append hexadecimal form of c left-padded with 0 - for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4) { - int digit = 0xf & (c >> shift); - int hc = (digit < 10) ? '0' + digit : 'a' - 10 + digit; - sb.append((char)hc); - } - } - } - return (sb == null) ? s : sb.toString(); - } - - static boolean isValidIdentifierName(String s) - { - int L = s.length(); - if (L == 0) - return false; - if (!Character.isJavaIdentifierStart(s.charAt(0))) - return false; - for (int i = 1; i != L; ++i) { - if (!Character.isJavaIdentifierPart(s.charAt(i))) - return false; - } - return !TokenStream.isKeyword(s); - } - - /** - * Convert the value to a string. - * - * See ECMA 9.8. - */ - public static String toString(Object val) { - for (;;) { - if (val == null) { - return "null"; - } - if (val == Undefined.instance) { - return "undefined"; - } - if (val instanceof String) { - return (String)val; - } - if (val instanceof Number) { - // XXX should we just teach NativeNumber.stringValue() - // about Numbers? - return numberToString(((Number)val).doubleValue(), 10); - } - if (val instanceof Scriptable) { - val = ((Scriptable) val).getDefaultValue(StringClass); - if (val instanceof Scriptable) { - throw errorWithClassName("msg.primitive.expected", val); - } - continue; - } - return val.toString(); - } - } - - static String defaultObjectToString(Scriptable obj) - { - return "[object " + obj.getClassName() + ']'; - } - - public static String toString(Object[] args, int index) - { - return (index < args.length) ? toString(args[index]) : "undefined"; - } - - /** - * Optimized version of toString(Object) for numbers. - */ - public static String toString(double val) { - return numberToString(val, 10); - } - - public static String numberToString(double d, int base) { - if (d != d) - return "NaN"; - if (d == Double.POSITIVE_INFINITY) - return "Infinity"; - if (d == Double.NEGATIVE_INFINITY) - return "-Infinity"; - if (d == 0.0) - return "0"; - - if ((base < 2) || (base > 36)) { - throw Context.reportRuntimeError1( - "msg.bad.radix", Integer.toString(base)); - } - - if (base != 10) { - return DToA.JS_dtobasestr(base, d); - } else { - StringBuffer result = new StringBuffer(); - DToA.JS_dtostr(result, DToA.DTOSTR_STANDARD, 0, d); - return result.toString(); - } - - } - - static String uneval(Context cx, Scriptable scope, Object value) - { - if (value == null) { - return "null"; - } - if (value == Undefined.instance) { - return "undefined"; - } - if (value instanceof String) { - String escaped = escapeString((String)value); - StringBuffer sb = new StringBuffer(escaped.length() + 2); - sb.append('\"'); - sb.append(escaped); - sb.append('\"'); - return sb.toString(); - } - if (value instanceof Number) { - double d = ((Number)value).doubleValue(); - if (d == 0 && 1 / d < 0) { - return "-0"; - } - return toString(d); - } - if (value instanceof Boolean) { - return toString(value); - } - if (value instanceof Scriptable) { - Scriptable obj = (Scriptable)value; - // Wrapped Java objects won't have "toSource" and will report - // errors for get()s of nonexistent name, so use has() first - if (ScriptableObject.hasProperty(obj, "toSource")) { - Object v = ScriptableObject.getProperty(obj, "toSource"); - if (v instanceof Function) { - Function f = (Function)v; - return toString(f.call(cx, scope, obj, emptyArgs)); - } - } - return toString(value); - } - warnAboutNonJSObject(value); - return value.toString(); - } - - static String defaultObjectToSource(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - boolean toplevel, iterating; - if (cx.iterating == null) { - toplevel = true; - iterating = false; - cx.iterating = new ObjToIntMap(31); - } else { - toplevel = false; - iterating = cx.iterating.has(thisObj); - } - - StringBuffer result = new StringBuffer(128); - if (toplevel) { - result.append("("); - } - result.append('{'); - - // Make sure cx.iterating is set to null when done - // so we don't leak memory - try { - if (!iterating) { - cx.iterating.intern(thisObj); // stop recursion. - Object[] ids = thisObj.getIds(); - for (int i=0; i < ids.length; i++) { - Object id = ids[i]; - Object value; - if (id instanceof Integer) { - int intId = ((Integer)id).intValue(); - value = thisObj.get(intId, thisObj); - if (value == Scriptable.NOT_FOUND) - continue; // a property has been removed - if (i > 0) - result.append(", "); - result.append(intId); - } else { - String strId = (String)id; - value = thisObj.get(strId, thisObj); - if (value == Scriptable.NOT_FOUND) - continue; // a property has been removed - if (i > 0) - result.append(", "); - if (ScriptRuntime.isValidIdentifierName(strId)) { - result.append(strId); - } else { - result.append('\''); - result.append( - ScriptRuntime.escapeString(strId, '\'')); - result.append('\''); - } - } - result.append(':'); - result.append(ScriptRuntime.uneval(cx, scope, value)); - } - } - } finally { - if (toplevel) { - cx.iterating = null; - } - } - - result.append('}'); - if (toplevel) { - result.append(')'); - } - return result.toString(); - } - - public static Scriptable toObject(Scriptable scope, Object val) - { - if (val instanceof Scriptable) { - return (Scriptable)val; - } - return toObject(Context.getContext(), scope, val); - } - - public static Scriptable toObjectOrNull(Context cx, Object obj) - { - if (obj instanceof Scriptable) { - return (Scriptable)obj; - } else if (obj != null && obj != Undefined.instance) { - return toObject(cx, getTopCallScope(cx), obj); - } - return null; - } - - /** - * @deprecated Use {@link #toObject(Scriptable, Object)} instead. - */ - public static Scriptable toObject(Scriptable scope, Object val, - Class staticClass) - { - if (val instanceof Scriptable) { - return (Scriptable)val; - } - return toObject(Context.getContext(), scope, val); - } - - /** - * Convert the value to an object. - * - * See ECMA 9.9. - */ - public static Scriptable toObject(Context cx, Scriptable scope, Object val) - { - if (val instanceof Scriptable) { - return (Scriptable) val; - } - if (val == null) { - throw typeError0("msg.null.to.object"); - } - if (val == Undefined.instance) { - throw typeError0("msg.undef.to.object"); - } - String className = val instanceof String ? "String" : - val instanceof Number ? "Number" : - val instanceof Boolean ? "Boolean" : - null; - if (className != null) { - Object[] args = { val }; - scope = ScriptableObject.getTopLevelScope(scope); - return newObject(cx, scope, className, args); - } - - // Extension: Wrap as a LiveConnect object. - Object wrapped = cx.getWrapFactory().wrap(cx, scope, val, null); - if (wrapped instanceof Scriptable) - return (Scriptable) wrapped; - throw errorWithClassName("msg.invalid.type", val); - } - - /** - * @deprecated Use {@link #toObject(Context, Scriptable, Object)} instead. - */ - public static Scriptable toObject(Context cx, Scriptable scope, Object val, - Class staticClass) - { - return toObject(cx, scope, val); - } - - /** - * @deprecated The method is only present for compatibility. - */ - public static Object call(Context cx, Object fun, Object thisArg, - Object[] args, Scriptable scope) - { - if (!(fun instanceof Function)) { - throw notFunctionError(toString(fun)); - } - Function function = (Function)fun; - Scriptable thisObj = toObjectOrNull(cx, thisArg); - if (thisObj == null) { - throw undefCallError(thisObj, "function"); - } - return function.call(cx, scope, thisObj, args); - } - - public static Scriptable newObject(Context cx, Scriptable scope, - String constructorName, Object[] args) - { - scope = ScriptableObject.getVeryTopLevelScope(scope); // APPJET - Function ctor = getExistingCtor(cx, scope, constructorName); - if (args == null) { args = ScriptRuntime.emptyArgs; } - return ctor.construct(cx, scope, args); - } - - /** - * - * See ECMA 9.4. - */ - public static double toInteger(Object val) { - return toInteger(toNumber(val)); - } - - // convenience method - public static double toInteger(double d) { - // if it's NaN - if (d != d) - return +0.0; - - if (d == 0.0 || - d == Double.POSITIVE_INFINITY || - d == Double.NEGATIVE_INFINITY) - return d; - - if (d > 0.0) - return Math.floor(d); - else - return Math.ceil(d); - } - - public static double toInteger(Object[] args, int index) { - return (index < args.length) ? toInteger(args[index]) : +0.0; - } - - /** - * - * See ECMA 9.5. - */ - public static int toInt32(Object val) - { - // short circuit for common integer values - if (val instanceof Integer) - return ((Integer)val).intValue(); - - return toInt32(toNumber(val)); - } - - public static int toInt32(Object[] args, int index) { - return (index < args.length) ? toInt32(args[index]) : 0; - } - - public static int toInt32(double d) { - int id = (int)d; - if (id == d) { - // This covers -0.0 as well - return id; - } - - if (d != d - || d == Double.POSITIVE_INFINITY - || d == Double.NEGATIVE_INFINITY) - { - return 0; - } - - d = (d >= 0) ? Math.floor(d) : Math.ceil(d); - - double two32 = 4294967296.0; - d = Math.IEEEremainder(d, two32); - // (double)(long)d == d should hold here - - long l = (long)d; - // returning (int)d does not work as d can be outside int range - // but the result must always be 32 lower bits of l - return (int)l; - } - - /** - * See ECMA 9.6. - * @return long value representing 32 bits unsigned integer - */ - public static long toUint32(double d) { - long l = (long)d; - if (l == d) { - // This covers -0.0 as well - return l & 0xffffffffL; - } - - if (d != d - || d == Double.POSITIVE_INFINITY - || d == Double.NEGATIVE_INFINITY) - { - return 0; - } - - d = (d >= 0) ? Math.floor(d) : Math.ceil(d); - - // 0x100000000 gives me a numeric overflow... - double two32 = 4294967296.0; - l = (long)Math.IEEEremainder(d, two32); - - return l & 0xffffffffL; - } - - public static long toUint32(Object val) { - return toUint32(toNumber(val)); - } - - /** - * - * See ECMA 9.7. - */ - public static char toUint16(Object val) { - double d = toNumber(val); - - int i = (int)d; - if (i == d) { - return (char)i; - } - - if (d != d - || d == Double.POSITIVE_INFINITY - || d == Double.NEGATIVE_INFINITY) - { - return 0; - } - - d = (d >= 0) ? Math.floor(d) : Math.ceil(d); - - int int16 = 0x10000; - i = (int)Math.IEEEremainder(d, int16); - - return (char)i; - } - - // XXX: this is until setDefaultNamespace will learn how to store NS - // properly and separates namespace form Scriptable.get etc. - private static final String DEFAULT_NS_TAG = "__default_namespace__"; - - public static Object setDefaultNamespace(Object namespace, Context cx) - { - Scriptable scope = cx.currentActivationCall; - if (scope == null) { - scope = getTopCallScope(cx); - } - - XMLLib xmlLib = currentXMLLib(cx); - Object ns = xmlLib.toDefaultXmlNamespace(cx, namespace); - - // XXX : this should be in separated namesapce from Scriptable.get/put - if (!scope.has(DEFAULT_NS_TAG, scope)) { - // XXX: this is racy of cause - ScriptableObject.defineProperty(scope, DEFAULT_NS_TAG, ns, - ScriptableObject.PERMANENT - | ScriptableObject.DONTENUM); - } else { - scope.put(DEFAULT_NS_TAG, scope, ns); - } - - return Undefined.instance; - } - - public static Object searchDefaultNamespace(Context cx) - { - Scriptable scope = cx.currentActivationCall; - if (scope == null) { - scope = getTopCallScope(cx); - } - Object nsObject; - for (;;) { - Scriptable parent = scope.getParentScope(); - if (parent == null) { - nsObject = ScriptableObject.getProperty(scope, DEFAULT_NS_TAG); - if (nsObject == Scriptable.NOT_FOUND) { - return null; - } - break; - } - nsObject = scope.get(DEFAULT_NS_TAG, scope); - if (nsObject != Scriptable.NOT_FOUND) { - break; - } - scope = parent; - } - return nsObject; - } - - public static Object getTopLevelProp(Scriptable scope, String id) { - scope = ScriptableObject.getTopLevelScope(scope); - return ScriptableObject.getProperty(scope, id); - } - - static Function getExistingCtor(Context cx, Scriptable scope, - String constructorName) - { - Object ctorVal = ScriptableObject.getProperty(scope, constructorName); - if (ctorVal instanceof Function) { - return (Function)ctorVal; - } - if (ctorVal == Scriptable.NOT_FOUND) { - throw Context.reportRuntimeError1( - "msg.ctor.not.found", constructorName); - } else { - throw Context.reportRuntimeError1( - "msg.not.ctor", constructorName); - } - } - - /** - * Return -1L if str is not an index or the index value as lower 32 - * bits of the result. - */ - private static long indexFromString(String str) - { - // The length of the decimal string representation of - // Integer.MAX_VALUE, 2147483647 - final int MAX_VALUE_LENGTH = 10; - - int len = str.length(); - if (len > 0) { - int i = 0; - boolean negate = false; - int c = str.charAt(0); - if (c == '-') { - if (len > 1) { - c = str.charAt(1); - i = 1; - negate = true; - } - } - c -= '0'; - if (0 <= c && c <= 9 - && len <= (negate ? MAX_VALUE_LENGTH + 1 : MAX_VALUE_LENGTH)) - { - // Use negative numbers to accumulate index to handle - // Integer.MIN_VALUE that is greater by 1 in absolute value - // then Integer.MAX_VALUE - int index = -c; - int oldIndex = 0; - i++; - if (index != 0) { - // Note that 00, 01, 000 etc. are not indexes - while (i != len && 0 <= (c = str.charAt(i) - '0') && c <= 9) - { - oldIndex = index; - index = 10 * index - c; - i++; - } - } - // Make sure all characters were consumed and that it couldn't - // have overflowed. - if (i == len && - (oldIndex > (Integer.MIN_VALUE / 10) || - (oldIndex == (Integer.MIN_VALUE / 10) && - c <= (negate ? -(Integer.MIN_VALUE % 10) - : (Integer.MAX_VALUE % 10))))) - { - return 0xFFFFFFFFL & (negate ? index : -index); - } - } - } - return -1L; - } - - /** - * If str is a decimal presentation of Uint32 value, return it as long. - * Othewise return -1L; - */ - public static long testUint32String(String str) - { - // The length of the decimal string representation of - // UINT32_MAX_VALUE, 4294967296 - final int MAX_VALUE_LENGTH = 10; - - int len = str.length(); - if (1 <= len && len <= MAX_VALUE_LENGTH) { - int c = str.charAt(0); - c -= '0'; - if (c == 0) { - // Note that 00,01 etc. are not valid Uint32 presentations - return (len == 1) ? 0L : -1L; - } - if (1 <= c && c <= 9) { - long v = c; - for (int i = 1; i != len; ++i) { - c = str.charAt(i) - '0'; - if (!(0 <= c && c <= 9)) { - return -1; - } - v = 10 * v + c; - } - // Check for overflow - if ((v >>> 32) == 0) { - return v; - } - } - } - return -1; - } - - /** - * If s represents index, then return index value wrapped as Integer - * and othewise return s. - */ - static Object getIndexObject(String s) - { - long indexTest = indexFromString(s); - if (indexTest >= 0) { - return new Integer((int)indexTest); - } - return s; - } - - /** - * If d is exact int value, return its value wrapped as Integer - * and othewise return d converted to String. - */ - static Object getIndexObject(double d) - { - int i = (int)d; - if (i == d) { - return new Integer(i); - } - return toString(d); - } - - /** - * If toString(id) is a decimal presentation of int32 value, then id - * is index. In this case return null and make the index available - * as ScriptRuntime.lastIndexResult(cx). Otherwise return toString(id). - */ - static String toStringIdOrIndex(Context cx, Object id) - { - if (id instanceof Number) { - double d = ((Number)id).doubleValue(); - int index = (int)d; - if (index == d) { - storeIndexResult(cx, index); - return null; - } - return toString(id); - } else { - String s; - if (id instanceof String) { - s = (String)id; - } else { - s = toString(id); - } - long indexTest = indexFromString(s); - if (indexTest >= 0) { - storeIndexResult(cx, (int)indexTest); - return null; - } - return s; - } - } - - /** - * Call obj.[[Get]](id) - */ - public static Object getObjectElem(Object obj, Object elem, Context cx) - { - Scriptable sobj = toObjectOrNull(cx, obj); - if (sobj == null) { - throw undefReadError(obj, elem); - } - return getObjectElem(sobj, elem, cx); - } - - public static Object getObjectElem(Scriptable obj, Object elem, - Context cx) - { - if (obj instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)obj; - return xmlObject.ecmaGet(cx, elem); - } - - Object result; - - String s = toStringIdOrIndex(cx, elem); - if (s == null) { - int index = lastIndexResult(cx); - result = ScriptableObject.getProperty(obj, index); - } else { - result = ScriptableObject.getProperty(obj, s); - } - - if (result == Scriptable.NOT_FOUND) { - result = Undefined.instance; - } - - return result; - } - - /** - * Version of getObjectElem when elem is a valid JS identifier name. - */ - public static Object getObjectProp(Object obj, String property, - Context cx) - { - Scriptable sobj = toObjectOrNull(cx, obj); - if (sobj == null) { - throw undefReadError(obj, property); - } - return getObjectProp(sobj, property, cx); - } - - public static Object getObjectProp(Scriptable obj, String property, - Context cx) - { - if (obj instanceof XMLObject) { - // TODO: Change XMLObject to just use Scriptable interface - // to avoid paying cost of instanceof check on *every property - // lookup* ! - XMLObject xmlObject = (XMLObject)obj; - return xmlObject.ecmaGet(cx, property); - } - - Object result = ScriptableObject.getProperty(obj, property); - if (result == Scriptable.NOT_FOUND) { - if (cx.hasFeature(Context.FEATURE_STRICT_MODE)) { - Context.reportWarning(ScriptRuntime.getMessage1( - "msg.ref.undefined.prop", property)); - } - result = Undefined.instance; - } - - return result; - } - - public static Object getObjectPropNoWarn(Object obj, String property, - Context cx) - { - Scriptable sobj = toObjectOrNull(cx, obj); - if (sobj == null) { - throw undefReadError(obj, property); - } - if (obj instanceof XMLObject) { - // TODO: fix as mentioned in note in method above - getObjectProp(sobj, property, cx); - } - Object result = ScriptableObject.getProperty(sobj, property); - if (result == Scriptable.NOT_FOUND) { - return Undefined.instance; - } - return result; - } - - /* - * A cheaper and less general version of the above for well-known argument - * types. - */ - public static Object getObjectIndex(Object obj, double dblIndex, - Context cx) - { - Scriptable sobj = toObjectOrNull(cx, obj); - if (sobj == null) { - throw undefReadError(obj, toString(dblIndex)); - } - - int index = (int)dblIndex; - if (index == dblIndex) { - return getObjectIndex(sobj, index, cx); - } else { - String s = toString(dblIndex); - return getObjectProp(sobj, s, cx); - } - } - - public static Object getObjectIndex(Scriptable obj, int index, - Context cx) - { - if (obj instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)obj; - return xmlObject.ecmaGet(cx, new Integer(index)); - } - - Object result = ScriptableObject.getProperty(obj, index); - if (result == Scriptable.NOT_FOUND) { - result = Undefined.instance; - } - - return result; - } - - /* - * Call obj.[[Put]](id, value) - */ - public static Object setObjectElem(Object obj, Object elem, Object value, - Context cx) - { - Scriptable sobj = toObjectOrNull(cx, obj); - if (sobj == null) { - throw undefWriteError(obj, elem, value); - } - return setObjectElem(sobj, elem, value, cx); - } - - public static Object setObjectElem(Scriptable obj, Object elem, - Object value, Context cx) - { - if (obj instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)obj; - xmlObject.ecmaPut(cx, elem, value); - return value; - } - - String s = toStringIdOrIndex(cx, elem); - if (s == null) { - int index = lastIndexResult(cx); - ScriptableObject.putProperty(obj, index, value); - } else { - ScriptableObject.putProperty(obj, s, value); - } - - return value; - } - - /** - * Version of setObjectElem when elem is a valid JS identifier name. - */ - public static Object setObjectProp(Object obj, String property, - Object value, Context cx) - { - Scriptable sobj = toObjectOrNull(cx, obj); - if (sobj == null) { - throw undefWriteError(obj, property, value); - } - return setObjectProp(sobj, property, value, cx); - } - - public static Object setObjectProp(Scriptable obj, String property, - Object value, Context cx) - { - if (obj instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)obj; - xmlObject.ecmaPut(cx, property, value); - } else { - ScriptableObject.putProperty(obj, property, value); - } - return value; - } - - /* - * A cheaper and less general version of the above for well-known argument - * types. - */ - public static Object setObjectIndex(Object obj, double dblIndex, - Object value, Context cx) - { - Scriptable sobj = toObjectOrNull(cx, obj); - if (sobj == null) { - throw undefWriteError(obj, String.valueOf(dblIndex), value); - } - - int index = (int)dblIndex; - if (index == dblIndex) { - return setObjectIndex(sobj, index, value, cx); - } else { - String s = toString(dblIndex); - return setObjectProp(sobj, s, value, cx); - } - } - - public static Object setObjectIndex(Scriptable obj, int index, Object value, - Context cx) - { - if (obj instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)obj; - xmlObject.ecmaPut(cx, new Integer(index), value); - } else { - ScriptableObject.putProperty(obj, index, value); - } - return value; - } - - public static boolean deleteObjectElem(Scriptable target, Object elem, - Context cx) - { - boolean result; - if (target instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)target; - result = xmlObject.ecmaDelete(cx, elem); - } else { - String s = toStringIdOrIndex(cx, elem); - if (s == null) { - int index = lastIndexResult(cx); - result = ScriptableObject.deleteProperty(target, index); - } else { - result = ScriptableObject.deleteProperty(target, s); - } - } - return result; - } - - public static boolean hasObjectElem(Scriptable target, Object elem, - Context cx) - { - boolean result; - - if (target instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)target; - result = xmlObject.ecmaHas(cx, elem); - } else { - String s = toStringIdOrIndex(cx, elem); - if (s == null) { - int index = lastIndexResult(cx); - result = ScriptableObject.hasProperty(target, index); - } else { - result = ScriptableObject.hasProperty(target, s); - } - } - - return result; - } - - public static Object refGet(Ref ref, Context cx) - { - return ref.get(cx); - } - - public static Object refSet(Ref ref, Object value, Context cx) - { - return ref.set(cx, value); - } - - public static Object refDel(Ref ref, Context cx) - { - return wrapBoolean(ref.delete(cx)); - } - - static boolean isSpecialProperty(String s) - { - return s.equals("__proto__") || s.equals("__parent__"); - } - - public static Ref specialRef(Object obj, String specialProperty, - Context cx) - { - return SpecialRef.createSpecial(cx, obj, specialProperty); - } - - /** - * The delete operator - * - * See ECMA 11.4.1 - * - * In ECMA 0.19, the description of the delete operator (11.4.1) - * assumes that the [[Delete]] method returns a value. However, - * the definition of the [[Delete]] operator (8.6.2.5) does not - * define a return value. Here we assume that the [[Delete]] - * method doesn't return a value. - */ - public static Object delete(Object obj, Object id, Context cx) - { - Scriptable sobj = toObjectOrNull(cx, obj); - if (sobj == null) { - String idStr = (id == null) ? "null" : id.toString(); - throw typeError2("msg.undef.prop.delete", toString(obj), idStr); - } - boolean result = deleteObjectElem(sobj, id, cx); - return wrapBoolean(result); - } - - /** - * Looks up a name in the scope chain and returns its value. - */ - public static Object name(Context cx, Scriptable scope, String name) - { - Scriptable parent = scope.getParentScope(); - if (parent == null) { - Object result = topScopeName(cx, scope, name); - if (result == Scriptable.NOT_FOUND) { - throw notFoundError(scope, name); - } - return result; - } - - return nameOrFunction(cx, scope, parent, name, false); - } - - private static Object nameOrFunction(Context cx, Scriptable scope, - Scriptable parentScope, String name, - boolean asFunctionCall) - { - Object result; - Scriptable thisObj = scope; // It is used only if asFunctionCall==true. - - XMLObject firstXMLObject = null; - for (;;) { - if (scope instanceof NativeWith) { - Scriptable withObj = scope.getPrototype(); - if (withObj instanceof XMLObject) { - XMLObject xmlObj = (XMLObject)withObj; - if (xmlObj.ecmaHas(cx, name)) { - // function this should be the target object of with - thisObj = xmlObj; - result = xmlObj.ecmaGet(cx, name); - break; - } - if (firstXMLObject == null) { - firstXMLObject = xmlObj; - } - } else { - result = ScriptableObject.getProperty(withObj, name); - if (result != Scriptable.NOT_FOUND) { - // function this should be the target object of with - thisObj = withObj; - break; - } - } - } else if (scope instanceof NativeCall) { - // NativeCall does not prototype chain and Scriptable.get - // can be called directly. - result = scope.get(name, scope); - if (result != Scriptable.NOT_FOUND) { - if (asFunctionCall) { - // ECMA 262 requires that this for nested funtions - // should be top scope - thisObj = ScriptableObject. - getTopLevelScope(parentScope); - } - break; - } - } else { - // Can happen if Rhino embedding decided that nested - // scopes are useful for what ever reasons. - result = ScriptableObject.getProperty(scope, name); - if (result != Scriptable.NOT_FOUND) { - thisObj = scope; - break; - } - } - scope = parentScope; - parentScope = parentScope.getParentScope(); - if (parentScope == null) { - result = topScopeName(cx, scope, name); - if (result == Scriptable.NOT_FOUND) { - if (firstXMLObject == null || asFunctionCall) { - throw notFoundError(scope, name); - } - // The name was not found, but we did find an XML - // object in the scope chain and we are looking for name, - // not function. The result should be an empty XMLList - // in name context. - result = firstXMLObject.ecmaGet(cx, name); - } - // For top scope thisObj for functions is always scope itself. - thisObj = scope; - break; - } - } - - if (asFunctionCall) { - if (!(result instanceof Callable)) { - throw notFunctionError(result, name); - } - storeScriptable(cx, thisObj); - } - - return result; - } - - private static Object topScopeName(Context cx, Scriptable scope, - String name) - { - if (cx.useDynamicScope) { - scope = checkDynamicScope(cx.topCallScope, scope); - } - return ScriptableObject.getProperty(scope, name); - } - - - /** - * Returns the object in the scope chain that has a given property. - * - * The order of evaluation of an assignment expression involves - * evaluating the lhs to a reference, evaluating the rhs, and then - * modifying the reference with the rhs value. This method is used - * to 'bind' the given name to an object containing that property - * so that the side effects of evaluating the rhs do not affect - * which property is modified. - * Typically used in conjunction with setName. - * - * See ECMA 10.1.4 - */ - public static Scriptable bind(Context cx, Scriptable scope, String id) - { - Scriptable firstXMLObject = null; - Scriptable parent = scope.getParentScope(); - childScopesChecks: if (parent != null) { - // Check for possibly nested "with" scopes first - while (scope instanceof NativeWith) { - Scriptable withObj = scope.getPrototype(); - if (withObj instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)withObj; - if (xmlObject.ecmaHas(cx, id)) { - return xmlObject; - } - if (firstXMLObject == null) { - firstXMLObject = xmlObject; - } - } else { - if (ScriptableObject.hasProperty(withObj, id)) { - return withObj; - } - } - scope = parent; - parent = parent.getParentScope(); - if (parent == null) { - break childScopesChecks; - } - } - for (;;) { - if (ScriptableObject.hasProperty(scope, id)) { - return scope; - } - scope = parent; - parent = parent.getParentScope(); - if (parent == null) { - break childScopesChecks; - } - } - } - // scope here is top scope - if (cx.useDynamicScope) { - scope = checkDynamicScope(cx.topCallScope, scope); - } - if (ScriptableObject.hasProperty(scope, id)) { - return scope; - } - // Nothing was found, but since XML objects always bind - // return one if found - return firstXMLObject; - } - - public static Object setName(Scriptable bound, Object value, - Context cx, Scriptable scope, String id) - { - if (bound != null) { - if (bound instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)bound; - xmlObject.ecmaPut(cx, id, value); - } else { - ScriptableObject.putProperty(bound, id, value); - } - } else { - // "newname = 7;", where 'newname' has not yet - // been defined, creates a new property in the - // top scope unless strict mode is specified. - if (cx.hasFeature(Context.FEATURE_STRICT_MODE) || - cx.hasFeature(Context.FEATURE_STRICT_VARS)) - { - Context.reportWarning( - ScriptRuntime.getMessage1("msg.assn.create.strict", id)); - } - // Find the top scope by walking up the scope chain. - bound = ScriptableObject.getTopLevelScope(scope); - if (cx.useDynamicScope) { - bound = checkDynamicScope(cx.topCallScope, bound); - } - bound.put(id, bound, value); - } - return value; - } - - public static Object setConst(Scriptable bound, Object value, - Context cx, String id) - { - if (bound instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)bound; - xmlObject.ecmaPut(cx, id, value); - } else { - ScriptableObject.putConstProperty(bound, id, value); - } - return value; - } - - /** - * This is the enumeration needed by the for..in statement. - * - * See ECMA 12.6.3. - * - * IdEnumeration maintains a ObjToIntMap to make sure a given - * id is enumerated only once across multiple objects in a - * prototype chain. - * - * XXX - ECMA delete doesn't hide properties in the prototype, - * but js/ref does. This means that the js/ref for..in can - * avoid maintaining a hash table and instead perform lookups - * to see if a given property has already been enumerated. - * - */ - private static class IdEnumeration implements Serializable - { - private static final long serialVersionUID = 1L; - Scriptable obj; - Object[] ids; - int index; - ObjToIntMap used; - Object currentId; - int enumType; /* one of ENUM_INIT_KEYS, ENUM_INIT_VALUES, - ENUM_INIT_ARRAY */ - - // if true, integer ids will be returned as numbers rather than strings - boolean enumNumbers; - - Scriptable iterator; - } - - public static Scriptable toIterator(Context cx, Scriptable scope, - Scriptable obj, boolean keyOnly) - { - /*APPJET 1.6*//* - if (ScriptableObject.hasProperty(obj, - NativeIterator.ITERATOR_PROPERTY_NAME)) - { - Object v = ScriptableObject.getProperty(obj, - NativeIterator.ITERATOR_PROPERTY_NAME); - if (!(v instanceof Callable)) { - throw typeError0("msg.invalid.iterator"); - } - Callable f = (Callable) v; - Object[] args = new Object[] { keyOnly ? Boolean.TRUE - : Boolean.FALSE }; - v = f.call(cx, scope, obj, args); - if (!(v instanceof Scriptable)) { - throw typeError0("msg.iterator.primitive"); - } - return (Scriptable) v; - }*/ - return null; - } - - // for backwards compatibility with generated class files - public static Object enumInit(Object value, Context cx, boolean enumValues) - { - return enumInit(value, cx, enumValues ? ENUMERATE_VALUES - : ENUMERATE_KEYS); - } - - public static final int ENUMERATE_KEYS = 0; - public static final int ENUMERATE_VALUES = 1; - public static final int ENUMERATE_ARRAY = 2; - public static final int ENUMERATE_KEYS_NO_ITERATOR = 3; - public static final int ENUMERATE_VALUES_NO_ITERATOR = 4; - public static final int ENUMERATE_ARRAY_NO_ITERATOR = 5; - - public static Object enumInit(Object value, Context cx, int enumType) - { - IdEnumeration x = new IdEnumeration(); - x.obj = toObjectOrNull(cx, value); - if (x.obj == null) { - // null or undefined do not cause errors but rather lead to empty - // "for in" loop - return x; - } - x.enumType = enumType; - x.iterator = null; - if (enumType != ENUMERATE_KEYS_NO_ITERATOR && - enumType != ENUMERATE_VALUES_NO_ITERATOR && - enumType != ENUMERATE_ARRAY_NO_ITERATOR) - { - x.iterator = toIterator(cx, x.obj.getParentScope(), x.obj, true); - } - if (x.iterator == null) { - // enumInit should read all initial ids before returning - // or "for (a.i in a)" would wrongly enumerate i in a as well - enumChangeObject(x); - } - - return x; - } - - public static void setEnumNumbers(Object enumObj, boolean enumNumbers) { - ((IdEnumeration)enumObj).enumNumbers = enumNumbers; - } - - public static Boolean enumNext(Object enumObj) - { - IdEnumeration x = (IdEnumeration)enumObj; - if (x.iterator != null) { - Object v = ScriptableObject.getProperty(x.iterator, "next"); - if (!(v instanceof Callable)) - return Boolean.FALSE; - Callable f = (Callable) v; - Context cx = Context.enter(); - try { - x.currentId = f.call(cx, x.iterator.getParentScope(), - x.iterator, emptyArgs); - return Boolean.TRUE; - } catch (JavaScriptException e) { - if (e.getValue() instanceof NativeIterator.StopIteration) { - return Boolean.FALSE; - } - throw e; - } finally { - Context.exit(); - } - } - for (;;) { - if (x.obj == null) { - return Boolean.FALSE; - } - if (x.index == x.ids.length) { - x.obj = x.obj.getPrototype(); - enumChangeObject(x); - continue; - } - Object id = x.ids[x.index++]; - if (x.used != null && x.used.has(id)) { - continue; - } - if (id instanceof String) { - String strId = (String)id; - if (!x.obj.has(strId, x.obj)) - continue; // must have been deleted - x.currentId = strId; - } else { - int intId = ((Number)id).intValue(); - if (!x.obj.has(intId, x.obj)) - continue; // must have been deleted - x.currentId = x.enumNumbers ? (Object) (new Integer(intId)) - : String.valueOf(intId); - } - return Boolean.TRUE; - } - } - - public static Object enumId(Object enumObj, Context cx) - { - IdEnumeration x = (IdEnumeration)enumObj; - if (x.iterator != null) { - return x.currentId; - } - switch (x.enumType) { - case ENUMERATE_KEYS: - case ENUMERATE_KEYS_NO_ITERATOR: - return x.currentId; - case ENUMERATE_VALUES: - case ENUMERATE_VALUES_NO_ITERATOR: - return enumValue(enumObj, cx); - case ENUMERATE_ARRAY: - case ENUMERATE_ARRAY_NO_ITERATOR: - Object[] elements = { x.currentId, enumValue(enumObj, cx) }; - return cx.newArray(x.obj.getParentScope(), elements); - default: - throw Kit.codeBug(); - } - } - - public static Object enumValue(Object enumObj, Context cx) { - IdEnumeration x = (IdEnumeration)enumObj; - - Object result; - - String s = toStringIdOrIndex(cx, x.currentId); - if (s == null) { - int index = lastIndexResult(cx); - result = x.obj.get(index, x.obj); - } else { - result = x.obj.get(s, x.obj); - } - - return result; - } - - private static void enumChangeObject(IdEnumeration x) - { - Object[] ids = null; - while (x.obj != null) { - ids = x.obj.getIds(); - if (ids.length != 0) { - break; - } - x.obj = x.obj.getPrototype(); - } - if (x.obj != null && x.ids != null) { - Object[] previous = x.ids; - int L = previous.length; - if (x.used == null) { - x.used = new ObjToIntMap(L); - } - for (int i = 0; i != L; ++i) { - x.used.intern(previous[i]); - } - } - x.ids = ids; - x.index = 0; - } - - /** - * Prepare for calling name(...): return function corresponding to - * name and make current top scope available - * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj. - * The caller must call ScriptRuntime.lastStoredScriptable() immediately - * after calling this method. - */ - public static Callable getNameFunctionAndThis(String name, - Context cx, - Scriptable scope) - { - Scriptable parent = scope.getParentScope(); - if (parent == null) { - Object result = topScopeName(cx, scope, name); - if (!(result instanceof Callable)) { - if (result == Scriptable.NOT_FOUND) { - throw notFoundError(scope, name); - } else { - throw notFunctionError(result, name); - } - } - // Top scope is not NativeWith or NativeCall => thisObj == scope - Scriptable thisObj = scope; - storeScriptable(cx, thisObj); - return (Callable)result; - } - - // name will call storeScriptable(cx, thisObj); - return (Callable)nameOrFunction(cx, scope, parent, name, true); - } - - /** - * Prepare for calling obj[id](...): return function corresponding to - * obj[id] and make obj properly converted to Scriptable available - * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj. - * The caller must call ScriptRuntime.lastStoredScriptable() immediately - * after calling this method. - */ - public static Callable getElemFunctionAndThis(Object obj, - Object elem, - Context cx) - { - String s = toStringIdOrIndex(cx, elem); - if (s != null) { - return getPropFunctionAndThis(obj, s, cx); - } - int index = lastIndexResult(cx); - - Scriptable thisObj = toObjectOrNull(cx, obj); - if (thisObj == null) { - throw undefCallError(obj, String.valueOf(index)); - } - - Object value; - for (;;) { - // Ignore XML lookup as requred by ECMA 357, 11.2.2.1 - value = ScriptableObject.getProperty(thisObj, index); - if (value != Scriptable.NOT_FOUND) { - break; - } - if (!(thisObj instanceof XMLObject)) { - break; - } - XMLObject xmlObject = (XMLObject)thisObj; - Scriptable extra = xmlObject.getExtraMethodSource(cx); - if (extra == null) { - break; - } - thisObj = extra; - } - if (!(value instanceof Callable)) { - throw notFunctionError(value, elem); - } - - storeScriptable(cx, thisObj); - return (Callable)value; - } - - /** - * Prepare for calling obj.property(...): return function corresponding to - * obj.property and make obj properly converted to Scriptable available - * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj. - * The caller must call ScriptRuntime.lastStoredScriptable() immediately - * after calling this method. - */ - public static Callable getPropFunctionAndThis(Object obj, - String property, - Context cx) - { - Scriptable thisObj = toObjectOrNull(cx, obj); - if (thisObj == null) { - throw undefCallError(obj, property); - } - - Object value; - for (;;) { - // Ignore XML lookup as required by ECMA 357, 11.2.2.1 - value = ScriptableObject.getProperty(thisObj, property); - if (value != Scriptable.NOT_FOUND) { - break; - } - if (!(thisObj instanceof XMLObject)) { - break; - } - XMLObject xmlObject = (XMLObject)thisObj; - Scriptable extra = xmlObject.getExtraMethodSource(cx); - if (extra == null) { - break; - } - thisObj = extra; - } - - if (!(value instanceof Callable)) { - Object noSuchMethod = ScriptableObject.getProperty(thisObj, "__noSuchMethod__"); - if (noSuchMethod instanceof Callable) - value = new NoSuchMethodShim((Callable)noSuchMethod, property); - else - throw notFunctionError(thisObj, value, property); - } - - storeScriptable(cx, thisObj); - return (Callable)value; - } - - /** - * Prepare for calling <expression>(...): return function corresponding to - * <expression> and make parent scope of the function available - * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj. - * The caller must call ScriptRuntime.lastStoredScriptable() immediately - * after calling this method. - */ - public static Callable getValueFunctionAndThis(Object value, Context cx) - { - if (!(value instanceof Callable)) { - throw notFunctionError(value); - } - - Callable f = (Callable)value; - Scriptable thisObj = null; - if (f instanceof Scriptable) { - thisObj = ((Scriptable)f).getParentScope(); - } - if (thisObj == null) { - if (cx.topCallScope == null) throw new IllegalStateException(); - thisObj = cx.topCallScope; - } - if (thisObj.getParentScope() != null) { - if (thisObj instanceof NativeWith) { - // functions defined inside with should have with target - // as their thisObj - } else if (thisObj instanceof NativeCall) { - // nested functions should have top scope as their thisObj - thisObj = ScriptableObject.getTopLevelScope(thisObj); - } - } - storeScriptable(cx, thisObj); - return f; - } - - /** - * Perform function call in reference context. Should always - * return value that can be passed to - * {@link #refGet(Ref, Context)} or {@link #refSet(Ref, Object, Context)} - * arbitrary number of times. - * The args array reference should not be stored in any object that is - * can be GC-reachable after this method returns. If this is necessary, - * store args.clone(), not args array itself. - */ - public static Ref callRef(Callable function, Scriptable thisObj, - Object[] args, Context cx) - { - if (function instanceof RefCallable) { - RefCallable rfunction = (RefCallable)function; - Ref ref = rfunction.refCall(cx, thisObj, args); - if (ref == null) { - throw new IllegalStateException(rfunction.getClass().getName()+".refCall() returned null"); - } - return ref; - } - // No runtime support for now - String msg = getMessage1("msg.no.ref.from.function", - toString(function)); - throw constructError("ReferenceError", msg); - } - - /** - * Operator new. - * - * See ECMA 11.2.2 - */ - public static Scriptable newObject(Object fun, Context cx, - Scriptable scope, Object[] args) - { - if (!(fun instanceof Function)) { - throw notFunctionError(fun); - } - Function function = (Function)fun; - return function.construct(cx, scope, args); - } - - public static Object callSpecial(Context cx, Callable fun, - Scriptable thisObj, - Object[] args, Scriptable scope, - Scriptable callerThis, int callType, - String filename, int lineNumber) - { - if (callType == Node.SPECIALCALL_EVAL) { - if (NativeGlobal.isEvalFunction(fun)) { - return evalSpecial(cx, scope, callerThis, args, - filename, lineNumber); - } - } else if (callType == Node.SPECIALCALL_WITH) { - if (NativeWith.isWithFunction(fun)) { - throw Context.reportRuntimeError1("msg.only.from.new", - "With"); - } - } else { - throw Kit.codeBug(); - } - - return fun.call(cx, scope, thisObj, args); - } - - public static Object newSpecial(Context cx, Object fun, - Object[] args, Scriptable scope, - int callType) - { - if (callType == Node.SPECIALCALL_EVAL) { - if (NativeGlobal.isEvalFunction(fun)) { - throw typeError1("msg.not.ctor", "eval"); - } - } else if (callType == Node.SPECIALCALL_WITH) { - if (NativeWith.isWithFunction(fun)) { - return NativeWith.newWithSpecial(cx, scope, args); - } - } else { - throw Kit.codeBug(); - } - - return newObject(fun, cx, scope, args); - } - - /** - * Function.prototype.apply and Function.prototype.call - * - * See Ecma 15.3.4.[34] - */ - public static Object applyOrCall(boolean isApply, - Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - int L = args.length; - Callable function = getCallable(thisObj); - - Scriptable callThis = null; - if (L != 0) { - callThis = toObjectOrNull(cx, args[0]); - } - if (callThis == null) { - // This covers the case of args[0] == (null|undefined) as well. - callThis = getTopCallScope(cx); - } - - Object[] callArgs; - if (isApply) { - // Follow Ecma 15.3.4.3 - callArgs = L <= 1 ? ScriptRuntime.emptyArgs : - getApplyArguments(cx, args[1]); - } else { - // Follow Ecma 15.3.4.4 - if (L <= 1) { - callArgs = ScriptRuntime.emptyArgs; - } else { - callArgs = new Object[L - 1]; - System.arraycopy(args, 1, callArgs, 0, L - 1); - } - } - - return function.call(cx, scope, callThis, callArgs); - } - - static Object[] getApplyArguments(Context cx, Object arg1) - { - if (arg1 == null || arg1 == Undefined.instance) { - return ScriptRuntime.emptyArgs; - } else if (arg1 instanceof NativeArray || arg1 instanceof Arguments) { - return cx.getElements((Scriptable) arg1); - } else { - throw ScriptRuntime.typeError0("msg.arg.isnt.array"); - } - } - - static Callable getCallable(Scriptable thisObj) - { - Callable function; - if (thisObj instanceof Callable) { - function = (Callable)thisObj; - } else { - Object value = thisObj.getDefaultValue(ScriptRuntime.FunctionClass); - if (!(value instanceof Callable)) { - throw ScriptRuntime.notFunctionError(value, thisObj); - } - function = (Callable)value; - } - return function; - } - - /** - * The eval function property of the global object. - * - * See ECMA 15.1.2.1 - */ - public static Object evalSpecial(Context cx, Scriptable scope, - Object thisArg, Object[] args, - String filename, int lineNumber) - { - if (args.length < 1) - return Undefined.instance; - Object x = args[0]; - if (!(x instanceof String)) { - if (cx.hasFeature(Context.FEATURE_STRICT_MODE) || - cx.hasFeature(Context.FEATURE_STRICT_EVAL)) - { - throw Context.reportRuntimeError0("msg.eval.nonstring.strict"); - } - String message = ScriptRuntime.getMessage0("msg.eval.nonstring"); - Context.reportWarning(message); - return x; - } - if (filename == null) { - int[] linep = new int[1]; - filename = Context.getSourcePositionFromStack(linep); - if (filename != null) { - lineNumber = linep[0]; - } else { - filename = ""; - } - } - String sourceName = ScriptRuntime. - makeUrlForGeneratedScript(true, filename, lineNumber); - - ErrorReporter reporter; - reporter = DefaultErrorReporter.forEval(cx.getErrorReporter()); - - Evaluator evaluator = Context.createInterpreter(); - if (evaluator == null) { - throw new JavaScriptException("Interpreter not present", - filename, lineNumber); - } - - // Compile with explicit interpreter instance to force interpreter - // mode. - Script script = cx.compileString((String)x, evaluator, - reporter, sourceName, 1, null); - evaluator.setEvalScriptFlag(script); - Callable c = (Callable)script; - return c.call(cx, scope, (Scriptable)thisArg, ScriptRuntime.emptyArgs); - } - - /** - * The typeof operator - */ - public static String typeof(Object value) - { - if (value == null) - return "object"; - if (value == Undefined.instance) - return "undefined"; - if (value instanceof Scriptable) - { - if (value instanceof ScriptableObject && - ((ScriptableObject)value).avoidObjectDetection()) - { - return "undefined"; - } - if (value instanceof XMLObject) - return "xml"; - return (value instanceof Callable) ? "function" : "object"; - } - if (value instanceof String) - return "string"; - if (value instanceof Number) - return "number"; - if (value instanceof Boolean) - return "boolean"; - throw errorWithClassName("msg.invalid.type", value); - } - - /** - * The typeof operator that correctly handles the undefined case - */ - public static String typeofName(Scriptable scope, String id) - { - Context cx = Context.getContext(); - Scriptable val = bind(cx, scope, id); - if (val == null) - return "undefined"; - return typeof(getObjectProp(val, id, cx)); - } - - // neg: - // implement the '-' operator inline in the caller - // as "-toNumber(val)" - - // not: - // implement the '!' operator inline in the caller - // as "!toBoolean(val)" - - // bitnot: - // implement the '~' operator inline in the caller - // as "~toInt32(val)" - - public static Object add(Object val1, Object val2, Context cx) - { - if(val1 instanceof Number && val2 instanceof Number) { - return wrapNumber(((Number)val1).doubleValue() + - ((Number)val2).doubleValue()); - } - if (val1 instanceof XMLObject) { - Object test = ((XMLObject)val1).addValues(cx, true, val2); - if (test != Scriptable.NOT_FOUND) { - return test; - } - } - if (val2 instanceof XMLObject) { - Object test = ((XMLObject)val2).addValues(cx, false, val1); - if (test != Scriptable.NOT_FOUND) { - return test; - } - } - if (val1 instanceof Scriptable) - val1 = ((Scriptable) val1).getDefaultValue(null); - if (val2 instanceof Scriptable) - val2 = ((Scriptable) val2).getDefaultValue(null); - if (!(val1 instanceof String) && !(val2 instanceof String)) - if ((val1 instanceof Number) && (val2 instanceof Number)) - return wrapNumber(((Number)val1).doubleValue() + - ((Number)val2).doubleValue()); - else - return wrapNumber(toNumber(val1) + toNumber(val2)); - return toString(val1).concat(toString(val2)); - } - - public static String add(String val1, Object val2) { - return val1.concat(toString(val2)); - } - - public static String add(Object val1, String val2) { - return toString(val1).concat(val2); - } - - /** - * @deprecated The method is only present for compatibility. - */ - public static Object nameIncrDecr(Scriptable scopeChain, String id, - int incrDecrMask) - { - return nameIncrDecr(scopeChain, id, Context.getContext(), incrDecrMask); - } - - public static Object nameIncrDecr(Scriptable scopeChain, String id, - Context cx, int incrDecrMask) - { - Scriptable target; - Object value; - search: { - do { - if (cx.useDynamicScope && scopeChain.getParentScope() == null) { - scopeChain = checkDynamicScope(cx.topCallScope, scopeChain); - } - target = scopeChain; - do { - value = target.get(id, scopeChain); - if (value != Scriptable.NOT_FOUND) { - break search; - } - target = target.getPrototype(); - } while (target != null); - scopeChain = scopeChain.getParentScope(); - } while (scopeChain != null); - throw notFoundError(scopeChain, id); - } - return doScriptableIncrDecr(target, id, scopeChain, value, - incrDecrMask); - } - - public static Object propIncrDecr(Object obj, String id, - Context cx, int incrDecrMask) - { - Scriptable start = toObjectOrNull(cx, obj); - if (start == null) { - throw undefReadError(obj, id); - } - - Scriptable target = start; - Object value; - search: { - do { - value = target.get(id, start); - if (value != Scriptable.NOT_FOUND) { - break search; - } - target = target.getPrototype(); - } while (target != null); - start.put(id, start, NaNobj); - return NaNobj; - } - return doScriptableIncrDecr(target, id, start, value, - incrDecrMask); - } - - private static Object doScriptableIncrDecr(Scriptable target, - String id, - Scriptable protoChainStart, - Object value, - int incrDecrMask) - { - boolean post = ((incrDecrMask & Node.POST_FLAG) != 0); - double number; - if (value instanceof Number) { - number = ((Number)value).doubleValue(); - } else { - number = toNumber(value); - if (post) { - // convert result to number - value = wrapNumber(number); - } - } - if ((incrDecrMask & Node.DECR_FLAG) == 0) { - ++number; - } else { - --number; - } - Number result = wrapNumber(number); - target.put(id, protoChainStart, result); - if (post) { - return value; - } else { - return result; - } - } - - public static Object elemIncrDecr(Object obj, Object index, - Context cx, int incrDecrMask) - { - Object value = getObjectElem(obj, index, cx); - boolean post = ((incrDecrMask & Node.POST_FLAG) != 0); - double number; - if (value instanceof Number) { - number = ((Number)value).doubleValue(); - } else { - number = toNumber(value); - if (post) { - // convert result to number - value = wrapNumber(number); - } - } - if ((incrDecrMask & Node.DECR_FLAG) == 0) { - ++number; - } else { - --number; - } - Number result = wrapNumber(number); - setObjectElem(obj, index, result, cx); - if (post) { - return value; - } else { - return result; - } - } - - public static Object refIncrDecr(Ref ref, Context cx, int incrDecrMask) - { - Object value = ref.get(cx); - boolean post = ((incrDecrMask & Node.POST_FLAG) != 0); - double number; - if (value instanceof Number) { - number = ((Number)value).doubleValue(); - } else { - number = toNumber(value); - if (post) { - // convert result to number - value = wrapNumber(number); - } - } - if ((incrDecrMask & Node.DECR_FLAG) == 0) { - ++number; - } else { - --number; - } - Number result = wrapNumber(number); - ref.set(cx, result); - if (post) { - return value; - } else { - return result; - } - } - - private static Object toPrimitive(Object val) - { - if (!(val instanceof Scriptable)) { - return val; - } - Scriptable s = (Scriptable)val; - Object result = s.getDefaultValue(null); - if (result instanceof Scriptable) - throw typeError0("msg.bad.default.value"); - return result; - } - - /** - * Equality - * - * See ECMA 11.9 - */ - public static boolean eq(Object x, Object y) - { - if (x == null || x == Undefined.instance) { - if (y == null || y == Undefined.instance) { - return true; - } - if (y instanceof ScriptableObject) { - Object test = ((ScriptableObject)y).equivalentValues(x); - if (test != Scriptable.NOT_FOUND) { - return ((Boolean)test).booleanValue(); - } - } - return false; - } else if (x instanceof Number) { - return eqNumber(((Number)x).doubleValue(), y); - } else if (x instanceof String) { - return eqString((String)x, y); - } else if (x instanceof Boolean) { - boolean b = ((Boolean)x).booleanValue(); - if (y instanceof Boolean) { - return b == ((Boolean)y).booleanValue(); - } - if (y instanceof ScriptableObject) { - Object test = ((ScriptableObject)y).equivalentValues(x); - if (test != Scriptable.NOT_FOUND) { - return ((Boolean)test).booleanValue(); - } - } - return eqNumber(b ? 1.0 : 0.0, y); - } else if (x instanceof Scriptable) { - if (y instanceof Scriptable) { - if (x == y) { - return true; - } - if (x instanceof ScriptableObject) { - Object test = ((ScriptableObject)x).equivalentValues(y); - if (test != Scriptable.NOT_FOUND) { - return ((Boolean)test).booleanValue(); - } - } - if (y instanceof ScriptableObject) { - Object test = ((ScriptableObject)y).equivalentValues(x); - if (test != Scriptable.NOT_FOUND) { - return ((Boolean)test).booleanValue(); - } - } - if (x instanceof Wrapper && y instanceof Wrapper) { - // See bug 413838. Effectively an extension to ECMA for - // the LiveConnect case. - Object unwrappedX = ((Wrapper)x).unwrap(); - Object unwrappedY = ((Wrapper)y).unwrap(); - return unwrappedX == unwrappedY || - (isPrimitive(unwrappedX) && - isPrimitive(unwrappedY) && - eq(unwrappedX, unwrappedY)); - } - return false; - } else if (y instanceof Boolean) { - if (x instanceof ScriptableObject) { - Object test = ((ScriptableObject)x).equivalentValues(y); - if (test != Scriptable.NOT_FOUND) { - return ((Boolean)test).booleanValue(); - } - } - double d = ((Boolean)y).booleanValue() ? 1.0 : 0.0; - return eqNumber(d, x); - } else if (y instanceof Number) { - return eqNumber(((Number)y).doubleValue(), x); - } else if (y instanceof String) { - return eqString((String)y, x); - } - // covers the case when y == Undefined.instance as well - return false; - } else { - warnAboutNonJSObject(x); - return x == y; - } - } - - private static boolean isPrimitive(Object obj) { - return (obj instanceof Number) || (obj instanceof String) || - (obj instanceof Boolean); - } - - static boolean eqNumber(double x, Object y) - { - for (;;) { - if (y == null || y == Undefined.instance) { - return false; - } else if (y instanceof Number) { - return x == ((Number)y).doubleValue(); - } else if (y instanceof String) { - return x == toNumber(y); - } else if (y instanceof Boolean) { - return x == (((Boolean)y).booleanValue() ? 1.0 : +0.0); - } else if (y instanceof Scriptable) { - if (y instanceof ScriptableObject) { - Object xval = wrapNumber(x); - Object test = ((ScriptableObject)y).equivalentValues(xval); - if (test != Scriptable.NOT_FOUND) { - return ((Boolean)test).booleanValue(); - } - } - y = toPrimitive(y); - } else { - warnAboutNonJSObject(y); - return false; - } - } - } - - private static boolean eqString(String x, Object y) - { - for (;;) { - if (y == null || y == Undefined.instance) { - return false; - } else if (y instanceof String) { - return x.equals(y); - } else if (y instanceof Number) { - return toNumber(x) == ((Number)y).doubleValue(); - } else if (y instanceof Boolean) { - return toNumber(x) == (((Boolean)y).booleanValue() ? 1.0 : 0.0); - } else if (y instanceof Scriptable) { - if (y instanceof ScriptableObject) { - Object test = ((ScriptableObject)y).equivalentValues(x); - if (test != Scriptable.NOT_FOUND) { - return ((Boolean)test).booleanValue(); - } - } - y = toPrimitive(y); - continue; - } else { - warnAboutNonJSObject(y); - return false; - } - } - } - public static boolean shallowEq(Object x, Object y) - { - if (x == y) { - if (!(x instanceof Number)) { - return true; - } - // NaN check - double d = ((Number)x).doubleValue(); - return d == d; - } - if (x == null || x == Undefined.instance) { - return false; - } else if (x instanceof Number) { - if (y instanceof Number) { - return ((Number)x).doubleValue() == ((Number)y).doubleValue(); - } - } else if (x instanceof String) { - if (y instanceof String) { - return x.equals(y); - } - } else if (x instanceof Boolean) { - if (y instanceof Boolean) { - return x.equals(y); - } - } else if (x instanceof Scriptable) { - if (x instanceof Wrapper && y instanceof Wrapper) { - return ((Wrapper)x).unwrap() == ((Wrapper)y).unwrap(); - } - } else { - warnAboutNonJSObject(x); - return x == y; - } - return false; - } - - /** - * The instanceof operator. - * - * @return a instanceof b - */ - public static boolean instanceOf(Object a, Object b, Context cx) - { - // Check RHS is an object - if (! (b instanceof Scriptable)) { - throw typeError0("msg.instanceof.not.object"); - } - - // for primitive values on LHS, return false - // XXX we may want to change this so that - // 5 instanceof Number == true - if (! (a instanceof Scriptable)) - return false; - - return ((Scriptable)b).hasInstance((Scriptable)a); - } - - /** - * Delegates to - * - * @return true iff rhs appears in lhs' proto chain - */ - public static boolean jsDelegatesTo(Scriptable lhs, Scriptable rhs) { - Scriptable proto = lhs.getPrototype(); - - while (proto != null) { - if (proto.equals(rhs)) return true; - proto = proto.getPrototype(); - } - - return false; - } - - /** - * The in operator. - * - * This is a new JS 1.3 language feature. The in operator mirrors - * the operation of the for .. in construct, and tests whether the - * rhs has the property given by the lhs. It is different from the - * for .. in construct in that: - * <BR> - it doesn't perform ToObject on the right hand side - * <BR> - it returns true for DontEnum properties. - * @param a the left hand operand - * @param b the right hand operand - * - * @return true if property name or element number a is a property of b - */ - public static boolean in(Object a, Object b, Context cx) - { - if (!(b instanceof Scriptable)) { - throw typeError0("msg.instanceof.not.object"); - } - - return hasObjectElem((Scriptable)b, a, cx); - } - - public static boolean cmp_LT(Object val1, Object val2) - { - double d1, d2; - if (val1 instanceof Number && val2 instanceof Number) { - d1 = ((Number)val1).doubleValue(); - d2 = ((Number)val2).doubleValue(); - } else { - if (val1 instanceof Scriptable) - val1 = ((Scriptable) val1).getDefaultValue(NumberClass); - if (val2 instanceof Scriptable) - val2 = ((Scriptable) val2).getDefaultValue(NumberClass); - if (val1 instanceof String && val2 instanceof String) { - return ((String)val1).compareTo((String)val2) < 0; - } - d1 = toNumber(val1); - d2 = toNumber(val2); - } - return d1 < d2; - } - - public static boolean cmp_LE(Object val1, Object val2) - { - double d1, d2; - if (val1 instanceof Number && val2 instanceof Number) { - d1 = ((Number)val1).doubleValue(); - d2 = ((Number)val2).doubleValue(); - } else { - if (val1 instanceof Scriptable) - val1 = ((Scriptable) val1).getDefaultValue(NumberClass); - if (val2 instanceof Scriptable) - val2 = ((Scriptable) val2).getDefaultValue(NumberClass); - if (val1 instanceof String && val2 instanceof String) { - return ((String)val1).compareTo((String)val2) <= 0; - } - d1 = toNumber(val1); - d2 = toNumber(val2); - } - return d1 <= d2; - } - - // ------------------ - // Statements - // ------------------ - - public static ScriptableObject getGlobal(Context cx) { - final String GLOBAL_CLASS = "org.mozilla.javascript.tools.shell.Global"; - Class globalClass = Kit.classOrNull(GLOBAL_CLASS); - if (globalClass != null) { - try { - Class[] parm = { ScriptRuntime.ContextClass }; - Constructor globalClassCtor = globalClass.getConstructor(parm); - Object[] arg = { cx }; - return (ScriptableObject) globalClassCtor.newInstance(arg); - } catch (Exception e) { - // fall through... - } - } - return new ImporterTopLevel(cx); - } - - public static boolean hasTopCall(Context cx) - { - return (cx.topCallScope != null); - } - - public static Scriptable getTopCallScope(Context cx) - { - Scriptable scope = cx.topCallScope; - if (scope == null) { - throw new IllegalStateException(); - } - return scope; - } - - public static Object doTopCall(Callable callable, - Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (scope == null) throw new IllegalArgumentException(); - if (cx.topCallScope != null) throw new IllegalStateException(); - - Object result; - cx.topCallScope = ScriptableObject.getTopLevelScope(scope); - cx.useDynamicScope = cx.hasFeature(Context.FEATURE_DYNAMIC_SCOPE); - ContextFactory f = cx.getFactory(); - try { - result = f.doTopCall(callable, cx, scope, thisObj, args); - } finally { - cx.topCallScope = null; - // Cleanup cached references - cx.cachedXMLLib = null; - - if (cx.currentActivationCall != null) { - // Function should always call exitActivationFunction - // if it creates activation record - throw new IllegalStateException(); - } - } - return result; - } - - /** - * Return <tt>possibleDynamicScope</tt> if <tt>staticTopScope</tt> - * is present on its prototype chain and return <tt>staticTopScope</tt> - * otherwise. - * Should only be called when <tt>staticTopScope</tt> is top scope. - */ - static Scriptable checkDynamicScope(Scriptable possibleDynamicScope, - Scriptable staticTopScope) - { - // Return cx.topCallScope if scope - if (possibleDynamicScope == staticTopScope) { - return possibleDynamicScope; - } - Scriptable proto = possibleDynamicScope; - for (;;) { - proto = proto.getPrototype(); - if (proto == staticTopScope) { - return possibleDynamicScope; - } - if (proto == null) { - return staticTopScope; - } - } - } - - public static void addInstructionCount(Context cx, int instructionsToAdd) - { - cx.instructionCount += instructionsToAdd; - if (cx.instructionCount > cx.instructionThreshold) - { - cx.observeInstructionCount(cx.instructionCount); - cx.instructionCount = 0; - } - } - - public static void initScript(NativeFunction funObj, Scriptable thisObj, - Context cx, Scriptable scope, - boolean evalScript) - { - if (cx.topCallScope == null) - throw new IllegalStateException(); - - int varCount = funObj.getParamAndVarCount(); - if (varCount != 0) { - - Scriptable varScope = scope; - // Never define any variables from var statements inside with - // object. See bug 38590. - while (varScope instanceof NativeWith) { - varScope = varScope.getParentScope(); - } - - for (int i = varCount; i-- != 0;) { - String name = funObj.getParamOrVarName(i); - boolean isConst = funObj.getParamOrVarConst(i); - // Don't overwrite existing def if already defined in object - // or prototypes of object. - if (!ScriptableObject.hasProperty(scope, name)) { - if (!evalScript) { - // Global var definitions are supposed to be DONTDELETE - if (isConst) - ScriptableObject.defineConstProperty(varScope, name); - else - ScriptableObject.defineProperty( - varScope, name, Undefined.instance, - ScriptableObject.PERMANENT); - } else { - varScope.put(name, varScope, Undefined.instance); - } - } else { - ScriptableObject.redefineProperty(scope, name, isConst); - } - } - } - } - - public static Scriptable createFunctionActivation(NativeFunction funObj, - Scriptable scope, - Object[] args) - { - return new NativeCall(funObj, scope, args); - } - - - public static void enterActivationFunction(Context cx, - Scriptable scope) - { - if (cx.topCallScope == null) - throw new IllegalStateException(); - NativeCall call = (NativeCall)scope; - call.parentActivationCall = cx.currentActivationCall; - cx.currentActivationCall = call; - } - - public static void exitActivationFunction(Context cx) - { - NativeCall call = cx.currentActivationCall; - cx.currentActivationCall = call.parentActivationCall; - call.parentActivationCall = null; - } - - static NativeCall findFunctionActivation(Context cx, Function f) - { - NativeCall call = cx.currentActivationCall; - while (call != null) { - if (call.function == f) - return call; - call = call.parentActivationCall; - } - return null; - } - - public static Scriptable newCatchScope(Throwable t, - Scriptable lastCatchScope, - String exceptionName, - Context cx, Scriptable scope) - { - Object obj; - boolean cacheObj; - - getObj: - if (t instanceof JavaScriptException) { - cacheObj = false; - obj = ((JavaScriptException)t).getValue(); - } else { - cacheObj = true; - - // Create wrapper object unless it was associated with - // the previous scope object - - if (lastCatchScope != null) { - NativeObject last = (NativeObject)lastCatchScope; - obj = last.getAssociatedValue(t); - if (obj == null) Kit.codeBug(); - break getObj; - } - - RhinoException re; - String errorName; - String errorMsg; - Throwable javaException = null; - - if (t instanceof EcmaError) { - EcmaError ee = (EcmaError)t; - re = ee; - errorName = ee.getName(); - errorMsg = ee.getErrorMessage(); - } else if (t instanceof WrappedException) { - WrappedException we = (WrappedException)t; - re = we; - javaException = we.getWrappedException(); - errorName = "JavaException"; - errorMsg = javaException.getClass().getName() - +": "+javaException.getMessage(); - } else if (t instanceof EvaluatorException) { - // Pure evaluator exception, nor WrappedException instance - EvaluatorException ee = (EvaluatorException)t; - re = ee; - errorName = "InternalError"; - errorMsg = ee.getMessage(); - } else if (cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS)) { - // With FEATURE_ENHANCED_JAVA_ACCESS, scripts can catch - // all exception types - re = new WrappedException(t); - errorName = "JavaException"; - errorMsg = t.toString(); - } else { - // Script can catch only instances of JavaScriptException, - // EcmaError and EvaluatorException - throw Kit.codeBug(); - } - - String sourceUri = re.sourceName(); - if (sourceUri == null) { - sourceUri = ""; - } - int line = re.lineNumber(); - Object args[]; - if (line > 0) { - args = new Object[] { errorMsg, sourceUri, new Integer(line) }; - } else { - args = new Object[] { errorMsg, sourceUri }; - } - - Scriptable errorObject = cx.newObject(scope, errorName, args); - ScriptableObject.putProperty(errorObject, "name", errorName); - - if (javaException != null) { - Object wrap = cx.getWrapFactory().wrap(cx, scope, javaException, - null); - ScriptableObject.defineProperty( - errorObject, "javaException", wrap, - ScriptableObject.PERMANENT | ScriptableObject.READONLY); - } - Object wrap = cx.getWrapFactory().wrap(cx, scope, re, null); - ScriptableObject.defineProperty( - errorObject, "rhinoException", wrap, - ScriptableObject.PERMANENT | ScriptableObject.READONLY); - - obj = errorObject; - } - - NativeObject catchScopeObject = new NativeObject(); - // See ECMA 12.4 - catchScopeObject.defineProperty( - exceptionName, obj, ScriptableObject.PERMANENT); - - // Add special Rhino object __exception__ defined in the catch - // scope that can be used to retrieve the Java exception associated - // with the JavaScript exception (to get stack trace info, etc.) - /*APPJET NOJAVA*/ - /*catchScopeObject.defineProperty( - "__exception__", Context.javaToJS(t, scope), - ScriptableObject.PERMANENT|ScriptableObject.DONTENUM);*/ - - if (cacheObj) { - catchScopeObject.associateValue(t, obj); - } - return catchScopeObject; - } - - public static Scriptable enterWith(Object obj, Context cx, - Scriptable scope) - { - Scriptable sobj = toObjectOrNull(cx, obj); - if (sobj == null) { - throw typeError1("msg.undef.with", toString(obj)); - } - if (sobj instanceof XMLObject) { - XMLObject xmlObject = (XMLObject)sobj; - return xmlObject.enterWith(scope); - } - return new NativeWith(scope, sobj); - } - - public static Scriptable leaveWith(Scriptable scope) - { - NativeWith nw = (NativeWith)scope; - return nw.getParentScope(); - } - - public static Scriptable enterDotQuery(Object value, Scriptable scope) - { - if (!(value instanceof XMLObject)) { - throw notXmlError(value); - } - XMLObject object = (XMLObject)value; - return object.enterDotQuery(scope); - } - - public static Object updateDotQuery(boolean value, Scriptable scope) - { - // Return null to continue looping - NativeWith nw = (NativeWith)scope; - return nw.updateDotQuery(value); - } - - public static Scriptable leaveDotQuery(Scriptable scope) - { - NativeWith nw = (NativeWith)scope; - return nw.getParentScope(); - } - - public static void setFunctionProtoAndParent(BaseFunction fn, - Scriptable scope) - { - fn.setParentScope(scope); - fn.setPrototype(ScriptableObject.getFunctionPrototype(scope)); - } - - public static void setObjectProtoAndParent(ScriptableObject object, - Scriptable scope) - { - // Compared with function it always sets the scope to top scope - scope = ScriptableObject.getVeryTopLevelScope(scope); // APPJET - object.setParentScope(scope); - Scriptable proto - = ScriptableObject.getClassPrototype(scope, object.getClassName()); - object.setPrototype(proto); - } - - public static void initFunction(Context cx, Scriptable scope, - NativeFunction function, int type, - boolean fromEvalCode) - { - if (type == FunctionNode.FUNCTION_STATEMENT) { - String name = function.getFunctionName(); - if (name != null && name.length() != 0) { - if (!fromEvalCode) { - // ECMA specifies that functions defined in global and - // function scope outside eval should have DONTDELETE set. - ScriptableObject.defineProperty - (scope, name, function, ScriptableObject.PERMANENT); - } else { - scope.put(name, scope, function); - } - } - } else if (type == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) { - String name = function.getFunctionName(); - if (name != null && name.length() != 0) { - // Always put function expression statements into initial - // activation object ignoring the with statement to follow - // SpiderMonkey - while (scope instanceof NativeWith) { - scope = scope.getParentScope(); - } - scope.put(name, scope, function); - } - } else { - throw Kit.codeBug(); - } - } - - public static Scriptable newArrayLiteral(Object[] objects, - int[] skipIndices, - Context cx, Scriptable scope) - { - final int SKIP_DENSITY = 2; - int count = objects.length; - int skipCount = 0; - if (skipIndices != null) { - skipCount = skipIndices.length; - } - int length = count + skipCount; - if (length > 1 && skipCount * SKIP_DENSITY < length) { - // If not too sparse, create whole array for constructor - Object[] sparse; - if (skipCount == 0) { - sparse = objects; - } else { - sparse = new Object[length]; - int skip = 0; - for (int i = 0, j = 0; i != length; ++i) { - if (skip != skipCount && skipIndices[skip] == i) { - sparse[i] = Scriptable.NOT_FOUND; - ++skip; - continue; - } - sparse[i] = objects[j]; - ++j; - } - } - return cx.newObject(scope, "Array", sparse); - } - - Scriptable arrayObj = cx.newObject(scope, "Array", - ScriptRuntime.emptyArgs); - int skip = 0; - for (int i = 0, j = 0; i != length; ++i) { - if (skip != skipCount && skipIndices[skip] == i) { - ++skip; - continue; - } - ScriptableObject.putProperty(arrayObj, i, objects[j]); - ++j; - } - return arrayObj; - } - - /** - * This method is here for backward compat with existing compiled code. It - * is called when an object literal is compiled. The next instance will be - * the version called from new code. - * @deprecated This method only present for compatibility. - */ - public static Scriptable newObjectLiteral(Object[] propertyIds, - Object[] propertyValues, - Context cx, Scriptable scope) - { - // This will initialize to all zeros, exactly what we need for old-style - // getterSetters values (no getters or setters in the list) - int [] getterSetters = new int[propertyIds.length]; - return newObjectLiteral(propertyIds, propertyValues, getterSetters, - cx, scope); - } - - public static Scriptable newObjectLiteral(Object[] propertyIds, - Object[] propertyValues, - int [] getterSetters, - Context cx, Scriptable scope) - { - Scriptable object = cx.newObject(scope); - for (int i = 0, end = propertyIds.length; i != end; ++i) { - Object id = propertyIds[i]; - int getterSetter = getterSetters[i]; - Object value = propertyValues[i]; - if (id instanceof String) { - if (getterSetter == 0) - ScriptableObject.putProperty(object, (String)id, value); - else { - Callable fun; - String definer; - if (getterSetter < 0) // < 0 means get foo() ... - definer = "__defineGetter__"; - else - definer = "__defineSetter__"; - fun = getPropFunctionAndThis(object, definer, cx); - // Must consume the last scriptable object in cx - lastStoredScriptable(cx); - Object[] outArgs = new Object[2]; - outArgs[0] = id; - outArgs[1] = value; - fun.call(cx, scope, object, outArgs); - } - } else { - int index = ((Integer)id).intValue(); - ScriptableObject.putProperty(object, index, value); - } - } - return object; - } - - public static boolean isArrayObject(Object obj) - { - return obj instanceof NativeArray || obj instanceof Arguments; - } - - public static Object[] getArrayElements(Scriptable object) - { - Context cx = Context.getContext(); - long longLen = NativeArray.getLengthProperty(cx, object); - if (longLen > Integer.MAX_VALUE) { - // arrays beyond MAX_INT is not in Java in any case - throw new IllegalArgumentException(); - } - int len = (int) longLen; - if (len == 0) { - return ScriptRuntime.emptyArgs; - } else { - Object[] result = new Object[len]; - for (int i=0; i < len; i++) { - Object elem = ScriptableObject.getProperty(object, i); - result[i] = (elem == Scriptable.NOT_FOUND) ? Undefined.instance - : elem; - } - return result; - } - } - - static void checkDeprecated(Context cx, String name) { - int version = cx.getLanguageVersion(); - if (version >= Context.VERSION_1_4 || version == Context.VERSION_DEFAULT) { - String msg = getMessage1("msg.deprec.ctor", name); - if (version == Context.VERSION_DEFAULT) - Context.reportWarning(msg); - else - throw Context.reportRuntimeError(msg); - } - } - - public static String getMessage0(String messageId) - { - return getMessage(messageId, null); - } - - public static String getMessage1(String messageId, Object arg1) - { - Object[] arguments = {arg1}; - return getMessage(messageId, arguments); - } - - public static String getMessage2( - String messageId, Object arg1, Object arg2) - { - Object[] arguments = {arg1, arg2}; - return getMessage(messageId, arguments); - } - - public static String getMessage3( - String messageId, Object arg1, Object arg2, Object arg3) - { - Object[] arguments = {arg1, arg2, arg3}; - return getMessage(messageId, arguments); - } - - public static String getMessage4( - String messageId, Object arg1, Object arg2, Object arg3, Object arg4) - { - Object[] arguments = {arg1, arg2, arg3, arg4}; - return getMessage(messageId, arguments); - } - - /* OPT there's a noticable delay for the first error! Maybe it'd - * make sense to use a ListResourceBundle instead of a properties - * file to avoid (synchronized) text parsing. - */ - public static String getMessage(String messageId, Object[] arguments) - { - final String defaultResource - = "org.mozilla.javascript.resources.Messages"; - - Context cx = Context.getCurrentContext(); - Locale locale = cx != null ? cx.getLocale() : Locale.getDefault(); - - // ResourceBundle does cacheing. - ResourceBundle rb = ResourceBundle.getBundle(defaultResource, locale); - - String formatString; - try { - formatString = rb.getString(messageId); - } catch (java.util.MissingResourceException mre) { - throw new RuntimeException - ("no message resource found for message property "+ messageId); - } - - /* - * It's OK to format the string, even if 'arguments' is null; - * we need to format it anyway, to make double ''s collapse to - * single 's. - */ - MessageFormat formatter = new MessageFormat(formatString); - return formatter.format(arguments); - } - - public static EcmaError constructError(String error, String message) - { - int[] linep = new int[1]; - String filename = Context.getSourcePositionFromStack(linep); - return constructError(error, message, filename, linep[0], null, 0); - } - - public static EcmaError constructError(String error, - String message, - int lineNumberDelta) - { - int[] linep = new int[1]; - String filename = Context.getSourcePositionFromStack(linep); - if (linep[0] != 0) { - linep[0] += lineNumberDelta; - } - return constructError(error, message, filename, linep[0], null, 0); - } - - public static EcmaError constructError(String error, - String message, - String sourceName, - int lineNumber, - String lineSource, - int columnNumber) - { - return new EcmaError(error, message, sourceName, - lineNumber, lineSource, columnNumber); - } - - public static EcmaError typeError(String message) - { - return constructError("TypeError", message); - } - - public static EcmaError typeError0(String messageId) - { - String msg = getMessage0(messageId); - return typeError(msg); - } - - public static EcmaError typeError1(String messageId, String arg1) - { - String msg = getMessage1(messageId, arg1); - return typeError(msg); - } - - public static EcmaError typeError2(String messageId, String arg1, - String arg2) - { - String msg = getMessage2(messageId, arg1, arg2); - return typeError(msg); - } - - public static EcmaError typeError3(String messageId, String arg1, - String arg2, String arg3) - { - String msg = getMessage3(messageId, arg1, arg2, arg3); - return typeError(msg); - } - - public static RuntimeException undefReadError(Object object, Object id) - { - String idStr = (id == null) ? "null" : id.toString(); - return typeError2("msg.undef.prop.read", toString(object), idStr); - } - - public static RuntimeException undefCallError(Object object, Object id) - { - String idStr = (id == null) ? "null" : id.toString(); - return typeError2("msg.undef.method.call", toString(object), idStr); - } - - public static RuntimeException undefWriteError(Object object, - Object id, - Object value) - { - String idStr = (id == null) ? "null" : id.toString(); - String valueStr = (value instanceof Scriptable) - ? value.toString() : toString(value); - return typeError3("msg.undef.prop.write", toString(object), idStr, - valueStr); - } - - public static RuntimeException notFoundError(Scriptable object, - String property) - { - // XXX: use object to improve the error message - String msg = getMessage1("msg.is.not.defined", property); - throw constructError("ReferenceError", msg); - } - - public static RuntimeException notFunctionError(Object value) - { - return notFunctionError(value, value); - } - - public static RuntimeException notFunctionError(Object value, - Object messageHelper) - { - // Use value for better error reporting - String msg = (messageHelper == null) - ? "null" : messageHelper.toString(); - if (value == Scriptable.NOT_FOUND) { - return typeError1("msg.function.not.found", msg); - } - return typeError2("msg.isnt.function", msg, typeof(value)); - } - - public static RuntimeException notFunctionError(Object obj, Object value, - String propertyName) - { - // Use obj and value for better error reporting - String objString = toString(obj); - if (value == Scriptable.NOT_FOUND) { - return typeError2("msg.function.not.found.in", propertyName, - objString); - } - return typeError3("msg.isnt.function.in", propertyName, objString, - typeof(value)); - } - - private static RuntimeException notXmlError(Object value) - { - throw typeError1("msg.isnt.xml.object", toString(value)); - } - - private static void warnAboutNonJSObject(Object nonJSObject) - { - String message = -"RHINO USAGE WARNING: Missed Context.javaToJS() conversion:\n" -+"Rhino runtime detected object "+nonJSObject+" of class "+nonJSObject.getClass().getName()+" where it expected String, Number, Boolean or Scriptable instance. Please check your code for missing Context.javaToJS() call."; - Context.reportWarning(message); - // Just to be sure that it would be noticed - System.err.println(message); - } - - public static RegExpProxy getRegExpProxy(Context cx) - { - return cx.getRegExpProxy(); - } - - public static void setRegExpProxy(Context cx, RegExpProxy proxy) - { - if (proxy == null) throw new IllegalArgumentException(); - cx.regExpProxy = proxy; - } - - public static RegExpProxy checkRegExpProxy(Context cx) - { - RegExpProxy result = getRegExpProxy(cx); - if (result == null) { - throw Context.reportRuntimeError0("msg.no.regexp"); - } - return result; - } - - private static XMLLib currentXMLLib(Context cx) - { - // Scripts should be running to access this - if (cx.topCallScope == null) - throw new IllegalStateException(); - - XMLLib xmlLib = cx.cachedXMLLib; - if (xmlLib == null) { - xmlLib = XMLLib.extractFromScope(cx.topCallScope); - if (xmlLib == null) - throw new IllegalStateException(); - cx.cachedXMLLib = xmlLib; - } - - return xmlLib; - } - - /** - * Escapes the reserved characters in a value of an attribute - * - * @param value Unescaped text - * @return The escaped text - */ - public static String escapeAttributeValue(Object value, Context cx) - { - XMLLib xmlLib = currentXMLLib(cx); - return xmlLib.escapeAttributeValue(value); - } - - /** - * Escapes the reserved characters in a value of a text node - * - * @param value Unescaped text - * @return The escaped text - */ - public static String escapeTextValue(Object value, Context cx) - { - XMLLib xmlLib = currentXMLLib(cx); - return xmlLib.escapeTextValue(value); - } - - public static Ref memberRef(Object obj, Object elem, - Context cx, int memberTypeFlags) - { - if (!(obj instanceof XMLObject)) { - throw notXmlError(obj); - } - XMLObject xmlObject = (XMLObject)obj; - return xmlObject.memberRef(cx, elem, memberTypeFlags); - } - - public static Ref memberRef(Object obj, Object namespace, Object elem, - Context cx, int memberTypeFlags) - { - if (!(obj instanceof XMLObject)) { - throw notXmlError(obj); - } - XMLObject xmlObject = (XMLObject)obj; - return xmlObject.memberRef(cx, namespace, elem, memberTypeFlags); - } - - public static Ref nameRef(Object name, Context cx, - Scriptable scope, int memberTypeFlags) - { - XMLLib xmlLib = currentXMLLib(cx); - return xmlLib.nameRef(cx, name, scope, memberTypeFlags); - } - - public static Ref nameRef(Object namespace, Object name, Context cx, - Scriptable scope, int memberTypeFlags) - { - XMLLib xmlLib = currentXMLLib(cx); - return xmlLib.nameRef(cx, namespace, name, scope, memberTypeFlags); - } - - private static void storeIndexResult(Context cx, int index) - { - cx.scratchIndex = index; - } - - static int lastIndexResult(Context cx) - { - return cx.scratchIndex; - } - - public static void storeUint32Result(Context cx, long value) - { - if ((value >>> 32) != 0) - throw new IllegalArgumentException(); - cx.scratchUint32 = value; - } - - public static long lastUint32Result(Context cx) - { - long value = cx.scratchUint32; - if ((value >>> 32) != 0) - throw new IllegalStateException(); - return value; - } - - private static void storeScriptable(Context cx, Scriptable value) - { - // The previosly stored scratchScriptable should be consumed - if (cx.scratchScriptable != null) - throw new IllegalStateException(); - cx.scratchScriptable = value; - } - - public static Scriptable lastStoredScriptable(Context cx) - { - Scriptable result = cx.scratchScriptable; - cx.scratchScriptable = null; - return result; - } - - static String makeUrlForGeneratedScript - (boolean isEval, String masterScriptUrl, int masterScriptLine) - { - if (isEval) { - return masterScriptUrl+'#'+masterScriptLine+"(eval)"; - } else { - return masterScriptUrl+'#'+masterScriptLine+"(Function)"; - } - } - - static boolean isGeneratedScript(String sourceUrl) { - // ALERT: this may clash with a valid URL containing (eval) or - // (Function) - return sourceUrl.indexOf("(eval)") >= 0 - || sourceUrl.indexOf("(Function)") >= 0; - } - - private static RuntimeException errorWithClassName(String msg, Object val) - { - return Context.reportRuntimeError1(msg, val.getClass().getName()); - } - - public static final Object[] emptyArgs = new Object[0]; - public static final String[] emptyStrings = new String[0]; - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Scriptable.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Scriptable.java deleted file mode 100644 index 74e5ba7..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Scriptable.java +++ /dev/null @@ -1,342 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * This is interface that all objects in JavaScript must implement. - * The interface provides for the management of properties and for - * performing conversions. - * <p> - * Host system implementors may find it easier to extend the ScriptableObject - * class rather than implementing Scriptable when writing host objects. - * <p> - * There are many static methods defined in ScriptableObject that perform - * the multiple calls to the Scriptable interface needed in order to - * manipulate properties in prototype chains. - * <p> - * - * @see org.mozilla.javascript.ScriptableObject - * @author Norris Boyd - * @author Nick Thompson - * @author Brendan Eich - */ - -public interface Scriptable { - - /** - * Get the name of the set of objects implemented by this Java class. - * This corresponds to the [[Class]] operation in ECMA and is used - * by Object.prototype.toString() in ECMA.<p> - * See ECMA 8.6.2 and 15.2.4.2. - */ - public String getClassName(); - - /** - * Value returned from <code>get</code> if the property is not - * found. - */ - public static final Object NOT_FOUND = UniqueTag.NOT_FOUND; - - /** - * Get a named property from the object. - * - * Looks property up in this object and returns the associated value - * if found. Returns NOT_FOUND if not found. - * Note that this method is not expected to traverse the prototype - * chain. This is different from the ECMA [[Get]] operation. - * - * Depending on the property selector, the runtime will call - * this method or the form of <code>get</code> that takes an - * integer: - * <table> - * <tr><th>JavaScript code</th><th>Java code</th></tr> - * <tr><td>a.b </td><td>a.get("b", a)</td></tr> - * <tr><td>a["foo"] </td><td>a.get("foo", a)</td></tr> - * <tr><td>a[3] </td><td>a.get(3, a)</td></tr> - * <tr><td>a["3"] </td><td>a.get(3, a)</td></tr> - * <tr><td>a[3.0] </td><td>a.get(3, a)</td></tr> - * <tr><td>a["3.0"] </td><td>a.get("3.0", a)</td></tr> - * <tr><td>a[1.1] </td><td>a.get("1.1", a)</td></tr> - * <tr><td>a[-4] </td><td>a.get(-4, a)</td></tr> - * </table> - * <p> - * The values that may be returned are limited to the following: - * <UL> - * <LI>java.lang.Boolean objects</LI> - * <LI>java.lang.String objects</LI> - * <LI>java.lang.Number objects</LI> - * <LI>org.mozilla.javascript.Scriptable objects</LI> - * <LI>null</LI> - * <LI>The value returned by Context.getUndefinedValue()</LI> - * <LI>NOT_FOUND</LI> - * </UL> - * @param name the name of the property - * @param start the object in which the lookup began - * @return the value of the property (may be null), or NOT_FOUND - * @see org.mozilla.javascript.Context#getUndefinedValue - */ - public Object get(String name, Scriptable start); - - /** - * Get a property from the object selected by an integral index. - * - * Identical to <code>get(String, Scriptable)</code> except that - * an integral index is used to select the property. - * - * @param index the numeric index for the property - * @param start the object in which the lookup began - * @return the value of the property (may be null), or NOT_FOUND - * @see org.mozilla.javascript.Scriptable#get(String,Scriptable) - */ - public Object get(int index, Scriptable start); - - /** - * Indicates whether or not a named property is defined in an object. - * - * Does not traverse the prototype chain.<p> - * - * The property is specified by a String name - * as defined for the <code>get</code> method.<p> - * - * @param name the name of the property - * @param start the object in which the lookup began - * @return true if and only if the named property is found in the object - * @see org.mozilla.javascript.Scriptable#get(String, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#getProperty(Scriptable, String) - */ - public boolean has(String name, Scriptable start); - - /** - * Indicates whether or not an indexed property is defined in an object. - * - * Does not traverse the prototype chain.<p> - * - * The property is specified by an integral index - * as defined for the <code>get</code> method.<p> - * - * @param index the numeric index for the property - * @param start the object in which the lookup began - * @return true if and only if the indexed property is found in the object - * @see org.mozilla.javascript.Scriptable#get(int, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#getProperty(Scriptable, int) - */ - public boolean has(int index, Scriptable start); - - /** - * Sets a named property in this object. - * <p> - * The property is specified by a string name - * as defined for <code>get</code>. - * <p> - * The possible values that may be passed in are as defined for - * <code>get</code>. A class that implements this method may choose - * to ignore calls to set certain properties, in which case those - * properties are effectively read-only.<p> - * For properties defined in a prototype chain, - * use <code>putProperty</code> in ScriptableObject. <p> - * Note that if a property <i>a</i> is defined in the prototype <i>p</i> - * of an object <i>o</i>, then evaluating <code>o.a = 23</code> will cause - * <code>set</code> to be called on the prototype <i>p</i> with - * <i>o</i> as the <i>start</i> parameter. - * To preserve JavaScript semantics, it is the Scriptable - * object's responsibility to modify <i>o</i>. <p> - * This design allows properties to be defined in prototypes and implemented - * in terms of getters and setters of Java values without consuming slots - * in each instance.<p> - * <p> - * The values that may be set are limited to the following: - * <UL> - * <LI>java.lang.Boolean objects</LI> - * <LI>java.lang.String objects</LI> - * <LI>java.lang.Number objects</LI> - * <LI>org.mozilla.javascript.Scriptable objects</LI> - * <LI>null</LI> - * <LI>The value returned by Context.getUndefinedValue()</LI> - * </UL><p> - * Arbitrary Java objects may be wrapped in a Scriptable by first calling - * <code>Context.toObject</code>. This allows the property of a JavaScript - * object to contain an arbitrary Java object as a value.<p> - * Note that <code>has</code> will be called by the runtime first before - * <code>set</code> is called to determine in which object the - * property is defined. - * Note that this method is not expected to traverse the prototype chain, - * which is different from the ECMA [[Put]] operation. - * @param name the name of the property - * @param start the object whose property is being set - * @param value value to set the property to - * @see org.mozilla.javascript.Scriptable#has(String, Scriptable) - * @see org.mozilla.javascript.Scriptable#get(String, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#putProperty(Scriptable, String, Object) - * @see org.mozilla.javascript.Context#toObject(Object, Scriptable) - */ - public void put(String name, Scriptable start, Object value); - - /** - * Sets an indexed property in this object. - * <p> - * The property is specified by an integral index - * as defined for <code>get</code>.<p> - * - * Identical to <code>put(String, Scriptable, Object)</code> except that - * an integral index is used to select the property. - * - * @param index the numeric index for the property - * @param start the object whose property is being set - * @param value value to set the property to - * @see org.mozilla.javascript.Scriptable#has(int, Scriptable) - * @see org.mozilla.javascript.Scriptable#get(int, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#putProperty(Scriptable, int, Object) - * @see org.mozilla.javascript.Context#toObject(Object, Scriptable) - */ - public void put(int index, Scriptable start, Object value); - - /** - * Removes a property from this object. - * This operation corresponds to the ECMA [[Delete]] except that - * the no result is returned. The runtime will guarantee that this - * method is called only if the property exists. After this method - * is called, the runtime will call Scriptable.has to see if the - * property has been removed in order to determine the boolean - * result of the delete operator as defined by ECMA 11.4.1. - * <p> - * A property can be made permanent by ignoring calls to remove - * it.<p> - * The property is specified by a String name - * as defined for <code>get</code>. - * <p> - * To delete properties defined in a prototype chain, - * see deleteProperty in ScriptableObject. - * @param name the identifier for the property - * @see org.mozilla.javascript.Scriptable#get(String, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#deleteProperty(Scriptable, String) - */ - public void delete(String name); - - /** - * Removes a property from this object. - * - * The property is specified by an integral index - * as defined for <code>get</code>. - * <p> - * To delete properties defined in a prototype chain, - * see deleteProperty in ScriptableObject. - * - * Identical to <code>delete(String)</code> except that - * an integral index is used to select the property. - * - * @param index the numeric index for the property - * @see org.mozilla.javascript.Scriptable#get(int, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#deleteProperty(Scriptable, int) - */ - public void delete(int index); - - /** - * Get the prototype of the object. - * @return the prototype - */ - public Scriptable getPrototype(); - - /** - * Set the prototype of the object. - * @param prototype the prototype to set - */ - public void setPrototype(Scriptable prototype); - - /** - * Get the parent scope of the object. - * @return the parent scope - */ - public Scriptable getParentScope(); - - /** - * Set the parent scope of the object. - * @param parent the parent scope to set - */ - public void setParentScope(Scriptable parent); - - /** - * Get an array of property ids. - * - * Not all property ids need be returned. Those properties - * whose ids are not returned are considered non-enumerable. - * - * @return an array of Objects. Each entry in the array is either - * a java.lang.String or a java.lang.Number - */ - public Object[] getIds(); - - /** - * Get the default value of the object with a given hint. - * The hints are String.class for type String, Number.class for type - * Number, Scriptable.class for type Object, and Boolean.class for - * type Boolean. <p> - * - * A <code>hint</code> of null means "no hint". - * - * See ECMA 8.6.2.6. - * - * @param hint the type hint - * @return the default value - */ - public Object getDefaultValue(Class hint); - - /** - * The instanceof operator. - * - * <p> - * The JavaScript code "lhs instanceof rhs" causes rhs.hasInstance(lhs) to - * be called. - * - * <p> - * The return value is implementation dependent so that embedded host objects can - * return an appropriate value. See the JS 1.3 language documentation for more - * detail. - * - * <p>This operator corresponds to the proposed EMCA [[HasInstance]] operator. - * - * @param instance The value that appeared on the LHS of the instanceof - * operator - * - * @return an implementation dependent value - */ - public boolean hasInstance(Scriptable instance); -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptableObject.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptableObject.java deleted file mode 100644 index 53de1fc..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ScriptableObject.java +++ /dev/null @@ -1,2428 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Bob Jervis - * Roger Lawrence - * Steve Weiss - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -import java.lang.reflect.*; -import java.util.Hashtable; -import java.io.*; -import org.mozilla.javascript.debug.DebuggableObject; - -/** - * This is the default implementation of the Scriptable interface. This - * class provides convenient default behavior that makes it easier to - * define host objects. - * <p> - * Various properties and methods of JavaScript objects can be conveniently - * defined using methods of ScriptableObject. - * <p> - * Classes extending ScriptableObject must define the getClassName method. - * - * @see org.mozilla.javascript.Scriptable - * @author Norris Boyd - */ - -public abstract class ScriptableObject implements Scriptable, Serializable, - DebuggableObject, - ConstProperties -{ - - /** - * The empty property attribute. - * - * Used by getAttributes() and setAttributes(). - * - * @see org.mozilla.javascript.ScriptableObject#getAttributes(String) - * @see org.mozilla.javascript.ScriptableObject#setAttributes(String, int) - */ - public static final int EMPTY = 0x00; - - /** - * Property attribute indicating assignment to this property is ignored. - * - * @see org.mozilla.javascript.ScriptableObject - * #put(String, Scriptable, Object) - * @see org.mozilla.javascript.ScriptableObject#getAttributes(String) - * @see org.mozilla.javascript.ScriptableObject#setAttributes(String, int) - */ - public static final int READONLY = 0x01; - - /** - * Property attribute indicating property is not enumerated. - * - * Only enumerated properties will be returned by getIds(). - * - * @see org.mozilla.javascript.ScriptableObject#getIds() - * @see org.mozilla.javascript.ScriptableObject#getAttributes(String) - * @see org.mozilla.javascript.ScriptableObject#setAttributes(String, int) - */ - public static final int DONTENUM = 0x02; - - /** - * Property attribute indicating property cannot be deleted. - * - * @see org.mozilla.javascript.ScriptableObject#delete(String) - * @see org.mozilla.javascript.ScriptableObject#getAttributes(String) - * @see org.mozilla.javascript.ScriptableObject#setAttributes(String, int) - */ - public static final int PERMANENT = 0x04; - - /** - * Property attribute indicating that this is a const property that has not - * been assigned yet. The first 'const' assignment to the property will - * clear this bit. - */ - public static final int UNINITIALIZED_CONST = 0x08; - - public static final int CONST = PERMANENT|READONLY|UNINITIALIZED_CONST; - /** - * The prototype of this object. - */ - private Scriptable prototypeObject; - - /** - * The parent scope of this object. - */ - private Scriptable parentScopeObject; - - private static final Slot REMOVED = new Slot(null, 0, READONLY); - - static { - REMOVED.wasDeleted = 1; - } - - private transient Slot[] slots; - // If count >= 0, it gives number of keys or if count < 0, - // it indicates sealed object where ~count gives number of keys - private int count; - - // cache; may be removed for smaller memory footprint - private transient Slot lastAccess = REMOVED; - - // associated values are not serialized - private transient volatile Hashtable associatedValues; - - private static final int SLOT_QUERY = 1; - private static final int SLOT_MODIFY = 2; - private static final int SLOT_REMOVE = 3; - private static final int SLOT_MODIFY_GETTER_SETTER = 4; - private static final int SLOT_MODIFY_CONST = 5; - - private static class Slot implements Serializable - { - static final long serialVersionUID = -3539051633409902634L; - - String name; // This can change due to caching - int indexOrHash; - private volatile short attributes; - transient volatile byte wasDeleted; - volatile Object value; - transient volatile Slot next; - - Slot(String name, int indexOrHash, int attributes) - { - this.name = name; - this.indexOrHash = indexOrHash; - this.attributes = (short)attributes; - } - - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - if (name != null) { - indexOrHash = name.hashCode(); - } - } - - final int getAttributes() - { - return attributes; - } - - final synchronized void setAttributes(int value) - { - checkValidAttributes(value); - attributes = (short)value; - } - - final void checkNotReadonly() - { - if ((attributes & READONLY) != 0) { - String str = (name != null ? name - : Integer.toString(indexOrHash)); - throw Context.reportRuntimeError1("msg.modify.readonly", str); - } - } - - } - - private static final class GetterSlot extends Slot - { - static final long serialVersionUID = -4900574849788797588L; - - Object getter; - Object setter; - - GetterSlot(String name, int indexOrHash, int attributes) - { - super(name, indexOrHash, attributes); - } - } - - static void checkValidAttributes(int attributes) - { - final int mask = READONLY | DONTENUM | PERMANENT | UNINITIALIZED_CONST; - if ((attributes & ~mask) != 0) { - throw new IllegalArgumentException(String.valueOf(attributes)); - } - } - - public ScriptableObject() - { - } - - public ScriptableObject(Scriptable scope, Scriptable prototype) - { - if (scope == null) - throw new IllegalArgumentException(); - - parentScopeObject = scope; - prototypeObject = prototype; - } - - /** - * Return the name of the class. - * - * This is typically the same name as the constructor. - * Classes extending ScriptableObject must implement this abstract - * method. - */ - public abstract String getClassName(); - - /** - * Returns true if the named property is defined. - * - * @param name the name of the property - * @param start the object in which the lookup began - * @return true if and only if the property was found in the object - */ - public boolean has(String name, Scriptable start) - { - return null != getSlot(name, 0, SLOT_QUERY); - } - - /** - * Returns true if the property index is defined. - * - * @param index the numeric index for the property - * @param start the object in which the lookup began - * @return true if and only if the property was found in the object - */ - public boolean has(int index, Scriptable start) - { - return null != getSlot(null, index, SLOT_QUERY); - } - - /** - * Returns the value of the named property or NOT_FOUND. - * - * If the property was created using defineProperty, the - * appropriate getter method is called. - * - * @param name the name of the property - * @param start the object in which the lookup began - * @return the value of the property (may be null), or NOT_FOUND - */ - public Object get(String name, Scriptable start) - { - return getImpl(name, 0, start); - } - - /** - * Returns the value of the indexed property or NOT_FOUND. - * - * @param index the numeric index for the property - * @param start the object in which the lookup began - * @return the value of the property (may be null), or NOT_FOUND - */ - public Object get(int index, Scriptable start) - { - return getImpl(null, index, start); - } - - /** - * Sets the value of the named property, creating it if need be. - * - * If the property was created using defineProperty, the - * appropriate setter method is called. <p> - * - * If the property's attributes include READONLY, no action is - * taken. - * This method will actually set the property in the start - * object. - * - * @param name the name of the property - * @param start the object whose property is being set - * @param value value to set the property to - */ - public void put(String name, Scriptable start, Object value) - { - if (putImpl(name, 0, start, value, EMPTY)) - return; - - if (start == this) throw Kit.codeBug(); - start.put(name, start, value); - } - - /** - * Sets the value of the indexed property, creating it if need be. - * - * @param index the numeric index for the property - * @param start the object whose property is being set - * @param value value to set the property to - */ - public void put(int index, Scriptable start, Object value) - { - if (putImpl(null, index, start, value, EMPTY)) - return; - - if (start == this) throw Kit.codeBug(); - start.put(index, start, value); - } - - /** - * Removes a named property from the object. - * - * If the property is not found, or it has the PERMANENT attribute, - * no action is taken. - * - * @param name the name of the property - */ - public void delete(String name) - { - checkNotSealed(name, 0); - accessSlot(name, 0, SLOT_REMOVE); - } - - /** - * Removes the indexed property from the object. - * - * If the property is not found, or it has the PERMANENT attribute, - * no action is taken. - * - * @param index the numeric index for the property - */ - public void delete(int index) - { - checkNotSealed(null, index); - accessSlot(null, index, SLOT_REMOVE); - } - - /** - * Sets the value of the named const property, creating it if need be. - * - * If the property was created using defineProperty, the - * appropriate setter method is called. <p> - * - * If the property's attributes include READONLY, no action is - * taken. - * This method will actually set the property in the start - * object. - * - * @param name the name of the property - * @param start the object whose property is being set - * @param value value to set the property to - */ - public void putConst(String name, Scriptable start, Object value) - { - if (putImpl(name, 0, start, value, READONLY)) - return; - - if (start == this) throw Kit.codeBug(); - if (start instanceof ConstProperties) - ((ConstProperties)start).putConst(name, start, value); - else - start.put(name, start, value); - } - - public void defineConst(String name, Scriptable start) - { - if (putImpl(name, 0, start, Undefined.instance, UNINITIALIZED_CONST)) - return; - - if (start == this) throw Kit.codeBug(); - if (start instanceof ConstProperties) - ((ConstProperties)start).defineConst(name, start); - } - /** - * Returns true if the named property is defined as a const on this object. - * @param name - * @return true if the named property is defined as a const, false - * otherwise. - */ - public boolean isConst(String name) - { - Slot slot = getSlot(name, 0, SLOT_QUERY); - if (slot == null) { - return false; - } - return (slot.getAttributes() & (PERMANENT|READONLY)) == - (PERMANENT|READONLY); - - } - /** - * @deprecated Use {@link #getAttributes(String name)}. The engine always - * ignored the start argument. - */ - public final int getAttributes(String name, Scriptable start) - { - return getAttributes(name); - } - - /** - * @deprecated Use {@link #getAttributes(int index)}. The engine always - * ignored the start argument. - */ - public final int getAttributes(int index, Scriptable start) - { - return getAttributes(index); - } - - /** - * @deprecated Use {@link #setAttributes(String name, int attributes)}. - * The engine always ignored the start argument. - */ - public final void setAttributes(String name, Scriptable start, - int attributes) - { - setAttributes(name, attributes); - } - - /** - * @deprecated Use {@link #setAttributes(int index, int attributes)}. - * The engine always ignored the start argument. - */ - public void setAttributes(int index, Scriptable start, - int attributes) - { - setAttributes(index, attributes); - } - - /** - * Get the attributes of a named property. - * - * The property is specified by <code>name</code> - * as defined for <code>has</code>.<p> - * - * @param name the identifier for the property - * @return the bitset of attributes - * @exception EvaluatorException if the named property is not found - * @see org.mozilla.javascript.ScriptableObject#has(String, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#READONLY - * @see org.mozilla.javascript.ScriptableObject#DONTENUM - * @see org.mozilla.javascript.ScriptableObject#PERMANENT - * @see org.mozilla.javascript.ScriptableObject#EMPTY - */ - public int getAttributes(String name) - { - return findAttributeSlot(name, 0, SLOT_QUERY).getAttributes(); - } - - /** - * Get the attributes of an indexed property. - * - * @param index the numeric index for the property - * @exception EvaluatorException if the named property is not found - * is not found - * @return the bitset of attributes - * @see org.mozilla.javascript.ScriptableObject#has(String, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#READONLY - * @see org.mozilla.javascript.ScriptableObject#DONTENUM - * @see org.mozilla.javascript.ScriptableObject#PERMANENT - * @see org.mozilla.javascript.ScriptableObject#EMPTY - */ - public int getAttributes(int index) - { - return findAttributeSlot(null, index, SLOT_QUERY).getAttributes(); - } - - /** - * Set the attributes of a named property. - * - * The property is specified by <code>name</code> - * as defined for <code>has</code>.<p> - * - * The possible attributes are READONLY, DONTENUM, - * and PERMANENT. Combinations of attributes - * are expressed by the bitwise OR of attributes. - * EMPTY is the state of no attributes set. Any unused - * bits are reserved for future use. - * - * @param name the name of the property - * @param attributes the bitset of attributes - * @exception EvaluatorException if the named property is not found - * @see org.mozilla.javascript.Scriptable#has(String, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#READONLY - * @see org.mozilla.javascript.ScriptableObject#DONTENUM - * @see org.mozilla.javascript.ScriptableObject#PERMANENT - * @see org.mozilla.javascript.ScriptableObject#EMPTY - */ - public void setAttributes(String name, int attributes) - { - checkNotSealed(name, 0); - findAttributeSlot(name, 0, SLOT_MODIFY).setAttributes(attributes); - } - - /** - * Set the attributes of an indexed property. - * - * @param index the numeric index for the property - * @param attributes the bitset of attributes - * @exception EvaluatorException if the named property is not found - * @see org.mozilla.javascript.Scriptable#has(String, Scriptable) - * @see org.mozilla.javascript.ScriptableObject#READONLY - * @see org.mozilla.javascript.ScriptableObject#DONTENUM - * @see org.mozilla.javascript.ScriptableObject#PERMANENT - * @see org.mozilla.javascript.ScriptableObject#EMPTY - */ - public void setAttributes(int index, int attributes) - { - checkNotSealed(null, index); - findAttributeSlot(null, index, SLOT_MODIFY).setAttributes(attributes); - } - - /** - * XXX: write docs. - */ - public void setGetterOrSetter(String name, int index, - Callable getterOrSeter, boolean isSetter) - { - if (name != null && index != 0) - throw new IllegalArgumentException(name); - - checkNotSealed(name, index); - GetterSlot gslot = (GetterSlot)getSlot(name, index, - SLOT_MODIFY_GETTER_SETTER); - gslot.checkNotReadonly(); - if (isSetter) { - gslot.setter = getterOrSeter; - } else { - gslot.getter = getterOrSeter; - } - gslot.value = Undefined.instance; - } - - /** - * Get the getter or setter for a given property. Used by __lookupGetter__ - * and __lookupSetter__. - * - * @param name Name of the object. If nonnull, index must be 0. - * @param index Index of the object. If nonzero, name must be null. - * @param isSetter If true, return the setter, otherwise return the getter. - * @exception IllegalArgumentException if both name and index are nonnull - * and nonzero respectively. - * @return Null if the property does not exist. Otherwise returns either - * the getter or the setter for the property, depending on - * the value of isSetter (may be undefined if unset). - */ - public Object getGetterOrSetter(String name, int index, boolean isSetter) - { - if (name != null && index != 0) - throw new IllegalArgumentException(name); - Slot slot = getSlot(name, index, SLOT_QUERY); - if (slot == null) - return null; - if (slot instanceof GetterSlot) { - GetterSlot gslot = (GetterSlot)slot; - Object result = isSetter ? gslot.setter : gslot.getter; - return result != null ? result : Undefined.instance; - } else - return Undefined.instance; - } - - /** - * Returns whether a property is a getter or a setter - * @param name property name - * @param index property index - * @param setter true to check for a setter, false for a getter - * @return whether the property is a getter or a setter - */ - protected boolean isGetterOrSetter(String name, int index, boolean setter) { - Slot slot = getSlot(name, index, SLOT_QUERY); - if (slot instanceof GetterSlot) { - if (setter && ((GetterSlot)slot).setter != null) return true; - if (!setter && ((GetterSlot)slot).getter != null) return true; - } - return false; - } - - void addLazilyInitializedValue(String name, int index, - LazilyLoadedCtor init, int attributes) - { - if (name != null && index != 0) - throw new IllegalArgumentException(name); - checkNotSealed(name, index); - GetterSlot gslot = (GetterSlot)getSlot(name, index, - SLOT_MODIFY_GETTER_SETTER); - gslot.setAttributes(attributes); - gslot.getter = null; - gslot.setter = null; - gslot.value = init; - } - - /** - * Returns the prototype of the object. - */ - public Scriptable getPrototype() - { - return prototypeObject; - } - - /** - * Sets the prototype of the object. - */ - public void setPrototype(Scriptable m) - { - prototypeObject = m; - } - - /** - * Returns the parent (enclosing) scope of the object. - */ - public Scriptable getParentScope() - { - return parentScopeObject; - } - - /** - * Sets the parent (enclosing) scope of the object. - */ - public void setParentScope(Scriptable m) - { - parentScopeObject = m; - } - - /** - * Returns an array of ids for the properties of the object. - * - * <p>Any properties with the attribute DONTENUM are not listed. <p> - * - * @return an array of java.lang.Objects with an entry for every - * listed property. Properties accessed via an integer index will - * have a corresponding - * Integer entry in the returned array. Properties accessed by - * a String will have a String entry in the returned array. - */ - public Object[] getIds() { - return getIds(false); - } - - /** - * Returns an array of ids for the properties of the object. - * - * <p>All properties, even those with attribute DONTENUM, are listed. <p> - * - * @return an array of java.lang.Objects with an entry for every - * listed property. Properties accessed via an integer index will - * have a corresponding - * Integer entry in the returned array. Properties accessed by - * a String will have a String entry in the returned array. - */ - public Object[] getAllIds() { - return getIds(true); - } - - /** - * Implements the [[DefaultValue]] internal method. - * - * <p>Note that the toPrimitive conversion is a no-op for - * every type other than Object, for which [[DefaultValue]] - * is called. See ECMA 9.1.<p> - * - * A <code>hint</code> of null means "no hint". - * - * @param typeHint the type hint - * @return the default value for the object - * - * See ECMA 8.6.2.6. - */ - public Object getDefaultValue(Class typeHint) - { - return getDefaultValue(this, typeHint); - } - - public static Object getDefaultValue(Scriptable object, Class typeHint) - { - Context cx = null; - for (int i=0; i < 2; i++) { - boolean tryToString; - if (typeHint == ScriptRuntime.StringClass) { - tryToString = (i == 0); - } else { - tryToString = (i == 1); - } - - String methodName; - Object[] args; - if (tryToString) { - methodName = "toString"; - args = ScriptRuntime.emptyArgs; - } else { - methodName = "valueOf"; - args = new Object[1]; - String hint; - if (typeHint == null) { - hint = "undefined"; - } else if (typeHint == ScriptRuntime.StringClass) { - hint = "string"; - } else if (typeHint == ScriptRuntime.ScriptableClass) { - hint = "object"; - } else if (typeHint == ScriptRuntime.FunctionClass) { - hint = "function"; - } else if (typeHint == ScriptRuntime.BooleanClass - || typeHint == Boolean.TYPE) - { - hint = "boolean"; - } else if (typeHint == ScriptRuntime.NumberClass || - typeHint == ScriptRuntime.ByteClass || - typeHint == Byte.TYPE || - typeHint == ScriptRuntime.ShortClass || - typeHint == Short.TYPE || - typeHint == ScriptRuntime.IntegerClass || - typeHint == Integer.TYPE || - typeHint == ScriptRuntime.FloatClass || - typeHint == Float.TYPE || - typeHint == ScriptRuntime.DoubleClass || - typeHint == Double.TYPE) - { - hint = "number"; - } else { - throw Context.reportRuntimeError1( - "msg.invalid.type", typeHint.toString()); - } - args[0] = hint; - } - Object v = getProperty(object, methodName); - if (!(v instanceof Function)) - continue; - Function fun = (Function) v; - if (cx == null) - cx = Context.getContext(); - v = fun.call(cx, fun.getParentScope(), object, args); - if (v != null) { - if (!(v instanceof Scriptable)) { - return v; - } - if (typeHint == ScriptRuntime.ScriptableClass - || typeHint == ScriptRuntime.FunctionClass) - { - return v; - } - if (tryToString && v instanceof Wrapper) { - // Let a wrapped java.lang.String pass for a primitive - // string. - Object u = ((Wrapper)v).unwrap(); - if (u instanceof String) - return u; - } - } - } - // fall through to error - String arg = (typeHint == null) ? "undefined" : typeHint.getName(); - throw ScriptRuntime.typeError1("msg.default.value", arg); - } - - /** - * Implements the instanceof operator. - * - * <p>This operator has been proposed to ECMA. - * - * @param instance The value that appeared on the LHS of the instanceof - * operator - * @return true if "this" appears in value's prototype chain - * - */ - public boolean hasInstance(Scriptable instance) { - // Default for JS objects (other than Function) is to do prototype - // chasing. This will be overridden in NativeFunction and non-JS - // objects. - - return ScriptRuntime.jsDelegatesTo(instance, this); - } - - /** - * Emulate the SpiderMonkey (and Firefox) feature of allowing - * custom objects to avoid detection by normal "object detection" - * code patterns. This is used to implement document.all. - * See https://bugzilla.mozilla.org/show_bug.cgi?id=412247. - * This is an analog to JOF_DETECTING from SpiderMonkey; see - * https://bugzilla.mozilla.org/show_bug.cgi?id=248549. - * Other than this special case, embeddings should return false. - * @return true if this object should avoid object detection - * @since 1.7R1 - */ - public boolean avoidObjectDetection() { - return false; - } - - /** - * Custom <tt>==</tt> operator. - * Must return {@link Scriptable#NOT_FOUND} if this object does not - * have custom equality operator for the given value, - * <tt>Boolean.TRUE</tt> if this object is equivalent to <tt>value</tt>, - * <tt>Boolean.FALSE</tt> if this object is not equivalent to - * <tt>value</tt>. - * <p> - * The default implementation returns Boolean.TRUE - * if <tt>this == value</tt> or {@link Scriptable#NOT_FOUND} otherwise. - * It indicates that by default custom equality is available only if - * <tt>value</tt> is <tt>this</tt> in which case true is returned. - */ - protected Object equivalentValues(Object value) - { - return (this == value) ? Boolean.TRUE : Scriptable.NOT_FOUND; - } - - /** - * Defines JavaScript objects from a Java class that implements Scriptable. - * - * If the given class has a method - * <pre> - * static void init(Context cx, Scriptable scope, boolean sealed);</pre> - * - * or its compatibility form - * <pre> - * static void init(Scriptable scope);</pre> - * - * then it is invoked and no further initialization is done.<p> - * - * However, if no such a method is found, then the class's constructors and - * methods are used to initialize a class in the following manner.<p> - * - * First, the zero-parameter constructor of the class is called to - * create the prototype. If no such constructor exists, - * a {@link EvaluatorException} is thrown. <p> - * - * Next, all methods are scanned for special prefixes that indicate that they - * have special meaning for defining JavaScript objects. - * These special prefixes are - * <ul> - * <li><code>jsFunction_</code> for a JavaScript function - * <li><code>jsStaticFunction_</code> for a JavaScript function that - * is a property of the constructor - * <li><code>jsGet_</code> for a getter of a JavaScript property - * <li><code>jsSet_</code> for a setter of a JavaScript property - * <li><code>jsConstructor</code> for a JavaScript function that - * is the constructor - * </ul><p> - * - * If the method's name begins with "jsFunction_", a JavaScript function - * is created with a name formed from the rest of the Java method name - * following "jsFunction_". So a Java method named "jsFunction_foo" will - * define a JavaScript method "foo". Calling this JavaScript function - * will cause the Java method to be called. The parameters of the method - * must be of number and types as defined by the FunctionObject class. - * The JavaScript function is then added as a property - * of the prototype. <p> - * - * If the method's name begins with "jsStaticFunction_", it is handled - * similarly except that the resulting JavaScript function is added as a - * property of the constructor object. The Java method must be static. - * - * If the method's name begins with "jsGet_" or "jsSet_", the method is - * considered to define a property. Accesses to the defined property - * will result in calls to these getter and setter methods. If no - * setter is defined, the property is defined as READONLY.<p> - * - * If the method's name is "jsConstructor", the method is - * considered to define the body of the constructor. Only one - * method of this name may be defined. - * If no method is found that can serve as constructor, a Java - * constructor will be selected to serve as the JavaScript - * constructor in the following manner. If the class has only one - * Java constructor, that constructor is used to define - * the JavaScript constructor. If the the class has two constructors, - * one must be the zero-argument constructor (otherwise an - * {@link EvaluatorException} would have already been thrown - * when the prototype was to be created). In this case - * the Java constructor with one or more parameters will be used - * to define the JavaScript constructor. If the class has three - * or more constructors, an {@link EvaluatorException} - * will be thrown.<p> - * - * Finally, if there is a method - * <pre> - * static void finishInit(Scriptable scope, FunctionObject constructor, - * Scriptable prototype)</pre> - * - * it will be called to finish any initialization. The <code>scope</code> - * argument will be passed, along with the newly created constructor and - * the newly created prototype.<p> - * - * @param scope The scope in which to define the constructor. - * @param clazz The Java class to use to define the JavaScript objects - * and properties. - * @exception IllegalAccessException if access is not available - * to a reflected class member - * @exception InstantiationException if unable to instantiate - * the named class - * @exception InvocationTargetException if an exception is thrown - * during execution of methods of the named class - * @see org.mozilla.javascript.Function - * @see org.mozilla.javascript.FunctionObject - * @see org.mozilla.javascript.ScriptableObject#READONLY - * @see org.mozilla.javascript.ScriptableObject - * #defineProperty(String, Class, int) - */ - public static void defineClass(Scriptable scope, Class clazz) - throws IllegalAccessException, InstantiationException, - InvocationTargetException - { - defineClass(scope, clazz, false, false); - } - - /** - * Defines JavaScript objects from a Java class, optionally - * allowing sealing. - * - * Similar to <code>defineClass(Scriptable scope, Class clazz)</code> - * except that sealing is allowed. An object that is sealed cannot have - * properties added or removed. Note that sealing is not allowed in - * the current ECMA/ISO language specification, but is likely for - * the next version. - * - * @param scope The scope in which to define the constructor. - * @param clazz The Java class to use to define the JavaScript objects - * and properties. The class must implement Scriptable. - * @param sealed Whether or not to create sealed standard objects that - * cannot be modified. - * @exception IllegalAccessException if access is not available - * to a reflected class member - * @exception InstantiationException if unable to instantiate - * the named class - * @exception InvocationTargetException if an exception is thrown - * during execution of methods of the named class - * @since 1.4R3 - */ - public static void defineClass(Scriptable scope, Class clazz, - boolean sealed) - throws IllegalAccessException, InstantiationException, - InvocationTargetException - { - defineClass(scope, clazz, sealed, false); - } - - /** - * Defines JavaScript objects from a Java class, optionally - * allowing sealing and mapping of Java inheritance to JavaScript - * prototype-based inheritance. - * - * Similar to <code>defineClass(Scriptable scope, Class clazz)</code> - * except that sealing and inheritance mapping are allowed. An object - * that is sealed cannot have properties added or removed. Note that - * sealing is not allowed in the current ECMA/ISO language specification, - * but is likely for the next version. - * - * @param scope The scope in which to define the constructor. - * @param clazz The Java class to use to define the JavaScript objects - * and properties. The class must implement Scriptable. - * @param sealed Whether or not to create sealed standard objects that - * cannot be modified. - * @param mapInheritance Whether or not to map Java inheritance to - * JavaScript prototype-based inheritance. - * @return the class name for the prototype of the specified class - * @exception IllegalAccessException if access is not available - * to a reflected class member - * @exception InstantiationException if unable to instantiate - * the named class - * @exception InvocationTargetException if an exception is thrown - * during execution of methods of the named class - * @since 1.6R2 - */ - public static String defineClass(Scriptable scope, Class clazz, - boolean sealed, boolean mapInheritance) - throws IllegalAccessException, InstantiationException, - InvocationTargetException - { - BaseFunction ctor = buildClassCtor(scope, clazz, sealed, - mapInheritance); - if (ctor == null) - return null; - String name = ctor.getClassPrototype().getClassName(); - defineProperty(scope, name, ctor, ScriptableObject.DONTENUM); - return name; - } - - static BaseFunction buildClassCtor(Scriptable scope, Class clazz, - boolean sealed, - boolean mapInheritance) - throws IllegalAccessException, InstantiationException, - InvocationTargetException - { - Method[] methods = FunctionObject.getMethodList(clazz); - for (int i=0; i < methods.length; i++) { - Method method = methods[i]; - if (!method.getName().equals("init")) - continue; - Class[] parmTypes = method.getParameterTypes(); - if (parmTypes.length == 3 && - parmTypes[0] == ScriptRuntime.ContextClass && - parmTypes[1] == ScriptRuntime.ScriptableClass && - parmTypes[2] == Boolean.TYPE && - Modifier.isStatic(method.getModifiers())) - { - Object args[] = { Context.getContext(), scope, - sealed ? Boolean.TRUE : Boolean.FALSE }; - method.invoke(null, args); - return null; - } - if (parmTypes.length == 1 && - parmTypes[0] == ScriptRuntime.ScriptableClass && - Modifier.isStatic(method.getModifiers())) - { - Object args[] = { scope }; - method.invoke(null, args); - return null; - } - - } - - // If we got here, there isn't an "init" method with the right - // parameter types. - - Constructor[] ctors = clazz.getConstructors(); - Constructor protoCtor = null; - for (int i=0; i < ctors.length; i++) { - if (ctors[i].getParameterTypes().length == 0) { - protoCtor = ctors[i]; - break; - } - } - if (protoCtor == null) { - throw Context.reportRuntimeError1( - "msg.zero.arg.ctor", clazz.getName()); - } - - Scriptable proto = (Scriptable) protoCtor.newInstance(ScriptRuntime.emptyArgs); - String className = proto.getClassName(); - - // Set the prototype's prototype, trying to map Java inheritance to JS - // prototype-based inheritance if requested to do so. - Scriptable superProto = null; - if (mapInheritance) { - Class superClass = clazz.getSuperclass(); - if (ScriptRuntime.ScriptableClass.isAssignableFrom(superClass) - && !Modifier.isAbstract(superClass.getModifiers())) { - String name = ScriptableObject.defineClass(scope, superClass, sealed, mapInheritance); - if (name != null) { - superProto = ScriptableObject.getClassPrototype(scope, name); - } - } - } - if (superProto == null) { - superProto = ScriptableObject.getObjectPrototype(scope); - } - proto.setPrototype(superProto); - - // Find out whether there are any methods that begin with - // "js". If so, then only methods that begin with special - // prefixes will be defined as JavaScript entities. - final String functionPrefix = "jsFunction_"; - final String staticFunctionPrefix = "jsStaticFunction_"; - final String getterPrefix = "jsGet_"; - final String setterPrefix = "jsSet_"; - final String ctorName = "jsConstructor"; - - Member ctorMember = FunctionObject.findSingleMethod(methods, ctorName); - - if (ctorMember == null) { - if (ctors.length == 1) { - ctorMember = ctors[0]; - } else if (ctors.length == 2) { - if (ctors[0].getParameterTypes().length == 0) - ctorMember = ctors[1]; - else if (ctors[1].getParameterTypes().length == 0) - ctorMember = ctors[0]; - } - if (ctorMember == null) { - throw Context.reportRuntimeError1( - "msg.ctor.multiple.parms", clazz.getName()); - } - } - - FunctionObject ctor = new FunctionObject(className, ctorMember, scope); - if (ctor.isVarArgsMethod()) { - throw Context.reportRuntimeError1 - ("msg.varargs.ctor", ctorMember.getName()); - } - ctor.initAsConstructor(scope, proto); - - Method finishInit = null; - for (int i=0; i < methods.length; i++) { - if (methods[i] == ctorMember) { - continue; - } - String name = methods[i].getName(); - if (name.equals("finishInit")) { - Class[] parmTypes = methods[i].getParameterTypes(); - if (parmTypes.length == 3 && - parmTypes[0] == ScriptRuntime.ScriptableClass && - parmTypes[1] == FunctionObject.class && - parmTypes[2] == ScriptRuntime.ScriptableClass && - Modifier.isStatic(methods[i].getModifiers())) - { - finishInit = methods[i]; - continue; - } - } - // ignore any compiler generated methods. - if (name.indexOf('$') != -1) - continue; - if (name.equals(ctorName)) - continue; - - String prefix = null; - if (name.startsWith(functionPrefix)) { - prefix = functionPrefix; - } else if (name.startsWith(staticFunctionPrefix)) { - prefix = staticFunctionPrefix; - if (!Modifier.isStatic(methods[i].getModifiers())) { - throw Context.reportRuntimeError( - "jsStaticFunction must be used with static method."); - } - } else if (name.startsWith(getterPrefix)) { - prefix = getterPrefix; - } else if (name.startsWith(setterPrefix)) { - prefix = setterPrefix; - } else { - continue; - } - name = name.substring(prefix.length()); - if (prefix == setterPrefix) - continue; // deal with set when we see get - if (prefix == getterPrefix) { - if (!(proto instanceof ScriptableObject)) { - throw Context.reportRuntimeError2( - "msg.extend.scriptable", - proto.getClass().toString(), name); - } - Method setter = FunctionObject.findSingleMethod( - methods, - setterPrefix + name); - int attr = ScriptableObject.PERMANENT | - ScriptableObject.DONTENUM | - (setter != null ? 0 - : ScriptableObject.READONLY); - ((ScriptableObject) proto).defineProperty(name, null, - methods[i], setter, - attr); - continue; - } - - FunctionObject f = new FunctionObject(name, methods[i], proto); - if (f.isVarArgsConstructor()) { - throw Context.reportRuntimeError1 - ("msg.varargs.fun", ctorMember.getName()); - } - Scriptable dest = prefix == staticFunctionPrefix - ? ctor - : proto; - defineProperty(dest, name, f, DONTENUM); - if (sealed) { - f.sealObject(); - } - } - - // Call user code to complete initialization if necessary. - if (finishInit != null) { - Object[] finishArgs = { scope, ctor, proto }; - finishInit.invoke(null, finishArgs); - } - - // Seal the object if necessary. - if (sealed) { - ctor.sealObject(); - if (proto instanceof ScriptableObject) { - ((ScriptableObject) proto).sealObject(); - } - } - - return ctor; - } - - /** - * Define a JavaScript property. - * - * Creates the property with an initial value and sets its attributes. - * - * @param propertyName the name of the property to define. - * @param value the initial value of the property - * @param attributes the attributes of the JavaScript property - * @see org.mozilla.javascript.Scriptable#put(String, Scriptable, Object) - */ - public void defineProperty(String propertyName, Object value, - int attributes) - { - checkNotSealed(propertyName, 0); - put(propertyName, this, value); - setAttributes(propertyName, attributes); - } - - /** - * Utility method to add properties to arbitrary Scriptable object. - * If destination is instance of ScriptableObject, calls - * defineProperty there, otherwise calls put in destination - * ignoring attributes - */ - public static void defineProperty(Scriptable destination, - String propertyName, Object value, - int attributes) - { - if (!(destination instanceof ScriptableObject)) { - destination.put(propertyName, destination, value); - return; - } - ScriptableObject so = (ScriptableObject)destination; - so.defineProperty(propertyName, value, attributes); - } - - /** - * Utility method to add properties to arbitrary Scriptable object. - * If destination is instance of ScriptableObject, calls - * defineProperty there, otherwise calls put in destination - * ignoring attributes - */ - public static void defineConstProperty(Scriptable destination, - String propertyName) - { - if (destination instanceof ConstProperties) { - ConstProperties cp = (ConstProperties)destination; - cp.defineConst(propertyName, destination); - } else - defineProperty(destination, propertyName, Undefined.instance, CONST); - } - - /** - * Define a JavaScript property with getter and setter side effects. - * - * If the setter is not found, the attribute READONLY is added to - * the given attributes. <p> - * - * The getter must be a method with zero parameters, and the setter, if - * found, must be a method with one parameter.<p> - * - * @param propertyName the name of the property to define. This name - * also affects the name of the setter and getter - * to search for. If the propertyId is "foo", then - * <code>clazz</code> will be searched for "getFoo" - * and "setFoo" methods. - * @param clazz the Java class to search for the getter and setter - * @param attributes the attributes of the JavaScript property - * @see org.mozilla.javascript.Scriptable#put(String, Scriptable, Object) - */ - public void defineProperty(String propertyName, Class clazz, - int attributes) - { - int length = propertyName.length(); - if (length == 0) throw new IllegalArgumentException(); - char[] buf = new char[3 + length]; - propertyName.getChars(0, length, buf, 3); - buf[3] = Character.toUpperCase(buf[3]); - buf[0] = 'g'; - buf[1] = 'e'; - buf[2] = 't'; - String getterName = new String(buf); - buf[0] = 's'; - String setterName = new String(buf); - - Method[] methods = FunctionObject.getMethodList(clazz); - Method getter = FunctionObject.findSingleMethod(methods, getterName); - Method setter = FunctionObject.findSingleMethod(methods, setterName); - if (setter == null) - attributes |= ScriptableObject.READONLY; - defineProperty(propertyName, null, getter, - setter == null ? null : setter, attributes); - } - - /** - * Define a JavaScript property. - * - * Use this method only if you wish to define getters and setters for - * a given property in a ScriptableObject. To create a property without - * special getter or setter side effects, use - * <code>defineProperty(String,int)</code>. - * - * If <code>setter</code> is null, the attribute READONLY is added to - * the given attributes.<p> - * - * Several forms of getters or setters are allowed. In all cases the - * type of the value parameter can be any one of the following types: - * Object, String, boolean, Scriptable, byte, short, int, long, float, - * or double. The runtime will perform appropriate conversions based - * upon the type of the parameter (see description in FunctionObject). - * The first forms are nonstatic methods of the class referred to - * by 'this': - * <pre> - * Object getFoo(); - * void setFoo(SomeType value);</pre> - * Next are static methods that may be of any class; the object whose - * property is being accessed is passed in as an extra argument: - * <pre> - * static Object getFoo(Scriptable obj); - * static void setFoo(Scriptable obj, SomeType value);</pre> - * Finally, it is possible to delegate to another object entirely using - * the <code>delegateTo</code> parameter. In this case the methods are - * nonstatic methods of the class delegated to, and the object whose - * property is being accessed is passed in as an extra argument: - * <pre> - * Object getFoo(Scriptable obj); - * void setFoo(Scriptable obj, SomeType value);</pre> - * - * @param propertyName the name of the property to define. - * @param delegateTo an object to call the getter and setter methods on, - * or null, depending on the form used above. - * @param getter the method to invoke to get the value of the property - * @param setter the method to invoke to set the value of the property - * @param attributes the attributes of the JavaScript property - */ - public void defineProperty(String propertyName, Object delegateTo, - Method getter, Method setter, int attributes) - { - MemberBox getterBox = null; - if (getter != null) { - getterBox = new MemberBox(getter); - - boolean delegatedForm; - if (!Modifier.isStatic(getter.getModifiers())) { - delegatedForm = (delegateTo != null); - getterBox.delegateTo = delegateTo; - } else { - delegatedForm = true; - // Ignore delegateTo for static getter but store - // non-null delegateTo indicator. - getterBox.delegateTo = Void.TYPE; - } - - String errorId = null; - Class[] parmTypes = getter.getParameterTypes(); - if (parmTypes.length == 0) { - if (delegatedForm) { - errorId = "msg.obj.getter.parms"; - } - } else if (parmTypes.length == 1) { - Object argType = parmTypes[0]; - // Allow ScriptableObject for compatibility - if (!(argType == ScriptRuntime.ScriptableClass || - argType == ScriptRuntime.ScriptableObjectClass)) - { - errorId = "msg.bad.getter.parms"; - } else if (!delegatedForm) { - errorId = "msg.bad.getter.parms"; - } - } else { - errorId = "msg.bad.getter.parms"; - } - if (errorId != null) { - throw Context.reportRuntimeError1(errorId, getter.toString()); - } - } - - MemberBox setterBox = null; - if (setter != null) { - if (setter.getReturnType() != Void.TYPE) - throw Context.reportRuntimeError1("msg.setter.return", - setter.toString()); - - setterBox = new MemberBox(setter); - - boolean delegatedForm; - if (!Modifier.isStatic(setter.getModifiers())) { - delegatedForm = (delegateTo != null); - setterBox.delegateTo = delegateTo; - } else { - delegatedForm = true; - // Ignore delegateTo for static setter but store - // non-null delegateTo indicator. - setterBox.delegateTo = Void.TYPE; - } - - String errorId = null; - Class[] parmTypes = setter.getParameterTypes(); - if (parmTypes.length == 1) { - if (delegatedForm) { - errorId = "msg.setter2.expected"; - } - } else if (parmTypes.length == 2) { - Object argType = parmTypes[0]; - // Allow ScriptableObject for compatibility - if (!(argType == ScriptRuntime.ScriptableClass || - argType == ScriptRuntime.ScriptableObjectClass)) - { - errorId = "msg.setter2.parms"; - } else if (!delegatedForm) { - errorId = "msg.setter1.parms"; - } - } else { - errorId = "msg.setter.parms"; - } - if (errorId != null) { - throw Context.reportRuntimeError1(errorId, setter.toString()); - } - } - - GetterSlot gslot = (GetterSlot)getSlot(propertyName, 0, - SLOT_MODIFY_GETTER_SETTER); - gslot.setAttributes(attributes); - gslot.getter = getterBox; - gslot.setter = setterBox; - } - - /** - * Search for names in a class, adding the resulting methods - * as properties. - * - * <p> Uses reflection to find the methods of the given names. Then - * FunctionObjects are constructed from the methods found, and - * are added to this object as properties with the given names. - * - * @param names the names of the Methods to add as function properties - * @param clazz the class to search for the Methods - * @param attributes the attributes of the new properties - * @see org.mozilla.javascript.FunctionObject - */ - public void defineFunctionProperties(String[] names, Class clazz, - int attributes) - { - Method[] methods = FunctionObject.getMethodList(clazz); - for (int i=0; i < names.length; i++) { - String name = names[i]; - Method m = FunctionObject.findSingleMethod(methods, name); - if (m == null) { - throw Context.reportRuntimeError2( - "msg.method.not.found", name, clazz.getName()); - } - FunctionObject f = new FunctionObject(name, m, this); - defineProperty(name, f, attributes); - } - } - - /** - * Get the Object.prototype property. - * See ECMA 15.2.4. - */ - public static Scriptable getObjectPrototype(Scriptable scope) { - return getClassPrototype(scope, "Object"); - } - - /** - * Get the Function.prototype property. - * See ECMA 15.3.4. - */ - public static Scriptable getFunctionPrototype(Scriptable scope) { - return getClassPrototype(scope, "Function"); - } - - /** - * Get the prototype for the named class. - * - * For example, <code>getClassPrototype(s, "Date")</code> will first - * walk up the parent chain to find the outermost scope, then will - * search that scope for the Date constructor, and then will - * return Date.prototype. If any of the lookups fail, or - * the prototype is not a JavaScript object, then null will - * be returned. - * - * @param scope an object in the scope chain - * @param className the name of the constructor - * @return the prototype for the named class, or null if it - * cannot be found. - */ - public static Scriptable getClassPrototype(Scriptable scope, - String className) - { - scope = getTopLevelScope(scope); - Object ctor = getProperty(scope, className); - Object proto; - if (ctor instanceof BaseFunction) { - proto = ((BaseFunction)ctor).getPrototypeProperty(); - } else if (ctor instanceof Scriptable) { - Scriptable ctorObj = (Scriptable)ctor; - proto = ctorObj.get("prototype", ctorObj); - } else { - return null; - } - if (proto instanceof Scriptable) { - return (Scriptable)proto; - } - return null; - } - - /** - * Get the global scope. - * - * <p>Walks the parent scope chain to find an object with a null - * parent scope (the global object). - * - * @param obj a JavaScript object - * @return the corresponding global scope - */ - public static Scriptable getTopLevelScope(Scriptable obj) - { - for (;;) { - Scriptable parent = obj.getParentScope(); - if (parent == null) { - return obj; - } - obj = parent; - } - } - - // APPJET - public static Scriptable getVeryTopLevelScope(Scriptable obj) { - return ScriptRuntime.getLibraryScopeOrNull(obj); - } - - /** - * Seal this object. - * - * A sealed object may not have properties added or removed. Once - * an object is sealed it may not be unsealed. - * - * @since 1.4R3 - */ - public synchronized void sealObject() { - if (count >= 0) { - count = ~count; - } - } - - /** - * Return true if this object is sealed. - * - * It is an error to attempt to add or remove properties to - * a sealed object. - * - * @return true if sealed, false otherwise. - * @since 1.4R3 - */ - public final boolean isSealed() { - return count < 0; - } - - private void checkNotSealed(String name, int index) - { - if (!isSealed()) - return; - - String str = (name != null) ? name : Integer.toString(index); - throw Context.reportRuntimeError1("msg.modify.sealed", str); - } - - /** - * Gets a named property from an object or any object in its prototype chain. - * <p> - * Searches the prototype chain for a property named <code>name</code>. - * <p> - * @param obj a JavaScript object - * @param name a property name - * @return the value of a property with name <code>name</code> found in - * <code>obj</code> or any object in its prototype chain, or - * <code>Scriptable.NOT_FOUND</code> if not found - * @since 1.5R2 - */ - public static Object getProperty(Scriptable obj, String name) - { - Scriptable start = obj; - Object result; - do { - result = obj.get(name, start); - if (result != Scriptable.NOT_FOUND) - break; - obj = obj.getPrototype(); - } while (obj != null); - return result; - } - - /** - * Gets an indexed property from an object or any object in its prototype chain. - * <p> - * Searches the prototype chain for a property with integral index - * <code>index</code>. Note that if you wish to look for properties with numerical - * but non-integral indicies, you should use getProperty(Scriptable,String) with - * the string value of the index. - * <p> - * @param obj a JavaScript object - * @param index an integral index - * @return the value of a property with index <code>index</code> found in - * <code>obj</code> or any object in its prototype chain, or - * <code>Scriptable.NOT_FOUND</code> if not found - * @since 1.5R2 - */ - public static Object getProperty(Scriptable obj, int index) - { - Scriptable start = obj; - Object result; - do { - result = obj.get(index, start); - if (result != Scriptable.NOT_FOUND) - break; - obj = obj.getPrototype(); - } while (obj != null); - return result; - } - - /** - * Returns whether a named property is defined in an object or any object - * in its prototype chain. - * <p> - * Searches the prototype chain for a property named <code>name</code>. - * <p> - * @param obj a JavaScript object - * @param name a property name - * @return the true if property was found - * @since 1.5R2 - */ - public static boolean hasProperty(Scriptable obj, String name) - { - return null != getBase(obj, name); - } - - /** - * If hasProperty(obj, name) would return true, then if the property that - * was found is compatible with the new property, this method just returns. - * If the property is not compatible, then an exception is thrown. - * - * A property redefinition is incompatible if the first definition was a - * const declaration or if this one is. They are compatible only if neither - * was const. - */ - public static void redefineProperty(Scriptable obj, String name, - boolean isConst) - { - Scriptable base = getBase(obj, name); - if (base == null) - return; - if (base instanceof ConstProperties) { - ConstProperties cp = (ConstProperties)base; - - if (cp.isConst(name)) - throw Context.reportRuntimeError1("msg.const.redecl", name); - } - if (isConst) - throw Context.reportRuntimeError1("msg.var.redecl", name); - } - /** - * Returns whether an indexed property is defined in an object or any object - * in its prototype chain. - * <p> - * Searches the prototype chain for a property with index <code>index</code>. - * <p> - * @param obj a JavaScript object - * @param index a property index - * @return the true if property was found - * @since 1.5R2 - */ - public static boolean hasProperty(Scriptable obj, int index) - { - return null != getBase(obj, index); - } - - /** - * Puts a named property in an object or in an object in its prototype chain. - * <p> - * Searches for the named property in the prototype chain. If it is found, - * the value of the property in <code>obj</code> is changed through a call - * to {@link Scriptable#put(String, Scriptable, Object)} on the - * prototype passing <code>obj</code> as the <code>start</code> argument. - * This allows the prototype to veto the property setting in case the - * prototype defines the property with [[ReadOnly]] attribute. If the - * property is not found, it is added in <code>obj</code>. - * @param obj a JavaScript object - * @param name a property name - * @param value any JavaScript value accepted by Scriptable.put - * @since 1.5R2 - */ - public static void putProperty(Scriptable obj, String name, Object value) - { - Scriptable base = getBase(obj, name); - if (base == null) - base = obj; - base.put(name, obj, value); - } - - /** - * Puts a named property in an object or in an object in its prototype chain. - * <p> - * Searches for the named property in the prototype chain. If it is found, - * the value of the property in <code>obj</code> is changed through a call - * to {@link Scriptable#put(String, Scriptable, Object)} on the - * prototype passing <code>obj</code> as the <code>start</code> argument. - * This allows the prototype to veto the property setting in case the - * prototype defines the property with [[ReadOnly]] attribute. If the - * property is not found, it is added in <code>obj</code>. - * @param obj a JavaScript object - * @param name a property name - * @param value any JavaScript value accepted by Scriptable.put - * @since 1.5R2 - */ - public static void putConstProperty(Scriptable obj, String name, Object value) - { - Scriptable base = getBase(obj, name); - if (base == null) - base = obj; - if (base instanceof ConstProperties) - ((ConstProperties)base).putConst(name, obj, value); - } - - /** - * Puts an indexed property in an object or in an object in its prototype chain. - * <p> - * Searches for the indexed property in the prototype chain. If it is found, - * the value of the property in <code>obj</code> is changed through a call - * to {@link Scriptable#put(int, Scriptable, Object)} on the prototype - * passing <code>obj</code> as the <code>start</code> argument. This allows - * the prototype to veto the property setting in case the prototype defines - * the property with [[ReadOnly]] attribute. If the property is not found, - * it is added in <code>obj</code>. - * @param obj a JavaScript object - * @param index a property index - * @param value any JavaScript value accepted by Scriptable.put - * @since 1.5R2 - */ - public static void putProperty(Scriptable obj, int index, Object value) - { - Scriptable base = getBase(obj, index); - if (base == null) - base = obj; - base.put(index, obj, value); - } - - /** - * Removes the property from an object or its prototype chain. - * <p> - * Searches for a property with <code>name</code> in obj or - * its prototype chain. If it is found, the object's delete - * method is called. - * @param obj a JavaScript object - * @param name a property name - * @return true if the property doesn't exist or was successfully removed - * @since 1.5R2 - */ - public static boolean deleteProperty(Scriptable obj, String name) - { - Scriptable base = getBase(obj, name); - if (base == null) - return true; - base.delete(name); - return !base.has(name, obj); - } - - /** - * Removes the property from an object or its prototype chain. - * <p> - * Searches for a property with <code>index</code> in obj or - * its prototype chain. If it is found, the object's delete - * method is called. - * @param obj a JavaScript object - * @param index a property index - * @return true if the property doesn't exist or was successfully removed - * @since 1.5R2 - */ - public static boolean deleteProperty(Scriptable obj, int index) - { - Scriptable base = getBase(obj, index); - if (base == null) - return true; - base.delete(index); - return !base.has(index, obj); - } - - /** - * Returns an array of all ids from an object and its prototypes. - * <p> - * @param obj a JavaScript object - * @return an array of all ids from all object in the prototype chain. - * If a given id occurs multiple times in the prototype chain, - * it will occur only once in this list. - * @since 1.5R2 - */ - public static Object[] getPropertyIds(Scriptable obj) - { - if (obj == null) { - return ScriptRuntime.emptyArgs; - } - Object[] result = obj.getIds(); - ObjToIntMap map = null; - for (;;) { - obj = obj.getPrototype(); - if (obj == null) { - break; - } - Object[] ids = obj.getIds(); - if (ids.length == 0) { - continue; - } - if (map == null) { - if (result.length == 0) { - result = ids; - continue; - } - map = new ObjToIntMap(result.length + ids.length); - for (int i = 0; i != result.length; ++i) { - map.intern(result[i]); - } - result = null; // Allow to GC the result - } - for (int i = 0; i != ids.length; ++i) { - map.intern(ids[i]); - } - } - if (map != null) { - result = map.getKeys(); - } - return result; - } - - /** - * Call a method of an object. - * @param obj the JavaScript object - * @param methodName the name of the function property - * @param args the arguments for the call - * - * @see Context#getCurrentContext() - */ - public static Object callMethod(Scriptable obj, String methodName, - Object[] args) - { - return callMethod(null, obj, methodName, args); - } - - /** - * Call a method of an object. - * @param cx the Context object associated with the current thread. - * @param obj the JavaScript object - * @param methodName the name of the function property - * @param args the arguments for the call - */ - public static Object callMethod(Context cx, Scriptable obj, - String methodName, - Object[] args) - { - Object funObj = getProperty(obj, methodName); - if (!(funObj instanceof Function)) { - throw ScriptRuntime.notFunctionError(obj, methodName); - } - Function fun = (Function)funObj; - // XXX: What should be the scope when calling funObj? - // The following favor scope stored in the object on the assumption - // that is more useful especially under dynamic scope setup. - // An alternative is to check for dynamic scope flag - // and use ScriptableObject.getTopLevelScope(fun) if the flag is not - // set. But that require access to Context and messy code - // so for now it is not checked. - Scriptable scope = ScriptableObject.getTopLevelScope(obj); - if (cx != null) { - return fun.call(cx, scope, obj, args); - } else { - return Context.call(null, fun, scope, obj, args); - } - } - - private static Scriptable getBase(Scriptable obj, String name) - { - do { - if (obj.has(name, obj)) - break; - obj = obj.getPrototype(); - } while(obj != null); - return obj; - } - - private static Scriptable getBase(Scriptable obj, int index) - { - do { - if (obj.has(index, obj)) - break; - obj = obj.getPrototype(); - } while(obj != null); - return obj; - } - - /** - * Get arbitrary application-specific value associated with this object. - * @param key key object to select particular value. - * @see #associateValue(Object key, Object value) - */ - public final Object getAssociatedValue(Object key) - { - Hashtable h = associatedValues; - if (h == null) - return null; - return h.get(key); - } - - /** - * Get arbitrary application-specific value associated with the top scope - * of the given scope. - * The method first calls {@link #getTopLevelScope(Scriptable scope)} - * and then searches the prototype chain of the top scope for the first - * object containing the associated value with the given key. - * - * @param scope the starting scope. - * @param key key object to select particular value. - * @see #getAssociatedValue(Object key) - */ - public static Object getTopScopeValue(Scriptable scope, Object key) - { - scope = ScriptableObject.getTopLevelScope(scope); - for (;;) { - if (scope instanceof ScriptableObject) { - ScriptableObject so = (ScriptableObject)scope; - Object value = so.getAssociatedValue(key); - if (value != null) { - return value; - } - } - scope = scope.getPrototype(); - if (scope == null) { - return null; - } - } - } - - /** - * Associate arbitrary application-specific value with this object. - * Value can only be associated with the given object and key only once. - * The method ignores any subsequent attempts to change the already - * associated value. - * <p> The associated values are not serialized. - * @param key key object to select particular value. - * @param value the value to associate - * @return the passed value if the method is called first time for the - * given key or old value for any subsequent calls. - * @see #getAssociatedValue(Object key) - */ - public final Object associateValue(Object key, Object value) - { - if (value == null) throw new IllegalArgumentException(); - Hashtable h = associatedValues; - if (h == null) { - synchronized (this) { - h = associatedValues; - if (h == null) { - h = new Hashtable(); - associatedValues = h; - } - } - } - return Kit.initHash(h, key, value); - } - - private Object getImpl(String name, int index, Scriptable start) - { - Slot slot = getSlot(name, index, SLOT_QUERY); - if (slot == null) { - return Scriptable.NOT_FOUND; - } - if (!(slot instanceof GetterSlot)) { - return slot.value; - } - Object getterObj = ((GetterSlot)slot).getter; - if (getterObj != null) { - if (getterObj instanceof MemberBox) { - MemberBox nativeGetter = (MemberBox)getterObj; - Object getterThis; - Object[] args; - if (nativeGetter.delegateTo == null) { - getterThis = start; - args = ScriptRuntime.emptyArgs; - } else { - getterThis = nativeGetter.delegateTo; - args = new Object[] { start }; - } - return nativeGetter.invoke(getterThis, args); - } else { - Function f = (Function)getterObj; - Context cx = Context.getContext(); - return f.call(cx, f.getParentScope(), start, - ScriptRuntime.emptyArgs); - } - } - Object value = slot.value; - if (value instanceof LazilyLoadedCtor) { - LazilyLoadedCtor initializer = (LazilyLoadedCtor)value; - try { - initializer.init(); - } finally { - value = initializer.getValue(); - slot.value = value; - } - } - return value; - } - - /** - * - * @param name - * @param index - * @param start - * @param value - * @param constFlag EMPTY means normal put. UNINITIALIZED_CONST means - * defineConstProperty. READONLY means const initialization expression. - * @return false if this != start and no slot was found. true if this == start - * or this != start and a READONLY slot was found. - */ - private boolean putImpl(String name, int index, Scriptable start, - Object value, int constFlag) - { - Slot slot; - if (this != start) { - slot = getSlot(name, index, SLOT_QUERY); - if (slot == null) { - return false; - } - } else { - checkNotSealed(name, index); - // either const hoisted declaration or initialization - if (constFlag != EMPTY) { - slot = getSlot(name, index, SLOT_MODIFY_CONST); - int attr = slot.getAttributes(); - if ((attr & READONLY) == 0) - throw Context.reportRuntimeError1("msg.var.redecl", name); - if ((attr & UNINITIALIZED_CONST) != 0) { - slot.value = value; - // clear the bit on const initialization - if (constFlag != UNINITIALIZED_CONST) - slot.setAttributes(attr & ~UNINITIALIZED_CONST); - } - return true; - } - slot = getSlot(name, index, SLOT_MODIFY); - } - if ((slot.getAttributes() & READONLY) != 0) - return true; - if (slot instanceof GetterSlot) { - Object setterObj = ((GetterSlot)slot).setter; - if (setterObj != null) { - Context cx = Context.getContext(); - if (setterObj instanceof MemberBox) { - MemberBox nativeSetter = (MemberBox)setterObj; - Class pTypes[] = nativeSetter.argTypes; - // XXX: cache tag since it is already calculated in - // defineProperty ? - Class valueType = pTypes[pTypes.length - 1]; - int tag = FunctionObject.getTypeTag(valueType); - Object actualArg = FunctionObject.convertArg(cx, start, - value, tag); - Object setterThis; - Object[] args; - if (nativeSetter.delegateTo == null) { - setterThis = start; - args = new Object[] { actualArg }; - } else { - setterThis = nativeSetter.delegateTo; - args = new Object[] { start, actualArg }; - } - nativeSetter.invoke(setterThis, args); - } else { - Function f = (Function)setterObj; - f.call(cx, f.getParentScope(), start, - new Object[] { value }); - } - return true; - } - } - if (this == start) { - slot.value = value; - return true; - } else { - return false; - } - } - - private Slot findAttributeSlot(String name, int index, int accessType) - { - Slot slot = getSlot(name, index, accessType); - if (slot == null) { - String str = (name != null ? name : Integer.toString(index)); - throw Context.reportRuntimeError1("msg.prop.not.found", str); - } - return slot; - } - - /** - * Locate the slot with given name or index. - * - * @param name property name or null if slot holds spare array index. - * @param index index or 0 if slot holds property name. - */ - private Slot getSlot(String name, int index, int accessType) - { - Slot slot; - - // Query last access cache and check that it was not deleted. - lastAccessCheck: - { - slot = lastAccess; - if (name != null) { - if (name != slot.name) - break lastAccessCheck; - // No String.equals here as successful slot search update - // name object with fresh reference of the same string. - } else { - if (slot.name != null || index != slot.indexOrHash) - break lastAccessCheck; - } - - if (slot.wasDeleted != 0) - break lastAccessCheck; - - if (accessType == SLOT_MODIFY_GETTER_SETTER && - !(slot instanceof GetterSlot)) - break lastAccessCheck; - - return slot; - } - - slot = accessSlot(name, index, accessType); - if (slot != null) { - // Update the cache - lastAccess = slot; - } - return slot; - } - - private Slot accessSlot(String name, int index, int accessType) - { - int indexOrHash = (name != null ? name.hashCode() : index); - - if (accessType == SLOT_QUERY || - accessType == SLOT_MODIFY || - accessType == SLOT_MODIFY_CONST || - accessType == SLOT_MODIFY_GETTER_SETTER) - { - // Check the hashtable without using synchronization - - Slot[] slotsLocalRef = slots; // Get stable local reference - if (slotsLocalRef == null) { - if (accessType == SLOT_QUERY) - return null; - } else { - int tableSize = slotsLocalRef.length; - int slotIndex = getSlotIndex(tableSize, indexOrHash); - Slot slot = slotsLocalRef[slotIndex]; - while (slot != null) { - String sname = slot.name; - if (sname != null) { - if (sname == name) - break; - if (name != null && indexOrHash == slot.indexOrHash) { - if (name.equals(sname)) { - // This will avoid calling String.equals when - // slot is accessed with same string object - // next time. - slot.name = name; - break; - } - } - } else if (name == null && - indexOrHash == slot.indexOrHash) { - break; - } - slot = slot.next; - } - if (accessType == SLOT_QUERY) { - return slot; - } else if (accessType == SLOT_MODIFY) { - if (slot != null) - return slot; - } else if (accessType == SLOT_MODIFY_GETTER_SETTER) { - if (slot instanceof GetterSlot) - return slot; - } else if (accessType == SLOT_MODIFY_CONST) { - if (slot != null) - return slot; - } - } - - // A new slot has to be inserted or the old has to be replaced - // by GetterSlot. Time to synchronize. - - synchronized (this) { - // Refresh local ref if another thread triggered grow - slotsLocalRef = slots; - int insertPos; - if (count == 0) { - // Always throw away old slots if any on empty insert - slotsLocalRef = new Slot[5]; - slots = slotsLocalRef; - insertPos = getSlotIndex(slotsLocalRef.length, indexOrHash); - } else { - int tableSize = slotsLocalRef.length; - insertPos = getSlotIndex(tableSize, indexOrHash); - Slot prev = slotsLocalRef[insertPos]; - Slot slot = prev; - while (slot != null) { - if (slot.indexOrHash == indexOrHash && - (slot.name == name || - (name != null && name.equals(slot.name)))) - { - break; - } - prev = slot; - slot = slot.next; - } - - if (slot != null) { - // Another thread just added a slot with same - // name/index before this one entered synchronized - // block. This is a race in application code and - // probably indicates bug there. But for the hashtable - // implementation it is harmless with the only - // complication is the need to replace the added slot - // if we need GetterSlot and the old one is not. - if (accessType == SLOT_MODIFY_GETTER_SETTER && - !(slot instanceof GetterSlot)) - { - GetterSlot newSlot = new GetterSlot(name, indexOrHash, - slot.getAttributes()); - newSlot.value = slot.value; - newSlot.next = slot.next; - if (prev == slot) { - slotsLocalRef[insertPos] = newSlot; - } else { - prev.next = newSlot; - } - slot.wasDeleted = (byte)1; - if (slot == lastAccess) { - lastAccess = REMOVED; - } - slot = newSlot; - } else if (accessType == SLOT_MODIFY_CONST) { - return null; - } - return slot; - } - - // Check if the table is not too full before inserting. - if (4 * (count + 1) > 3 * slotsLocalRef.length) { - slotsLocalRef = new Slot[slotsLocalRef.length * 2 + 1]; - copyTable(slots, slotsLocalRef, count); - slots = slotsLocalRef; - insertPos = getSlotIndex(slotsLocalRef.length, - indexOrHash); - } - } - - Slot newSlot = (accessType == SLOT_MODIFY_GETTER_SETTER - ? new GetterSlot(name, indexOrHash, 0) - : new Slot(name, indexOrHash, 0)); - if (accessType == SLOT_MODIFY_CONST) - newSlot.setAttributes(CONST); - ++count; - addKnownAbsentSlot(slotsLocalRef, newSlot, insertPos); - return newSlot; - } - - } else if (accessType == SLOT_REMOVE) { - synchronized (this) { - Slot[] slotsLocalRef = slots; - if (count != 0) { - int tableSize = slots.length; - int slotIndex = getSlotIndex(tableSize, indexOrHash); - Slot prev = slotsLocalRef[slotIndex]; - Slot slot = prev; - while (slot != null) { - if (slot.indexOrHash == indexOrHash && - (slot.name == name || - (name != null && name.equals(slot.name)))) - { - break; - } - prev = slot; - slot = slot.next; - } - if (slot != null && (slot.getAttributes() & PERMANENT) == 0) { - count--; - if (prev == slot) { - slotsLocalRef[slotIndex] = slot.next; - } else { - prev.next = slot.next; - } - // Mark the slot as removed to handle a case when - // another thread manages to put just removed slot - // into lastAccess cache. - slot.wasDeleted = (byte)1; - if (slot == lastAccess) { - lastAccess = REMOVED; - } - } - } - } - return null; - - } else { - throw Kit.codeBug(); - } - } - - private static int getSlotIndex(int tableSize, int indexOrHash) - { - return (indexOrHash & 0x7fffffff) % tableSize; - } - - // Must be inside synchronized (this) - private static void copyTable(Slot[] slots, Slot[] newSlots, int count) - { - if (count == 0) throw Kit.codeBug(); - - int tableSize = newSlots.length; - int i = slots.length; - for (;;) { - --i; - Slot slot = slots[i]; - while (slot != null) { - int insertPos = getSlotIndex(tableSize, slot.indexOrHash); - Slot next = slot.next; - addKnownAbsentSlot(newSlots, slot, insertPos); - slot.next = null; - slot = next; - if (--count == 0) - return; - } - } - } - - /** - * Add slot with keys that are known to absent from the table. - * This is an optimization to use when inserting into empty table, - * after table growth or during deserialization. - */ - private static void addKnownAbsentSlot(Slot[] slots, Slot slot, int insertPos) - { - if (slots[insertPos] == null) { - slots[insertPos] = slot; - } else { - Slot prev = slots[insertPos]; - while (prev.next != null) { - prev = prev.next; - } - prev.next = slot; - } - } - - Object[] getIds(boolean getAll) { - Slot[] s = slots; - Object[] a = ScriptRuntime.emptyArgs; - if (s == null) - return a; - int c = 0; - for (int i=0; i < s.length; i++) { - Slot slot = s[i]; - while (slot != null) { - if (getAll || (slot.getAttributes() & DONTENUM) == 0) { - if (c == 0) - a = new Object[s.length]; - a[c++] = (slot.name != null ? (Object) slot.name - : new Integer(slot.indexOrHash)); - } - slot = slot.next; - } - } - if (c == a.length) - return a; - Object[] result = new Object[c]; - System.arraycopy(a, 0, result, 0, c); - return result; - } - - private synchronized void writeObject(ObjectOutputStream out) - throws IOException - { - out.defaultWriteObject(); - int objectsCount = count; - if (objectsCount < 0) { - // "this" was sealed - objectsCount = ~objectsCount; - } - if (objectsCount == 0) { - out.writeInt(0); - } else { - out.writeInt(slots.length); - for (int i = 0; i < slots.length; ++i) { - Slot slot = slots[i]; - while (slot != null) { - out.writeObject(slot); - slot = slot.next; - if (--objectsCount == 0) - return; - } - } - } - } - - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - lastAccess = REMOVED; - - int tableSize = in.readInt(); - if (tableSize != 0) { - slots = new Slot[tableSize]; - int objectsCount = count; - if (objectsCount < 0) { - // "this" was sealed - objectsCount = ~objectsCount; - } - for (int i = 0; i != objectsCount; ++i) { - Slot slot = (Slot)in.readObject(); - int slotIndex = getSlotIndex(tableSize, slot.indexOrHash); - addKnownAbsentSlot(slots, slot, slotIndex); - } - } - } - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SecureCaller.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SecureCaller.java deleted file mode 100644 index bc8ed86..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SecureCaller.java +++ /dev/null @@ -1,198 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.ref.SoftReference; -import java.lang.reflect.UndeclaredThrowableException; -import java.net.URL; -import java.security.AccessController; -import java.security.CodeSource; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.security.SecureClassLoader; -import java.util.Map; -import java.util.WeakHashMap; - -/** - * @author Attila Szegedi - */ -public abstract class SecureCaller -{ - private static final byte[] secureCallerImplBytecode = loadBytecode(); - - // We're storing a CodeSource -> (ClassLoader -> SecureRenderer), since we - // need to have one renderer per class loader. We're using weak hash maps - // and soft references all the way, since we don't want to interfere with - // cleanup of either CodeSource or ClassLoader objects. - private static final Map callers = new WeakHashMap(); - - public abstract Object call(Callable callable, Context cx, - Scriptable scope, Scriptable thisObj, Object[] args); - - /** - * Call the specified callable using a protection domain belonging to the - * specified code source. - */ - static Object callSecurely(final CodeSource codeSource, Callable callable, - Context cx, Scriptable scope, Scriptable thisObj, Object[] args) - { - final Thread thread = Thread.currentThread(); - // Run in doPrivileged as we might be checked for "getClassLoader" - // runtime permission - final ClassLoader classLoader = (ClassLoader)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return thread.getContextClassLoader(); - } - }); - Map classLoaderMap; - synchronized(callers) - { - classLoaderMap = (Map)callers.get(codeSource); - if(classLoaderMap == null) - { - classLoaderMap = new WeakHashMap(); - callers.put(codeSource, classLoaderMap); - } - } - SecureCaller caller; - synchronized(classLoaderMap) - { - SoftReference ref = (SoftReference)classLoaderMap.get(classLoader); - if(ref != null) - { - caller = (SecureCaller)ref.get(); - } - else - { - caller = null; - } - if(caller == null) - { - try - { - // Run in doPrivileged as we'll be checked for - // "createClassLoader" runtime permission - caller = (SecureCaller)AccessController.doPrivileged( - new PrivilegedExceptionAction() - { - public Object run() throws Exception - { - ClassLoader effectiveClassLoader; - Class thisClass = getClass(); - if(classLoader.loadClass(thisClass.getName()) != thisClass) { - effectiveClassLoader = thisClass.getClassLoader(); - } else { - effectiveClassLoader = classLoader; - } - SecureClassLoaderImpl secCl = - new SecureClassLoaderImpl(effectiveClassLoader); - Class c = secCl.defineAndLinkClass( - SecureCaller.class.getName() + "Impl", - secureCallerImplBytecode, codeSource); - return c.newInstance(); - } - }); - classLoaderMap.put(classLoader, new SoftReference(caller)); - } - catch(PrivilegedActionException ex) - { - throw new UndeclaredThrowableException(ex.getCause()); - } - } - } - return caller.call(callable, cx, scope, thisObj, args); - } - - private static class SecureClassLoaderImpl extends SecureClassLoader - { - SecureClassLoaderImpl(ClassLoader parent) - { - super(parent); - } - - Class defineAndLinkClass(String name, byte[] bytes, CodeSource cs) - { - Class cl = defineClass(name, bytes, 0, bytes.length, cs); - resolveClass(cl); - return cl; - } - } - - private static byte[] loadBytecode() - { - return (byte[])AccessController.doPrivileged(new PrivilegedAction() - { - public Object run() - { - return loadBytecodePrivileged(); - } - }); - } - - private static byte[] loadBytecodePrivileged() - { - URL url = SecureCaller.class.getResource("SecureCallerImpl.clazz"); - try - { - InputStream in = url.openStream(); - try - { - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - for(;;) - { - int r = in.read(); - if(r == -1) - { - return bout.toByteArray(); - } - bout.write(r); - } - } - finally - { - in.close(); - } - } - catch(IOException e) - { - throw new UndeclaredThrowableException(e); - } - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SecurityController.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SecurityController.java deleted file mode 100644 index ed85dbf..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SecurityController.java +++ /dev/null @@ -1,211 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * This class describes the support needed to implement security. - * <p> - * Three main pieces of functionality are required to implement - * security for JavaScript. First, it must be possible to define - * classes with an associated security domain. (This security - * domain may be any object incorporating notion of access - * restrictions that has meaning to an embedding; for a client-side - * JavaScript embedding this would typically be - * java.security.ProtectionDomain or similar object depending on an - * origin URL and/or a digital certificate.) - * Next it must be possible to get a security domain object that - * allows a particular action only if all security domains - * associated with code on the current Java stack allows it. And - * finally, it must be possible to execute script code with - * associated security domain injected into Java stack. - * <p> - * These three pieces of functionality are encapsulated in the - * SecurityController class. - * - * @see org.mozilla.javascript.Context#setSecurityController(SecurityController) - * @see java.lang.ClassLoader - * @since 1.5 Release 4 - */ -public abstract class SecurityController -{ - private static SecurityController global; - -// The method must NOT be public or protected - static SecurityController global() - { - return global; - } - - /** - * Check if global {@link SecurityController} was already installed. - * @see #initGlobal(SecurityController controller) - */ - public static boolean hasGlobal() - { - return global != null; - } - - /** - * Initialize global controller that will be used for all - * security-related operations. The global controller takes precedence - * over already installed {@link Context}-specific controllers and cause - * any subsequent call to - * {@link Context#setSecurityController(SecurityController)} - * to throw an exception. - * <p> - * The method can only be called once. - * - * @see #hasGlobal() - */ - public static void initGlobal(SecurityController controller) - { - if (controller == null) throw new IllegalArgumentException(); - if (global != null) { - throw new SecurityException("Cannot overwrite already installed global SecurityController"); - } - global = controller; - } - - /** - * Get class loader-like object that can be used - * to define classes with the given security context. - * @param parentLoader parent class loader to delegate search for classes - * not defined by the class loader itself - * @param securityDomain some object specifying the security - * context of the code that is defined by the returned class loader. - */ - public abstract GeneratedClassLoader createClassLoader( - ClassLoader parentLoader, Object securityDomain); - - /** - * Create {@link GeneratedClassLoader} with restrictions imposed by - * staticDomain and all current stack frames. - * The method uses the SecurityController instance associated with the - * current {@link Context} to construct proper dynamic domain and create - * corresponding class loader. - * <par> - * If no SecurityController is associated with the current {@link Context} , - * the method calls {@link Context#createClassLoader(ClassLoader parent)}. - * - * @param parent parent class loader. If null, - * {@link Context#getApplicationClassLoader()} will be used. - * @param staticDomain static security domain. - */ - public static GeneratedClassLoader createLoader( - ClassLoader parent, Object staticDomain) - { - Context cx = Context.getContext(); - if (parent == null) { - parent = cx.getApplicationClassLoader(); - } - SecurityController sc = cx.getSecurityController(); - GeneratedClassLoader loader; - if (sc == null) { - loader = cx.createClassLoader(parent); - } else { - Object dynamicDomain = sc.getDynamicSecurityDomain(staticDomain); - loader = sc.createClassLoader(parent, dynamicDomain); - } - return loader; - } - - public static Class getStaticSecurityDomainClass() { - SecurityController sc = Context.getContext().getSecurityController(); - return sc == null ? null : sc.getStaticSecurityDomainClassInternal(); - } - - public Class getStaticSecurityDomainClassInternal() - { - return null; - } - - /** - * Get dynamic security domain that allows an action only if it is allowed - * by the current Java stack and <i>securityDomain</i>. If - * <i>securityDomain</i> is null, return domain representing permissions - * allowed by the current stack. - */ - public abstract Object getDynamicSecurityDomain(Object securityDomain); - - /** - * Call {@link - * Callable#call(Context cx, Scriptable scope, Scriptable thisObj, - * Object[] args)} - * of <i>callable</i> under restricted security domain where an action is - * allowed only if it is allowed according to the Java stack on the - * moment of the <i>execWithDomain</i> call and <i>securityDomain</i>. - * Any call to {@link #getDynamicSecurityDomain(Object)} during - * execution of <tt>callable.call(cx, scope, thisObj, args)</tt> - * should return a domain incorporate restrictions imposed by - * <i>securityDomain</i> and Java stack on the moment of callWithDomain - * invocation. - * <p> - * The method should always be overridden, it is not declared abstract - * for compatibility reasons. - */ - public Object callWithDomain(Object securityDomain, Context cx, - final Callable callable, Scriptable scope, - final Scriptable thisObj, final Object[] args) - { - return execWithDomain(cx, scope, new Script() - { - public Object exec(Context cx, Scriptable scope) - { - return callable.call(cx, scope, thisObj, args); - } - - }, securityDomain); - } - - /** - * @deprecated The application should not override this method and instead - * override - * {@link #callWithDomain(Object securityDomain, Context cx, Callable callable, Scriptable scope, Scriptable thisObj, Object[] args)}. - */ - public Object execWithDomain(Context cx, Scriptable scope, - Script script, Object securityDomain) - { - throw new IllegalStateException("callWithDomain should be overridden"); - } - - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SecurityUtilities.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SecurityUtilities.java deleted file mode 100644 index 275ad92..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SecurityUtilities.java +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.ProtectionDomain; - -/** - * @author Attila Szegedi - */ -public class SecurityUtilities -{ - /** - * Retrieves a system property within a privileged block. Use it only when - * the property is used from within Rhino code and is not passed out of it. - * @param name the name of the system property - * @return the value of the system property - */ - public static String getSystemProperty(final String name) - { - return (String)AccessController.doPrivileged( - new PrivilegedAction() - { - public Object run() - { - return System.getProperty(name); - } - }); - } - - public static ProtectionDomain getProtectionDomain(final Class clazz) - { - return (ProtectionDomain)AccessController.doPrivileged( - new PrivilegedAction() - { - public Object run() - { - return clazz.getProtectionDomain(); - } - }); - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SpecialRef.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SpecialRef.java deleted file mode 100644 index b037eaf..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/SpecialRef.java +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov, igor@fastmail.fm - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -class SpecialRef extends Ref -{ - static final long serialVersionUID = -7521596632456797847L; - - private static final int SPECIAL_NONE = 0; - private static final int SPECIAL_PROTO = 1; - private static final int SPECIAL_PARENT = 2; - - private Scriptable target; - private int type; - private String name; - - private SpecialRef(Scriptable target, int type, String name) - { - this.target = target; - this.type = type; - this.name = name; - } - - static Ref createSpecial(Context cx, Object object, String name) - { - Scriptable target = ScriptRuntime.toObjectOrNull(cx, object); - if (target == null) { - throw ScriptRuntime.undefReadError(object, name); - } - - int type; - if (name.equals("__proto__")) { - type = SPECIAL_PROTO; - } else if (name.equals("__parent__")) { - type = SPECIAL_PARENT; - } else { - throw new IllegalArgumentException(name); - } - - if (!cx.hasFeature(Context.FEATURE_PARENT_PROTO_PROPERTIES)) { - // Clear special after checking for valid name! - type = SPECIAL_NONE; - } - - return new SpecialRef(target, type, name); - } - - public Object get(Context cx) - { - switch (type) { - case SPECIAL_NONE: - return ScriptRuntime.getObjectProp(target, name, cx); - case SPECIAL_PROTO: - return target.getPrototype(); - case SPECIAL_PARENT: - return target.getParentScope(); - default: - throw Kit.codeBug(); - } - } - - public Object set(Context cx, Object value) - { - switch (type) { - case SPECIAL_NONE: - return ScriptRuntime.setObjectProp(target, name, value, cx); - case SPECIAL_PROTO: - case SPECIAL_PARENT: - { - Scriptable obj = ScriptRuntime.toObjectOrNull(cx, value); - if (obj != null) { - // Check that obj does not contain on its prototype/scope - // chain to prevent cycles - Scriptable search = obj; - do { - if (search == target) { - throw Context.reportRuntimeError1( - "msg.cyclic.value", name); - } - if (type == SPECIAL_PROTO) { - search = search.getPrototype(); - } else { - search = search.getParentScope(); - } - } while (search != null); - } - if (type == SPECIAL_PROTO) { - target.setPrototype(obj); - } else { - target.setParentScope(obj); - } - return obj; - } - default: - throw Kit.codeBug(); - } - } - - public boolean has(Context cx) - { - if (type == SPECIAL_NONE) { - return ScriptRuntime.hasObjectElem(target, name, cx); - } - return true; - } - - public boolean delete(Context cx) - { - if (type == SPECIAL_NONE) { - return ScriptRuntime.deleteObjectElem(target, name, cx); - } - return false; - } -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Synchronizer.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Synchronizer.java deleted file mode 100644 index f2fca52..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Synchronizer.java +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Delegator.java, released - * Sep 27, 2000. - * - * The Initial Developer of the Original Code is - * Matthias Radestock. <matthias@sorted.org>. - * Portions created by the Initial Developer are Copyright (C) 2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * This class provides support for implementing Java-style synchronized - * methods in Javascript. - * - * Synchronized functions are created from ordinary Javascript - * functions by the <code>Synchronizer</code> constructor, e.g. - * <code>new Packages.org.mozilla.javascript.Synchronizer(fun)</code>. - * The resulting object is a function that establishes an exclusive - * lock on the <code>this</code> object of its invocation. - * - * The Rhino shell provides a short-cut for the creation of - * synchronized methods: <code>sync(fun)</code> has the same effect as - * calling the above constructor. - * - * @see org.mozilla.javascript.Delegator - * @author Matthias Radestock - */ - -public class Synchronizer extends Delegator { - - /** - * Create a new synchronized function from an existing one. - * - * @param obj the existing function - */ - public Synchronizer(Scriptable obj) { - super(obj); - } - - /** - * @see org.mozilla.javascript.Function#call - */ - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - synchronized(thisObj instanceof Wrapper ? ((Wrapper)thisObj).unwrap() : thisObj) { - return ((Function)obj).call(cx,scope,thisObj,args); - } - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Token.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Token.java deleted file mode 100644 index be96487..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Token.java +++ /dev/null @@ -1,436 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Roger Lawrence - * Mike McCabe - * Igor Bukanov - * Bob Jervis - * Milen Nankov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class implements the JavaScript scanner. - * - * It is based on the C source files jsscan.c and jsscan.h - * in the jsref package. - * - * @see org.mozilla.javascript.Parser - * - * @author Mike McCabe - * @author Brendan Eich - */ - -public class Token -{ - - // debug flags - public static final boolean printTrees = - /*APPJET: some info not generated with this off; we disable - actual printing in Interpreter and CodeGen */true; - static final boolean printICode = false; - static final boolean printNames = printTrees || printICode; - - /** - * Token types. These values correspond to JSTokenType values in - * jsscan.c. - */ - - public final static int - // start enum - ERROR = -1, // well-known as the only code < EOF - EOF = 0, // end of file token - (not EOF_CHAR) - EOL = 1, // end of line - - // Interpreter reuses the following as bytecodes - FIRST_BYTECODE_TOKEN = 2, - - ENTERWITH = 2, - LEAVEWITH = 3, - RETURN = 4, - GOTO = 5, - IFEQ = 6, - IFNE = 7, - SETNAME = 8, - BITOR = 9, - BITXOR = 10, - BITAND = 11, - EQ = 12, - NE = 13, - LT = 14, - LE = 15, - GT = 16, - GE = 17, - LSH = 18, - RSH = 19, - URSH = 20, - ADD = 21, - SUB = 22, - MUL = 23, - DIV = 24, - MOD = 25, - NOT = 26, - BITNOT = 27, - POS = 28, - NEG = 29, - NEW = 30, - DELPROP = 31, - TYPEOF = 32, - GETPROP = 33, - GETPROPNOWARN = 34, - SETPROP = 35, - GETELEM = 36, - SETELEM = 37, - CALL = 38, - NAME = 39, - NUMBER = 40, - STRING = 41, - NULL = 42, - THIS = 43, - FALSE = 44, - TRUE = 45, - SHEQ = 46, // shallow equality (===) - SHNE = 47, // shallow inequality (!==) - REGEXP = 48, - BINDNAME = 49, - THROW = 50, - RETHROW = 51, // rethrow caught exception: catch (e if ) use it - IN = 52, - INSTANCEOF = 53, - LOCAL_LOAD = 54, - GETVAR = 55, - SETVAR = 56, - CATCH_SCOPE = 57, - ENUM_INIT_KEYS = 58, - ENUM_INIT_VALUES = 59, - ENUM_INIT_ARRAY= 60, - ENUM_NEXT = 61, - ENUM_ID = 62, - THISFN = 63, - RETURN_RESULT = 64, // to return previously stored return result - ARRAYLIT = 65, // array literal - OBJECTLIT = 66, // object literal - GET_REF = 67, // *reference - SET_REF = 68, // *reference = something - DEL_REF = 69, // delete reference - REF_CALL = 70, // f(args) = something or f(args)++ - REF_SPECIAL = 71, // reference for special properties like __proto - YIELD = 72, // JS 1.7 yield pseudo keyword - - // For XML support: - DEFAULTNAMESPACE = 73, // default xml namespace = - ESCXMLATTR = 74, - ESCXMLTEXT = 75, - REF_MEMBER = 76, // Reference for x.@y, x..y etc. - REF_NS_MEMBER = 77, // Reference for x.ns::y, x..ns::y etc. - REF_NAME = 78, // Reference for @y, @[y] etc. - REF_NS_NAME = 79; // Reference for ns::y, @ns::y@[y] etc. - - // End of interpreter bytecodes - public final static int - LAST_BYTECODE_TOKEN = REF_NS_NAME, - - TRY = 80, - SEMI = 81, // semicolon - LB = 82, // left and right brackets - RB = 83, - LC = 84, // left and right curlies (braces) - RC = 85, - LP = 86, // left and right parentheses - RP = 87, - COMMA = 88, // comma operator - - ASSIGN = 89, // simple assignment (=) - ASSIGN_BITOR = 90, // |= - ASSIGN_BITXOR = 91, // ^= - ASSIGN_BITAND = 92, // |= - ASSIGN_LSH = 93, // <<= - ASSIGN_RSH = 94, // >>= - ASSIGN_URSH = 95, // >>>= - ASSIGN_ADD = 96, // += - ASSIGN_SUB = 97, // -= - ASSIGN_MUL = 98, // *= - ASSIGN_DIV = 99, // /= - ASSIGN_MOD = 100; // %= - - public final static int - FIRST_ASSIGN = ASSIGN, - LAST_ASSIGN = ASSIGN_MOD, - - HOOK = 101, // conditional (?:) - COLON = 102, - OR = 103, // logical or (||) - AND = 104, // logical and (&&) - INC = 105, // increment/decrement (++ --) - DEC = 106, - DOT = 107, // member operator (.) - FUNCTION = 108, // function keyword - EXPORT = 109, // export keyword - IMPORT = 110, // import keyword - IF = 111, // if keyword - ELSE = 112, // else keyword - SWITCH = 113, // switch keyword - CASE = 114, // case keyword - DEFAULT = 115, // default keyword - WHILE = 116, // while keyword - DO = 117, // do keyword - FOR = 118, // for keyword - BREAK = 119, // break keyword - CONTINUE = 120, // continue keyword - VAR = 121, // var keyword - WITH = 122, // with keyword - CATCH = 123, // catch keyword - FINALLY = 124, // finally keyword - VOID = 125, // void keyword - RESERVED = 126, // reserved keywords - - EMPTY = 127, - - /* types used for the parse tree - these never get returned - * by the scanner. - */ - - BLOCK = 128, // statement block - LABEL = 129, // label - TARGET = 130, - LOOP = 131, - EXPR_VOID = 132, // expression statement in functions - EXPR_RESULT = 133, // expression statement in scripts - JSR = 134, - SCRIPT = 135, // top-level node for entire script - TYPEOFNAME = 136, // for typeof(simple-name) - USE_STACK = 137, - SETPROP_OP = 138, // x.y op= something - SETELEM_OP = 139, // x[y] op= something - LOCAL_BLOCK = 140, - SET_REF_OP = 141, // *reference op= something - - // For XML support: - DOTDOT = 142, // member operator (..) - COLONCOLON = 143, // namespace::name - XML = 144, // XML type - DOTQUERY = 145, // .() -- e.g., x.emps.emp.(name == "terry") - XMLATTR = 146, // @ - XMLEND = 147, - - // Optimizer-only-tokens - TO_OBJECT = 148, - TO_DOUBLE = 149, - - GET = 150, // JS 1.5 get pseudo keyword - SET = 151, // JS 1.5 set pseudo keyword - LET = 152, // JS 1.7 let pseudo keyword - CONST = 153, - SETCONST = 154, - SETCONSTVAR = 155, - ARRAYCOMP = 156, // array comprehension - LETEXPR = 157, - WITHEXPR = 158, - DEBUGGER = 159, - LAST_TOKEN = 159; - - public static String name(int token) - { - if (!printNames) { - return String.valueOf(token); - } - switch (token) { - case ERROR: return "ERROR"; - case EOF: return "EOF"; - case EOL: return "EOL"; - case ENTERWITH: return "ENTERWITH"; - case LEAVEWITH: return "LEAVEWITH"; - case RETURN: return "RETURN"; - case GOTO: return "GOTO"; - case IFEQ: return "IFEQ"; - case IFNE: return "IFNE"; - case SETNAME: return "SETNAME"; - case BITOR: return "BITOR"; - case BITXOR: return "BITXOR"; - case BITAND: return "BITAND"; - case EQ: return "EQ"; - case NE: return "NE"; - case LT: return "LT"; - case LE: return "LE"; - case GT: return "GT"; - case GE: return "GE"; - case LSH: return "LSH"; - case RSH: return "RSH"; - case URSH: return "URSH"; - case ADD: return "ADD"; - case SUB: return "SUB"; - case MUL: return "MUL"; - case DIV: return "DIV"; - case MOD: return "MOD"; - case NOT: return "NOT"; - case BITNOT: return "BITNOT"; - case POS: return "POS"; - case NEG: return "NEG"; - case NEW: return "NEW"; - case DELPROP: return "DELPROP"; - case TYPEOF: return "TYPEOF"; - case GETPROP: return "GETPROP"; - case GETPROPNOWARN: return "GETPROPNOWARN"; - case SETPROP: return "SETPROP"; - case GETELEM: return "GETELEM"; - case SETELEM: return "SETELEM"; - case CALL: return "CALL"; - case NAME: return "NAME"; - case NUMBER: return "NUMBER"; - case STRING: return "STRING"; - case NULL: return "NULL"; - case THIS: return "THIS"; - case FALSE: return "FALSE"; - case TRUE: return "TRUE"; - case SHEQ: return "SHEQ"; - case SHNE: return "SHNE"; - case REGEXP: return "OBJECT"; - case BINDNAME: return "BINDNAME"; - case THROW: return "THROW"; - case RETHROW: return "RETHROW"; - case IN: return "IN"; - case INSTANCEOF: return "INSTANCEOF"; - case LOCAL_LOAD: return "LOCAL_LOAD"; - case GETVAR: return "GETVAR"; - case SETVAR: return "SETVAR"; - case CATCH_SCOPE: return "CATCH_SCOPE"; - case ENUM_INIT_KEYS: return "ENUM_INIT_KEYS"; - case ENUM_INIT_VALUES:return "ENUM_INIT_VALUES"; - case ENUM_INIT_ARRAY: return "ENUM_INIT_ARRAY"; - case ENUM_NEXT: return "ENUM_NEXT"; - case ENUM_ID: return "ENUM_ID"; - case THISFN: return "THISFN"; - case RETURN_RESULT: return "RETURN_RESULT"; - case ARRAYLIT: return "ARRAYLIT"; - case OBJECTLIT: return "OBJECTLIT"; - case GET_REF: return "GET_REF"; - case SET_REF: return "SET_REF"; - case DEL_REF: return "DEL_REF"; - case REF_CALL: return "REF_CALL"; - case REF_SPECIAL: return "REF_SPECIAL"; - case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE"; - case ESCXMLTEXT: return "ESCXMLTEXT"; - case ESCXMLATTR: return "ESCXMLATTR"; - case REF_MEMBER: return "REF_MEMBER"; - case REF_NS_MEMBER: return "REF_NS_MEMBER"; - case REF_NAME: return "REF_NAME"; - case REF_NS_NAME: return "REF_NS_NAME"; - case TRY: return "TRY"; - case SEMI: return "SEMI"; - case LB: return "LB"; - case RB: return "RB"; - case LC: return "LC"; - case RC: return "RC"; - case LP: return "LP"; - case RP: return "RP"; - case COMMA: return "COMMA"; - case ASSIGN: return "ASSIGN"; - case ASSIGN_BITOR: return "ASSIGN_BITOR"; - case ASSIGN_BITXOR: return "ASSIGN_BITXOR"; - case ASSIGN_BITAND: return "ASSIGN_BITAND"; - case ASSIGN_LSH: return "ASSIGN_LSH"; - case ASSIGN_RSH: return "ASSIGN_RSH"; - case ASSIGN_URSH: return "ASSIGN_URSH"; - case ASSIGN_ADD: return "ASSIGN_ADD"; - case ASSIGN_SUB: return "ASSIGN_SUB"; - case ASSIGN_MUL: return "ASSIGN_MUL"; - case ASSIGN_DIV: return "ASSIGN_DIV"; - case ASSIGN_MOD: return "ASSIGN_MOD"; - case HOOK: return "HOOK"; - case COLON: return "COLON"; - case OR: return "OR"; - case AND: return "AND"; - case INC: return "INC"; - case DEC: return "DEC"; - case DOT: return "DOT"; - case FUNCTION: return "FUNCTION"; - case EXPORT: return "EXPORT"; - case IMPORT: return "IMPORT"; - case IF: return "IF"; - case ELSE: return "ELSE"; - case SWITCH: return "SWITCH"; - case CASE: return "CASE"; - case DEFAULT: return "DEFAULT"; - case WHILE: return "WHILE"; - case DO: return "DO"; - case FOR: return "FOR"; - case BREAK: return "BREAK"; - case CONTINUE: return "CONTINUE"; - case VAR: return "VAR"; - case WITH: return "WITH"; - case CATCH: return "CATCH"; - case FINALLY: return "FINALLY"; - case VOID: return "VOID"; - case RESERVED: return "RESERVED"; - case EMPTY: return "EMPTY"; - case BLOCK: return "BLOCK"; - case LABEL: return "LABEL"; - case TARGET: return "TARGET"; - case LOOP: return "LOOP"; - case EXPR_VOID: return "EXPR_VOID"; - case EXPR_RESULT: return "EXPR_RESULT"; - case JSR: return "JSR"; - case SCRIPT: return "SCRIPT"; - case TYPEOFNAME: return "TYPEOFNAME"; - case USE_STACK: return "USE_STACK"; - case SETPROP_OP: return "SETPROP_OP"; - case SETELEM_OP: return "SETELEM_OP"; - case LOCAL_BLOCK: return "LOCAL_BLOCK"; - case SET_REF_OP: return "SET_REF_OP"; - case DOTDOT: return "DOTDOT"; - case COLONCOLON: return "COLONCOLON"; - case XML: return "XML"; - case DOTQUERY: return "DOTQUERY"; - case XMLATTR: return "XMLATTR"; - case XMLEND: return "XMLEND"; - case TO_OBJECT: return "TO_OBJECT"; - case TO_DOUBLE: return "TO_DOUBLE"; - case GET: return "GET"; - case SET: return "SET"; - case LET: return "LET"; - case YIELD: return "YIELD"; - case CONST: return "CONST"; - case SETCONST: return "SETCONST"; - case ARRAYCOMP: return "ARRAYCOMP"; - case WITHEXPR: return "WITHEXPR"; - case LETEXPR: return "LETEXPR"; - case DEBUGGER: return "DEBUGGER"; - } - - // Token without name - throw new IllegalStateException(String.valueOf(token)); - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/TokenStream.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/TokenStream.java deleted file mode 100644 index c8c3045..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/TokenStream.java +++ /dev/null @@ -1,1500 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Roger Lawrence - * Mike McCabe - * Igor Bukanov - * Ethan Hugg - * Bob Jervis - * Terry Lucas - * Milen Nankov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.*; - -/** - * This class implements the JavaScript scanner. - * - * It is based on the C source files jsscan.c and jsscan.h - * in the jsref package. - * - * @see org.mozilla.javascript.Parser - * - * @author Mike McCabe - * @author Brendan Eich - */ - -class TokenStream -{ - /* - * For chars - because we need something out-of-range - * to check. (And checking EOF by exception is annoying.) - * Note distinction from EOF token type! - */ - private final static int - EOF_CHAR = -1; - - TokenStream(Parser parser, Reader sourceReader, String sourceString, - int lineno) - { - this.parser = parser; - this.lineno = lineno; - if (sourceReader != null) { - if (sourceString != null) Kit.codeBug(); - this.sourceReader = sourceReader; - this.sourceBuffer = new char[512]; - this.sourceEnd = 0; - } else { - if (sourceString == null) Kit.codeBug(); - this.sourceString = sourceString; - this.sourceEnd = sourceString.length(); - } - this.sourceCursor = 0; - } - - /* This function uses the cached op, string and number fields in - * TokenStream; if getToken has been called since the passed token - * was scanned, the op or string printed may be incorrect. - */ - String tokenToString(int token) - { - if (Token.printTrees) { - String name = Token.name(token); - - switch (token) { - case Token.STRING: - case Token.REGEXP: - case Token.NAME: - return name + " `" + this.string + "'"; - - case Token.NUMBER: - return "NUMBER " + this.number; - } - - return name; - } - return ""; - } - - static boolean isKeyword(String s) - { - return Token.EOF != stringToKeyword(s); - } - - private static int stringToKeyword(String name) - { -// #string_id_map# -// The following assumes that Token.EOF == 0 - final int - Id_break = Token.BREAK, - Id_case = Token.CASE, - Id_continue = Token.CONTINUE, - Id_default = Token.DEFAULT, - Id_delete = Token.DELPROP, - Id_do = Token.DO, - Id_else = Token.ELSE, - Id_export = Token.EXPORT, - Id_false = Token.FALSE, - Id_for = Token.FOR, - Id_function = Token.FUNCTION, - Id_if = Token.IF, - Id_in = Token.IN, - Id_let = Token.LET, - Id_new = Token.NEW, - Id_null = Token.NULL, - Id_return = Token.RETURN, - Id_switch = Token.SWITCH, - Id_this = Token.THIS, - Id_true = Token.TRUE, - Id_typeof = Token.TYPEOF, - Id_var = Token.VAR, - Id_void = Token.VOID, - Id_while = Token.WHILE, - Id_with = Token.WITH, - Id_yield = Token.YIELD, - - // the following are #ifdef RESERVE_JAVA_KEYWORDS in jsscan.c - Id_abstract = Token.RESERVED, - Id_boolean = Token.RESERVED, - Id_byte = Token.RESERVED, - Id_catch = Token.CATCH, - Id_char = Token.RESERVED, - Id_class = Token.RESERVED, - Id_const = Token.CONST, - Id_debugger = Token.DEBUGGER, - Id_double = Token.RESERVED, - Id_enum = Token.RESERVED, - Id_extends = Token.RESERVED, - Id_final = Token.RESERVED, - Id_finally = Token.FINALLY, - Id_float = Token.RESERVED, - Id_goto = Token.RESERVED, - Id_implements = Token.RESERVED, - Id_import = Token.IMPORT, - Id_instanceof = Token.INSTANCEOF, - Id_int = Token.RESERVED, - Id_interface = Token.RESERVED, - Id_long = Token.RESERVED, - Id_native = Token.RESERVED, - Id_package = Token.RESERVED, - Id_private = Token.RESERVED, - Id_protected = Token.RESERVED, - Id_public = Token.RESERVED, - Id_short = Token.RESERVED, - Id_static = Token.RESERVED, - Id_super = Token.RESERVED, - Id_synchronized = Token.RESERVED, - Id_throw = Token.THROW, - Id_throws = Token.RESERVED, - Id_transient = Token.RESERVED, - Id_try = Token.TRY, - Id_volatile = Token.RESERVED; - - int id; - String s = name; -// #generated# Last update: 2007-04-18 13:53:30 PDT - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 2: c=s.charAt(1); - if (c=='f') { if (s.charAt(0)=='i') {id=Id_if; break L0;} } - else if (c=='n') { if (s.charAt(0)=='i') {id=Id_in; break L0;} } - else if (c=='o') { if (s.charAt(0)=='d') {id=Id_do; break L0;} } - break L; - case 3: switch (s.charAt(0)) { - case 'f': if (s.charAt(2)=='r' && s.charAt(1)=='o') {id=Id_for; break L0;} break L; - case 'i': if (s.charAt(2)=='t' && s.charAt(1)=='n') {id=Id_int; break L0;} break L; - case 'l': if (s.charAt(2)=='t' && s.charAt(1)=='e') {id=Id_let; break L0;} break L; - case 'n': if (s.charAt(2)=='w' && s.charAt(1)=='e') {id=Id_new; break L0;} break L; - case 't': if (s.charAt(2)=='y' && s.charAt(1)=='r') {id=Id_try; break L0;} break L; - case 'v': if (s.charAt(2)=='r' && s.charAt(1)=='a') {id=Id_var; break L0;} break L; - } break L; - case 4: switch (s.charAt(0)) { - case 'b': X="byte";id=Id_byte; break L; - case 'c': c=s.charAt(3); - if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='a') {id=Id_case; break L0;} } - else if (c=='r') { if (s.charAt(2)=='a' && s.charAt(1)=='h') {id=Id_char; break L0;} } - break L; - case 'e': c=s.charAt(3); - if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='l') {id=Id_else; break L0;} } - else if (c=='m') { if (s.charAt(2)=='u' && s.charAt(1)=='n') {id=Id_enum; break L0;} } - break L; - case 'g': X="goto";id=Id_goto; break L; - case 'l': X="long";id=Id_long; break L; - case 'n': X="null";id=Id_null; break L; - case 't': c=s.charAt(3); - if (c=='e') { if (s.charAt(2)=='u' && s.charAt(1)=='r') {id=Id_true; break L0;} } - else if (c=='s') { if (s.charAt(2)=='i' && s.charAt(1)=='h') {id=Id_this; break L0;} } - break L; - case 'v': X="void";id=Id_void; break L; - case 'w': X="with";id=Id_with; break L; - } break L; - case 5: switch (s.charAt(2)) { - case 'a': X="class";id=Id_class; break L; - case 'e': c=s.charAt(0); - if (c=='b') { X="break";id=Id_break; } - else if (c=='y') { X="yield";id=Id_yield; } - break L; - case 'i': X="while";id=Id_while; break L; - case 'l': X="false";id=Id_false; break L; - case 'n': c=s.charAt(0); - if (c=='c') { X="const";id=Id_const; } - else if (c=='f') { X="final";id=Id_final; } - break L; - case 'o': c=s.charAt(0); - if (c=='f') { X="float";id=Id_float; } - else if (c=='s') { X="short";id=Id_short; } - break L; - case 'p': X="super";id=Id_super; break L; - case 'r': X="throw";id=Id_throw; break L; - case 't': X="catch";id=Id_catch; break L; - } break L; - case 6: switch (s.charAt(1)) { - case 'a': X="native";id=Id_native; break L; - case 'e': c=s.charAt(0); - if (c=='d') { X="delete";id=Id_delete; } - else if (c=='r') { X="return";id=Id_return; } - break L; - case 'h': X="throws";id=Id_throws; break L; - /*APPJET*//* case 'm': X="import";id=Id_import; break L;*/ - case 'o': X="double";id=Id_double; break L; - case 't': X="static";id=Id_static; break L; - case 'u': X="public";id=Id_public; break L; - case 'w': X="switch";id=Id_switch; break L; - case 'x': X="export";id=Id_export; break L; - case 'y': X="typeof";id=Id_typeof; break L; - } break L; - case 7: switch (s.charAt(1)) { - case 'a': X="package";id=Id_package; break L; - case 'e': X="default";id=Id_default; break L; - case 'i': X="finally";id=Id_finally; break L; - case 'o': X="boolean";id=Id_boolean; break L; - case 'r': X="private";id=Id_private; break L; - case 'x': X="extends";id=Id_extends; break L; - } break L; - case 8: switch (s.charAt(0)) { - case 'a': X="abstract";id=Id_abstract; break L; - case 'c': X="continue";id=Id_continue; break L; - case 'd': X="debugger";id=Id_debugger; break L; - case 'f': X="function";id=Id_function; break L; - case 'v': X="volatile";id=Id_volatile; break L; - } break L; - case 9: c=s.charAt(0); - if (c=='i') { X="interface";id=Id_interface; } - else if (c=='p') { X="protected";id=Id_protected; } - else if (c=='t') { X="transient";id=Id_transient; } - break L; - case 10: c=s.charAt(1); - if (c=='m') { X="implements";id=Id_implements; } - else if (c=='n') { X="instanceof";id=Id_instanceof; } - break L; - case 12: X="synchronized";id=Id_synchronized; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - } -// #/generated# -// #/string_id_map# - if (id == 0) { return Token.EOF; } - return id & 0xff; - } - - final int getLineno() { return lineno; } - - final String getString() { return string; } - - final double getNumber() { return number; } - - final boolean eof() { return hitEOF; } - - final int getToken() throws IOException - { - int c; - - retry: - for (;;) { - // Eat whitespace, possibly sensitive to newlines. - for (;;) { - c = getChar(); - if (c == EOF_CHAR) { - return Token.EOF; - } else if (c == '\n') { - dirtyLine = false; - return Token.EOL; - } else if (!isJSSpace(c)) { - if (c != '-') { - dirtyLine = true; - } - break; - } - } - - if (c == '@') return Token.XMLATTR; - - // identifier/keyword/instanceof? - // watch out for starting with a <backslash> - boolean identifierStart; - boolean isUnicodeEscapeStart = false; - if (c == '\\') { - c = getChar(); - if (c == 'u') { - identifierStart = true; - isUnicodeEscapeStart = true; - stringBufferTop = 0; - } else { - identifierStart = false; - ungetChar(c); - c = '\\'; - } - } else { - identifierStart = Character.isJavaIdentifierStart((char)c); - if (identifierStart) { - stringBufferTop = 0; - addToString(c); - } - } - - if (identifierStart) { - boolean containsEscape = isUnicodeEscapeStart; - for (;;) { - if (isUnicodeEscapeStart) { - // strictly speaking we should probably push-back - // all the bad characters if the <backslash>uXXXX - // sequence is malformed. But since there isn't a - // correct context(is there?) for a bad Unicode - // escape sequence in an identifier, we can report - // an error here. - int escapeVal = 0; - for (int i = 0; i != 4; ++i) { - c = getChar(); - escapeVal = Kit.xDigitToInt(c, escapeVal); - // Next check takes care about c < 0 and bad escape - if (escapeVal < 0) { break; } - } - if (escapeVal < 0) { - parser.addError("msg.invalid.escape"); - return Token.ERROR; - } - addToString(escapeVal); - isUnicodeEscapeStart = false; - } else { - c = getChar(); - if (c == '\\') { - c = getChar(); - if (c == 'u') { - isUnicodeEscapeStart = true; - containsEscape = true; - } else { - /*APPJET*/ - parser.addError("msg.illegal.character.appjet", - "\\"+Character.toString((char)c)); - return Token.ERROR; - } - } else { - if (c == EOF_CHAR - || !Character.isJavaIdentifierPart((char)c)) - { - break; - } - addToString(c); - } - } - } - ungetChar(c); - - String str = getStringFromBuffer(); - /*APPJET*//*MOVED*/this.string = (String)allStrings.intern(str); - /*APPJET this move lets the names of RESERVED tokens and other - tokens be determined, and also fixes broken yield/let parsing - under pre-1.7 JS */ - if (!containsEscape) { - // OPT we shouldn't have to make a string (object!) to - // check if it's a keyword. - - // Return the corresponding token if it's a keyword - int result = stringToKeyword(str); - if (result != Token.EOF) { - if ((result == Token.LET || result == Token.YIELD) && - parser.compilerEnv.getLanguageVersion() - < Context.VERSION_1_7) - { - // LET and YIELD are tokens only in 1.7 and later - result = Token.NAME; - } - if (result != Token.RESERVED) { - return result; - } else if (!parser.compilerEnv. - isReservedKeywordAsIdentifier()) - { - return result; - } else { - // If implementation permits to use future reserved - // keywords in violation with the EcmaScript, - // treat it as name but issue warning - parser.addWarning("msg.reserved.keyword", str); - } - } - } - return Token.NAME; - } - - // is it a number? - if (isDigit(c) || (c == '.' && isDigit(peekChar()))) { - - stringBufferTop = 0; - int base = 10; - - if (c == '0') { - c = getChar(); - if (c == 'x' || c == 'X') { - base = 16; - c = getChar(); - } else if (isDigit(c)) { - base = 8; - } else { - addToString('0'); - } - } - - if (base == 16) { - while (0 <= Kit.xDigitToInt(c, 0)) { - addToString(c); - c = getChar(); - } - } else { - while ('0' <= c && c <= '9') { - /* - * We permit 08 and 09 as decimal numbers, which - * makes our behavior a superset of the ECMA - * numeric grammar. We might not always be so - * permissive, so we warn about it. - */ - if (base == 8 && c >= '8') { - parser.addWarning("msg.bad.octal.literal", - c == '8' ? "8" : "9"); - base = 10; - } - addToString(c); - c = getChar(); - } - } - - boolean isInteger = true; - - if (base == 10 && (c == '.' || c == 'e' || c == 'E')) { - isInteger = false; - if (c == '.') { - do { - addToString(c); - c = getChar(); - } while (isDigit(c)); - } - if (c == 'e' || c == 'E') { - addToString(c); - c = getChar(); - if (c == '+' || c == '-') { - addToString(c); - c = getChar(); - } - if (!isDigit(c)) { - parser.addError("msg.missing.exponent"); - return Token.ERROR; - } - do { - addToString(c); - c = getChar(); - } while (isDigit(c)); - } - } - ungetChar(c); - String numString = getStringFromBuffer(); - - double dval; - if (base == 10 && !isInteger) { - try { - // Use Java conversion to number from string... - dval = Double.valueOf(numString).doubleValue(); - } - catch (NumberFormatException ex) { - parser.addError("msg.caught.nfe"); - return Token.ERROR; - } - } else { - dval = ScriptRuntime.stringToNumber(numString, 0, base); - } - - this.number = dval; - return Token.NUMBER; - } - - // is it a string? - if (c == '"' || c == '\'') { - // We attempt to accumulate a string the fast way, by - // building it directly out of the reader. But if there - // are any escaped characters in the string, we revert to - // building it out of a StringBuffer. - - /*APPJET*/ - if (c == '"' && tryReadTripleQuotedString()) { - return Token.STRING; - } - - int quoteChar = c; - stringBufferTop = 0; - - c = getChar(); - strLoop: while (c != quoteChar) { - if (c == '\n' || c == EOF_CHAR) { - ungetChar(c); - /*APPJET*/ - parser.addError("msg.unterminated.string.lit", - Character.toString((char)quoteChar)); - return Token.ERROR; - } - - if (c == '\\') { - // We've hit an escaped character - int escapeVal; - - c = getChar(); - switch (c) { - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - - // \v a late addition to the ECMA spec, - // it is not in Java, so use 0xb - case 'v': c = 0xb; break; - - case 'u': - // Get 4 hex digits; if the u escape is not - // followed by 4 hex digits, use 'u' + the - // literal character sequence that follows. - int escapeStart = stringBufferTop; - addToString('u'); - escapeVal = 0; - for (int i = 0; i != 4; ++i) { - c = getChar(); - escapeVal = Kit.xDigitToInt(c, escapeVal); - if (escapeVal < 0) { - continue strLoop; - } - addToString(c); - } - // prepare for replace of stored 'u' sequence - // by escape value - stringBufferTop = escapeStart; - c = escapeVal; - break; - case 'x': - // Get 2 hex digits, defaulting to 'x'+literal - // sequence, as above. - c = getChar(); - escapeVal = Kit.xDigitToInt(c, 0); - if (escapeVal < 0) { - addToString('x'); - continue strLoop; - } else { - int c1 = c; - c = getChar(); - escapeVal = Kit.xDigitToInt(c, escapeVal); - if (escapeVal < 0) { - addToString('x'); - addToString(c1); - continue strLoop; - } else { - // got 2 hex digits - c = escapeVal; - } - } - break; - - case '\n': - // Remove line terminator after escape to follow - // SpiderMonkey and C/C++ - c = getChar(); - continue strLoop; - - default: - if ('0' <= c && c < '8') { - int val = c - '0'; - c = getChar(); - if ('0' <= c && c < '8') { - val = 8 * val + c - '0'; - c = getChar(); - if ('0' <= c && c < '8' && val <= 037) { - // c is 3rd char of octal sequence only - // if the resulting val <= 0377 - val = 8 * val + c - '0'; - c = getChar(); - } - } - ungetChar(c); - c = val; - } - } - } - addToString(c); - c = getChar(); - } - - String str = getStringFromBuffer(); - this.string = (String)allStrings.intern(str); - return Token.STRING; - } - - switch (c) { - case ';': return Token.SEMI; - case '[': return Token.LB; - case ']': return Token.RB; - case '{': return Token.LC; - case '}': return Token.RC; - case '(': return Token.LP; - case ')': return Token.RP; - case ',': return Token.COMMA; - case '?': return Token.HOOK; - case ':': - if (matchChar(':')) { - return Token.COLONCOLON; - } else { - return Token.COLON; - } - case '.': - if (matchChar('.')) { - return Token.DOTDOT; - } else if (matchChar('(')) { - return Token.DOTQUERY; - } else { - return Token.DOT; - } - - case '|': - if (matchChar('|')) { - return Token.OR; - } else if (matchChar('=')) { - return Token.ASSIGN_BITOR; - } else { - return Token.BITOR; - } - - case '^': - if (matchChar('=')) { - return Token.ASSIGN_BITXOR; - } else { - return Token.BITXOR; - } - - case '&': - if (matchChar('&')) { - return Token.AND; - } else if (matchChar('=')) { - return Token.ASSIGN_BITAND; - } else { - return Token.BITAND; - } - - case '=': - if (matchChar('=')) { - if (matchChar('=')) - return Token.SHEQ; - else - return Token.EQ; - } else { - return Token.ASSIGN; - } - - case '!': - if (matchChar('=')) { - if (matchChar('=')) - return Token.SHNE; - else - return Token.NE; - } else { - return Token.NOT; - } - - case '<': - /* NB:treat HTML begin-comment as comment-till-eol */ - if (matchChar('!')) { - if (matchChar('-')) { - if (matchChar('-')) { - skipLine(); - continue retry; - } - ungetChar('-'); - } - ungetChar('!'); - } - if (matchChar('<')) { - if (matchChar('=')) { - return Token.ASSIGN_LSH; - } else { - return Token.LSH; - } - } else { - if (matchChar('=')) { - return Token.LE; - } else { - return Token.LT; - } - } - - case '>': - if (matchChar('>')) { - if (matchChar('>')) { - if (matchChar('=')) { - return Token.ASSIGN_URSH; - } else { - return Token.URSH; - } - } else { - if (matchChar('=')) { - return Token.ASSIGN_RSH; - } else { - return Token.RSH; - } - } - } else { - if (matchChar('=')) { - return Token.GE; - } else { - return Token.GT; - } - } - - case '*': - if (matchChar('=')) { - return Token.ASSIGN_MUL; - } else { - return Token.MUL; - } - - case '/': - // is it a // comment? - if (matchChar('/')) { - skipLine(); - continue retry; - } - if (matchChar('*')) { - boolean lookForSlash = false; - for (;;) { - c = getChar(); - if (c == EOF_CHAR) { - parser.addError("msg.unterminated.comment"); - return Token.ERROR; - } else if (c == '*') { - lookForSlash = true; - } else if (c == '/') { - if (lookForSlash) { - continue retry; - } - } else { - lookForSlash = false; - } - } - } - - if (matchChar('=')) { - return Token.ASSIGN_DIV; - } else { - return Token.DIV; - } - - case '%': - if (matchChar('=')) { - return Token.ASSIGN_MOD; - } else { - return Token.MOD; - } - - case '~': - return Token.BITNOT; - - case '+': - if (matchChar('=')) { - return Token.ASSIGN_ADD; - } else if (matchChar('+')) { - return Token.INC; - } else { - return Token.ADD; - } - - case '-': - if (matchChar('=')) { - c = Token.ASSIGN_SUB; - } else if (matchChar('-')) { - if (!dirtyLine) { - // treat HTML end-comment after possible whitespace - // after line start as comment-utill-eol - if (matchChar('>')) { - skipLine(); - continue retry; - } - } - c = Token.DEC; - } else { - c = Token.SUB; - } - dirtyLine = true; - return c; - - default: - /*APPJET*/ - parser.addError("msg.illegal.character.appjet", - Character.toString((char)c)); - return Token.ERROR; - } - } - } - - private static boolean isAlpha(int c) - { - // Use 'Z' < 'a' - if (c <= 'Z') { - return 'A' <= c; - } else { - return 'a' <= c && c <= 'z'; - } - } - - static boolean isDigit(int c) - { - return '0' <= c && c <= '9'; - } - - /* As defined in ECMA. jsscan.c uses C isspace() (which allows - * \v, I think.) note that code in getChar() implicitly accepts - * '\r' == \u000D as well. - */ - static boolean isJSSpace(int c) - { - if (c <= 127) { - return c == 0x20 || c == 0x9 || c == 0xC || c == 0xB; - } else { - return c == 0xA0 - || Character.getType((char)c) == Character.SPACE_SEPARATOR; - } - } - - private static boolean isJSFormatChar(int c) - { - return c > 127 && Character.getType((char)c) == Character.FORMAT; - } - - /** - * Parser calls the method when it gets / or /= in literal context. - */ - void readRegExp(int startToken) - throws IOException - { - stringBufferTop = 0; - if (startToken == Token.ASSIGN_DIV) { - // Miss-scanned /= - addToString('='); - } else { - if (startToken != Token.DIV) Kit.codeBug(); - } - - int c; - while ((c = getChar()) != '/') { - if (c == '\n' || c == EOF_CHAR) { - ungetChar(c); - throw parser.reportError("msg.unterminated.re.lit"); - } - if (c == '\\') { - addToString(c); - c = getChar(); - } - - addToString(c); - } - int reEnd = stringBufferTop; - - while (true) { - if (matchChar('g')) - addToString('g'); - else if (matchChar('i')) - addToString('i'); - else if (matchChar('m')) - addToString('m'); - else - break; - } - - if (isAlpha(peekChar())) { - throw parser.reportError("msg.invalid.re.flag"); - } - - this.string = new String(stringBuffer, 0, reEnd); - this.regExpFlags = new String(stringBuffer, reEnd, - stringBufferTop - reEnd); - } - - boolean isXMLAttribute() - { - return xmlIsAttribute; - } - - int getFirstXMLToken() throws IOException - { - xmlOpenTagsCount = 0; - xmlIsAttribute = false; - xmlIsTagContent = false; - ungetChar('<'); - return getNextXMLToken(); - } - - int getNextXMLToken() throws IOException - { - stringBufferTop = 0; // remember the XML - - for (int c = getChar(); c != EOF_CHAR; c = getChar()) { - if (xmlIsTagContent) { - switch (c) { - case '>': - addToString(c); - xmlIsTagContent = false; - xmlIsAttribute = false; - break; - case '/': - addToString(c); - if (peekChar() == '>') { - c = getChar(); - addToString(c); - xmlIsTagContent = false; - xmlOpenTagsCount--; - } - break; - case '{': - ungetChar(c); - this.string = getStringFromBuffer(); - return Token.XML; - case '\'': - case '"': - addToString(c); - if (!readQuotedString(c)) return Token.ERROR; - break; - case '=': - addToString(c); - xmlIsAttribute = true; - break; - case ' ': - case '\t': - case '\r': - case '\n': - addToString(c); - break; - default: - addToString(c); - xmlIsAttribute = false; - break; - } - - if (!xmlIsTagContent && xmlOpenTagsCount == 0) { - this.string = getStringFromBuffer(); - return Token.XMLEND; - } - } else { - switch (c) { - case '<': - addToString(c); - c = peekChar(); - switch (c) { - case '!': - c = getChar(); // Skip ! - addToString(c); - c = peekChar(); - switch (c) { - case '-': - c = getChar(); // Skip - - addToString(c); - c = getChar(); - if (c == '-') { - addToString(c); - if(!readXmlComment()) return Token.ERROR; - } else { - // throw away the string in progress - stringBufferTop = 0; - this.string = null; - parser.addError("msg.XML.bad.form"); - return Token.ERROR; - } - break; - case '[': - c = getChar(); // Skip [ - addToString(c); - if (getChar() == 'C' && - getChar() == 'D' && - getChar() == 'A' && - getChar() == 'T' && - getChar() == 'A' && - getChar() == '[') - { - addToString('C'); - addToString('D'); - addToString('A'); - addToString('T'); - addToString('A'); - addToString('['); - if (!readCDATA()) return Token.ERROR; - - } else { - // throw away the string in progress - stringBufferTop = 0; - this.string = null; - parser.addError("msg.XML.bad.form"); - return Token.ERROR; - } - break; - default: - if(!readEntity()) return Token.ERROR; - break; - } - break; - case '?': - c = getChar(); // Skip ? - addToString(c); - if (!readPI()) return Token.ERROR; - break; - case '/': - // End tag - c = getChar(); // Skip / - addToString(c); - if (xmlOpenTagsCount == 0) { - // throw away the string in progress - stringBufferTop = 0; - this.string = null; - parser.addError("msg.XML.bad.form"); - return Token.ERROR; - } - xmlIsTagContent = true; - xmlOpenTagsCount--; - break; - default: - // Start tag - xmlIsTagContent = true; - xmlOpenTagsCount++; - break; - } - break; - case '{': - ungetChar(c); - this.string = getStringFromBuffer(); - return Token.XML; - default: - addToString(c); - break; - } - } - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return Token.ERROR; - } - - /** - * - */ - private boolean readQuotedString(int quote) throws IOException - { - for (int c = getChar(); c != EOF_CHAR; c = getChar()) { - addToString(c); - if (c == quote) return true; - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return false; - } - - /** - * - */ - private boolean readXmlComment() throws IOException - { - for (int c = getChar(); c != EOF_CHAR;) { - addToString(c); - if (c == '-' && peekChar() == '-') { - c = getChar(); - addToString(c); - if (peekChar() == '>') { - c = getChar(); // Skip > - addToString(c); - return true; - } else { - continue; - } - } - c = getChar(); - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return false; - } - - /** - * - */ - private boolean readCDATA() throws IOException - { - for (int c = getChar(); c != EOF_CHAR;) { - addToString(c); - if (c == ']' && peekChar() == ']') { - c = getChar(); - addToString(c); - if (peekChar() == '>') { - c = getChar(); // Skip > - addToString(c); - return true; - } else { - continue; - } - } - c = getChar(); - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return false; - } - - /** - * - */ - private boolean readEntity() throws IOException - { - int declTags = 1; - for (int c = getChar(); c != EOF_CHAR; c = getChar()) { - addToString(c); - switch (c) { - case '<': - declTags++; - break; - case '>': - declTags--; - if (declTags == 0) return true; - break; - } - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return false; - } - - /** - * - */ - private boolean readPI() throws IOException - { - for (int c = getChar(); c != EOF_CHAR; c = getChar()) { - addToString(c); - if (c == '?' && peekChar() == '>') { - c = getChar(); // Skip > - addToString(c); - return true; - } - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return false; - } - - private String getStringFromBuffer() - { - return new String(stringBuffer, 0, stringBufferTop); - } - - private void addToString(int c) - { - int N = stringBufferTop; - if (N == stringBuffer.length) { - char[] tmp = new char[stringBuffer.length * 2]; - System.arraycopy(stringBuffer, 0, tmp, 0, N); - stringBuffer = tmp; - } - stringBuffer[N] = (char)c; - stringBufferTop = N + 1; - } - - private void ungetChar(int c) - { - // can not unread past across line boundary - if (ungetCursor != 0 && ungetBuffer[ungetCursor - 1] == '\n') - Kit.codeBug(); - ungetBuffer[ungetCursor++] = c; - } - - private boolean matchChar(int test) throws IOException - { - int c = getChar(); - if (c == test) { - return true; - } else { - ungetChar(c); - return false; - } - } - - private int peekChar() throws IOException - { - int c = getChar(); - ungetChar(c); - return c; - } - - private int getChar() throws IOException - { - if (ungetCursor != 0) { - return ungetBuffer[--ungetCursor]; - } - - for(;;) { - int c; - if (sourceString != null) { - if (sourceCursor == sourceEnd) { - hitEOF = true; - return EOF_CHAR; - } - c = sourceString.charAt(sourceCursor++); - } else { - if (sourceCursor == sourceEnd) { - if (!fillSourceBuffer()) { - hitEOF = true; - return EOF_CHAR; - } - } - c = sourceBuffer[sourceCursor++]; - } - - if (lineEndChar >= 0) { - if (lineEndChar == '\r' && c == '\n') { - lineEndChar = '\n'; - continue; - } - lineEndChar = -1; - lineStart = sourceCursor - 1; - lineno++; - } - - if (c <= 127) { - if (c == '\n' || c == '\r') { - lineEndChar = c; - c = '\n'; - } - } else { - if (isJSFormatChar(c)) { - continue; - } - if (ScriptRuntime.isJSLineTerminator(c)) { - lineEndChar = c; - c = '\n'; - } - } - return c; - } - } - - private void skipLine() throws IOException - { - // skip to end of line - int c; - while ((c = getChar()) != EOF_CHAR && c != '\n') { } - ungetChar(c); - } - - final int getOffset() - { - int n = sourceCursor - lineStart; - if (lineEndChar >= 0) { --n; } - return n; - } - - final String getLine() - { - if (sourceString != null) { - // String case - int lineEnd = sourceCursor; - if (lineEndChar >= 0) { - --lineEnd; - } else { - for (; lineEnd != sourceEnd; ++lineEnd) { - int c = sourceString.charAt(lineEnd); - if (ScriptRuntime.isJSLineTerminator(c)) { - break; - } - } - } - return sourceString.substring(lineStart, lineEnd); - } else { - // Reader case - int lineLength = sourceCursor - lineStart; - if (lineEndChar >= 0) { - --lineLength; - } else { - // Read until the end of line - for (;; ++lineLength) { - int i = lineStart + lineLength; - if (i == sourceEnd) { - try { - if (!fillSourceBuffer()) { break; } - } catch (IOException ioe) { - // ignore it, we're already displaying an error... - break; - } - // i recalculuation as fillSourceBuffer can move saved - // line buffer and change lineStart - i = lineStart + lineLength; - } - int c = sourceBuffer[i]; - if (ScriptRuntime.isJSLineTerminator(c)) { - break; - } - } - } - return new String(sourceBuffer, lineStart, lineLength); - } - } - - private boolean fillSourceBuffer() throws IOException - { - if (sourceString != null) Kit.codeBug(); - if (sourceEnd == sourceBuffer.length) { - if (lineStart != 0) { - System.arraycopy(sourceBuffer, lineStart, sourceBuffer, 0, - sourceEnd - lineStart); - sourceEnd -= lineStart; - sourceCursor -= lineStart; - lineStart = 0; - } else { - char[] tmp = new char[sourceBuffer.length * 2]; - System.arraycopy(sourceBuffer, 0, tmp, 0, sourceEnd); - sourceBuffer = tmp; - } - } - int n = sourceReader.read(sourceBuffer, sourceEnd, - sourceBuffer.length - sourceEnd); - if (n < 0) { - return false; - } - sourceEnd += n; - return true; - } - - // stuff other than whitespace since start of line - private boolean dirtyLine; - - String regExpFlags; - - // Set this to an inital non-null value so that the Parser has - // something to retrieve even if an error has occured and no - // string is found. Fosters one class of error, but saves lots of - // code. - private String string = ""; - private double number; - - private char[] stringBuffer = new char[128]; - private int stringBufferTop; - private ObjToIntMap allStrings = new ObjToIntMap(50); - - // Room to backtrace from to < on failed match of the last - in <!-- - private final int[] ungetBuffer = new int[3]; - private int ungetCursor; - - private boolean hitEOF = false; - - private int lineStart = 0; - private int lineno; - private int lineEndChar = -1; - - private String sourceString; - private Reader sourceReader; - private char[] sourceBuffer; - private int sourceEnd; - private int sourceCursor; - - // for xml tokenizer - private boolean xmlIsAttribute; - private boolean xmlIsTagContent; - private int xmlOpenTagsCount; - - private Parser parser; - - /*APPJET*//* added method */ - private boolean tryReadTripleQuotedString() throws IOException { - // have to be kind of clever, because we don't want to - // add to the overhead of tokenizing, but there are constraints - // like "once you've gotten a newline and put it back (ungotten it), - // you can't put anything else back" - - // have seen one quote - int c = getChar(); - if (c != '"') { ungetChar(c); return false; } - // have seen two quotes - c = getChar(); - if (c != '"') { - ungetChar(c); - this.string = (String)allStrings.intern(""); - return true; - } - // have seen three quotes - - final boolean newPolicy = false; - - stringBufferTop = 0; - - boolean afterBackslash = false; - boolean done = false; - while (! done) { - c = getChar(); - if (c == EOF_CHAR) { - ungetChar(c); - throw parser.reportError("msg.unterminated.mstring.appjet"); - } - if (c == '"') { - int quoteCount = 0; - int quoteLimit = 3; - if (newPolicy && ! afterBackslash) - quoteLimit = 5; - while (c == '"' && quoteCount < quoteLimit) { - quoteCount++; - c = getChar(); - } - ungetChar(c); - - if (afterBackslash) { - if (quoteCount < 3) addToString('\\'); - } - else if (quoteCount >= 3) { - quoteCount -= 3; - done = true; - } - - while (quoteCount > 0) { - addToString('"'); quoteCount--; - } - afterBackslash = false; - } - else { - if (afterBackslash) { - addToString('\\'); - afterBackslash = false; - } - if (c == '\\') { - afterBackslash = true; - } - else { - addToString(c); - } - } - } - - String str = getStringFromBuffer(); - this.string = (String)allStrings.intern(str); - - return true; - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/UintMap.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/UintMap.java deleted file mode 100644 index 0027819..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/UintMap.java +++ /dev/null @@ -1,659 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Serializable; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -/** - * Map to associate non-negative integers to objects or integers. - * The map does not synchronize any of its operation, so either use - * it from a single thread or do own synchronization or perform all mutation - * operations on one thread before passing the map to others. - * - * @author Igor Bukanov - * - */ - -public class UintMap implements Serializable -{ - static final long serialVersionUID = 4242698212885848444L; - -// Map implementation via hashtable, -// follows "The Art of Computer Programming" by Donald E. Knuth - - public UintMap() { - this(4); - } - - public UintMap(int initialCapacity) { - if (initialCapacity < 0) Kit.codeBug(); - // Table grow when number of stored keys >= 3/4 of max capacity - int minimalCapacity = initialCapacity * 4 / 3; - int i; - for (i = 2; (1 << i) < minimalCapacity; ++i) { } - power = i; - if (check && power < 2) Kit.codeBug(); - } - - public boolean isEmpty() { - return keyCount == 0; - } - - public int size() { - return keyCount; - } - - public boolean has(int key) { - if (key < 0) Kit.codeBug(); - return 0 <= findIndex(key); - } - - /** - * Get object value assigned with key. - * @return key object value or null if key is absent - */ - public Object getObject(int key) { - if (key < 0) Kit.codeBug(); - if (values != null) { - int index = findIndex(key); - if (0 <= index) { - return values[index]; - } - } - return null; - } - - /** - * Get integer value assigned with key. - * @return key integer value or defaultValue if key is absent - */ - public int getInt(int key, int defaultValue) { - if (key < 0) Kit.codeBug(); - int index = findIndex(key); - if (0 <= index) { - if (ivaluesShift != 0) { - return keys[ivaluesShift + index]; - } - return 0; - } - return defaultValue; - } - - /** - * Get integer value assigned with key. - * @return key integer value or defaultValue if key does not exist or does - * not have int value - * @throws RuntimeException if key does not exist - */ - public int getExistingInt(int key) { - if (key < 0) Kit.codeBug(); - int index = findIndex(key); - if (0 <= index) { - if (ivaluesShift != 0) { - return keys[ivaluesShift + index]; - } - return 0; - } - // Key must exist - Kit.codeBug(); - return 0; - } - - /** - * Set object value of the key. - * If key does not exist, also set its int value to 0. - */ - public void put(int key, Object value) { - if (key < 0) Kit.codeBug(); - int index = ensureIndex(key, false); - if (values == null) { - values = new Object[1 << power]; - } - values[index] = value; - } - - /** - * Set int value of the key. - * If key does not exist, also set its object value to null. - */ - public void put(int key, int value) { - if (key < 0) Kit.codeBug(); - int index = ensureIndex(key, true); - if (ivaluesShift == 0) { - int N = 1 << power; - // keys.length can be N * 2 after clear which set ivaluesShift to 0 - if (keys.length != N * 2) { - int[] tmp = new int[N * 2]; - System.arraycopy(keys, 0, tmp, 0, N); - keys = tmp; - } - ivaluesShift = N; - } - keys[ivaluesShift + index] = value; - } - - public void remove(int key) { - if (key < 0) Kit.codeBug(); - int index = findIndex(key); - if (0 <= index) { - keys[index] = DELETED; - --keyCount; - // Allow to GC value and make sure that new key with the deleted - // slot shall get proper default values - if (values != null) { values[index] = null; } - if (ivaluesShift != 0) { keys[ivaluesShift + index] = 0; } - } - } - - public void clear() { - int N = 1 << power; - if (keys != null) { - for (int i = 0; i != N; ++i) { - keys[i] = EMPTY; - } - if (values != null) { - for (int i = 0; i != N; ++i) { - values[i] = null; - } - } - } - ivaluesShift = 0; - keyCount = 0; - occupiedCount = 0; - } - - /** Return array of present keys */ - public int[] getKeys() { - int[] keys = this.keys; - int n = keyCount; - int[] result = new int[n]; - for (int i = 0; n != 0; ++i) { - int entry = keys[i]; - if (entry != EMPTY && entry != DELETED) { - result[--n] = entry; - } - } - return result; - } - - private static int tableLookupStep(int fraction, int mask, int power) { - int shift = 32 - 2 * power; - if (shift >= 0) { - return ((fraction >>> shift) & mask) | 1; - } - else { - return (fraction & (mask >>> -shift)) | 1; - } - } - - private int findIndex(int key) { - int[] keys = this.keys; - if (keys != null) { - int fraction = key * A; - int index = fraction >>> (32 - power); - int entry = keys[index]; - if (entry == key) { return index; } - if (entry != EMPTY) { - // Search in table after first failed attempt - int mask = (1 << power) - 1; - int step = tableLookupStep(fraction, mask, power); - int n = 0; - do { - if (check) { - if (n >= occupiedCount) Kit.codeBug(); - ++n; - } - index = (index + step) & mask; - entry = keys[index]; - if (entry == key) { return index; } - } while (entry != EMPTY); - } - } - return -1; - } - -// Insert key that is not present to table without deleted entries -// and enough free space - private int insertNewKey(int key) { - if (check && occupiedCount != keyCount) Kit.codeBug(); - if (check && keyCount == 1 << power) Kit.codeBug(); - int[] keys = this.keys; - int fraction = key * A; - int index = fraction >>> (32 - power); - if (keys[index] != EMPTY) { - int mask = (1 << power) - 1; - int step = tableLookupStep(fraction, mask, power); - int firstIndex = index; - do { - if (check && keys[index] == DELETED) Kit.codeBug(); - index = (index + step) & mask; - if (check && firstIndex == index) Kit.codeBug(); - } while (keys[index] != EMPTY); - } - keys[index] = key; - ++occupiedCount; - ++keyCount; - return index; - } - - private void rehashTable(boolean ensureIntSpace) { - if (keys != null) { - // Check if removing deleted entries would free enough space - if (keyCount * 2 >= occupiedCount) { - // Need to grow: less then half of deleted entries - ++power; - } - } - int N = 1 << power; - int[] old = keys; - int oldShift = ivaluesShift; - if (oldShift == 0 && !ensureIntSpace) { - keys = new int[N]; - } - else { - ivaluesShift = N; keys = new int[N * 2]; - } - for (int i = 0; i != N; ++i) { keys[i] = EMPTY; } - - Object[] oldValues = values; - if (oldValues != null) { values = new Object[N]; } - - int oldCount = keyCount; - occupiedCount = 0; - if (oldCount != 0) { - keyCount = 0; - for (int i = 0, remaining = oldCount; remaining != 0; ++i) { - int key = old[i]; - if (key != EMPTY && key != DELETED) { - int index = insertNewKey(key); - if (oldValues != null) { - values[index] = oldValues[i]; - } - if (oldShift != 0) { - keys[ivaluesShift + index] = old[oldShift + i]; - } - --remaining; - } - } - } - } - -// Ensure key index creating one if necessary - private int ensureIndex(int key, boolean intType) { - int index = -1; - int firstDeleted = -1; - int[] keys = this.keys; - if (keys != null) { - int fraction = key * A; - index = fraction >>> (32 - power); - int entry = keys[index]; - if (entry == key) { return index; } - if (entry != EMPTY) { - if (entry == DELETED) { firstDeleted = index; } - // Search in table after first failed attempt - int mask = (1 << power) - 1; - int step = tableLookupStep(fraction, mask, power); - int n = 0; - do { - if (check) { - if (n >= occupiedCount) Kit.codeBug(); - ++n; - } - index = (index + step) & mask; - entry = keys[index]; - if (entry == key) { return index; } - if (entry == DELETED && firstDeleted < 0) { - firstDeleted = index; - } - } while (entry != EMPTY); - } - } - // Inserting of new key - if (check && keys != null && keys[index] != EMPTY) - Kit.codeBug(); - if (firstDeleted >= 0) { - index = firstDeleted; - } - else { - // Need to consume empty entry: check occupation level - if (keys == null || occupiedCount * 4 >= (1 << power) * 3) { - // Too litle unused entries: rehash - rehashTable(intType); - keys = this.keys; - return insertNewKey(key); - } - ++occupiedCount; - } - keys[index] = key; - ++keyCount; - return index; - } - - private void writeObject(ObjectOutputStream out) - throws IOException - { - out.defaultWriteObject(); - - int count = keyCount; - if (count != 0) { - boolean hasIntValues = (ivaluesShift != 0); - boolean hasObjectValues = (values != null); - out.writeBoolean(hasIntValues); - out.writeBoolean(hasObjectValues); - - for (int i = 0; count != 0; ++i) { - int key = keys[i]; - if (key != EMPTY && key != DELETED) { - --count; - out.writeInt(key); - if (hasIntValues) { - out.writeInt(keys[ivaluesShift + i]); - } - if (hasObjectValues) { - out.writeObject(values[i]); - } - } - } - } - } - - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - - int writtenKeyCount = keyCount; - if (writtenKeyCount != 0) { - keyCount = 0; - boolean hasIntValues = in.readBoolean(); - boolean hasObjectValues = in.readBoolean(); - - int N = 1 << power; - if (hasIntValues) { - keys = new int[2 * N]; - ivaluesShift = N; - }else { - keys = new int[N]; - } - for (int i = 0; i != N; ++i) { - keys[i] = EMPTY; - } - if (hasObjectValues) { - values = new Object[N]; - } - for (int i = 0; i != writtenKeyCount; ++i) { - int key = in.readInt(); - int index = insertNewKey(key); - if (hasIntValues) { - int ivalue = in.readInt(); - keys[ivaluesShift + index] = ivalue; - } - if (hasObjectValues) { - values[index] = in.readObject(); - } - } - } - } - -// A == golden_ratio * (1 << 32) = ((sqrt(5) - 1) / 2) * (1 << 32) -// See Knuth etc. - private static final int A = 0x9e3779b9; - - private static final int EMPTY = -1; - private static final int DELETED = -2; - -// Structure of kyes and values arrays (N == 1 << power): -// keys[0 <= i < N]: key value or EMPTY or DELETED mark -// values[0 <= i < N]: value of key at keys[i] -// keys[N <= i < 2N]: int values of keys at keys[i - N] - - private transient int[] keys; - private transient Object[] values; - - private int power; - private int keyCount; - private transient int occupiedCount; // == keyCount + deleted_count - - // If ivaluesShift != 0, keys[ivaluesShift + index] contains integer - // values associated with keys - private transient int ivaluesShift; - -// If true, enables consitency checks - private static final boolean check = false; - -/* TEST START - - public static void main(String[] args) { - if (!check) { - System.err.println("Set check to true and re-run"); - throw new RuntimeException("Set check to true and re-run"); - } - - UintMap map; - map = new UintMap(); - testHash(map, 2); - map = new UintMap(); - testHash(map, 10 * 1000); - map = new UintMap(30 * 1000); - testHash(map, 10 * 100); - map.clear(); - testHash(map, 4); - map = new UintMap(0); - testHash(map, 10 * 100); - } - - private static void testHash(UintMap map, int N) { - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - map.put(i, i); - check(i == map.getInt(i, -1)); - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - map.put(i, i); - check(i == map.getInt(i, -1)); - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - map.put(i, new Integer(i)); - check(-1 == map.getInt(i, -1)); - Integer obj = (Integer)map.getObject(i); - check(obj != null && i == obj.intValue()); - } - - check(map.size() == N); - - System.out.print("."); System.out.flush(); - int[] keys = map.getKeys(); - check(keys.length == N); - for (int i = 0; i != N; ++i) { - int key = keys[i]; - check(map.has(key)); - check(!map.isIntType(key)); - check(map.isObjectType(key)); - Integer obj = (Integer) map.getObject(key); - check(obj != null && key == obj.intValue()); - } - - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - check(-1 == map.getInt(i, -1)); - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - map.put(i * i, i); - check(i == map.getInt(i * i, -1)); - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - check(i == map.getInt(i * i, -1)); - } - - System.out.print("."); System.out.flush(); - for (int i = 0; i != N; ++i) { - map.put(i * i, new Integer(i)); - check(-1 == map.getInt(i * i, -1)); - map.remove(i * i); - check(!map.has(i * i)); - map.put(i * i, i); - check(map.isIntType(i * i)); - check(null == map.getObject(i * i)); - map.remove(i * i); - check(!map.isObjectType(i * i)); - check(!map.isIntType(i * i)); - } - - int old_size = map.size(); - for (int i = 0; i != N; ++i) { - map.remove(i * i); - check(map.size() == old_size); - } - - System.out.print("."); System.out.flush(); - map.clear(); - check(map.size() == 0); - for (int i = 0; i != N; ++i) { - map.put(i * i, i); - map.put(i * i + 1, new Double(i+0.5)); - } - checkSameMaps(map, (UintMap)writeAndRead(map)); - - System.out.print("."); System.out.flush(); - map = new UintMap(0); - checkSameMaps(map, (UintMap)writeAndRead(map)); - map = new UintMap(1); - checkSameMaps(map, (UintMap)writeAndRead(map)); - map = new UintMap(1000); - checkSameMaps(map, (UintMap)writeAndRead(map)); - - System.out.print("."); System.out.flush(); - map = new UintMap(N / 10); - for (int i = 0; i != N; ++i) { - map.put(2*i+1, i); - } - checkSameMaps(map, (UintMap)writeAndRead(map)); - - System.out.print("."); System.out.flush(); - map = new UintMap(N / 10); - for (int i = 0; i != N; ++i) { - map.put(2*i+1, i); - } - for (int i = 0; i != N / 2; ++i) { - map.remove(2*i+1); - } - checkSameMaps(map, (UintMap)writeAndRead(map)); - - System.out.print("."); System.out.flush(); - map = new UintMap(); - for (int i = 0; i != N; ++i) { - map.put(2*i+1, new Double(i + 10)); - } - for (int i = 0; i != N / 2; ++i) { - map.remove(2*i+1); - } - checkSameMaps(map, (UintMap)writeAndRead(map)); - - System.out.println(); System.out.flush(); - - } - - private static void checkSameMaps(UintMap map1, UintMap map2) { - check(map1.size() == map2.size()); - int[] keys = map1.getKeys(); - check(keys.length == map1.size()); - for (int i = 0; i != keys.length; ++i) { - int key = keys[i]; - check(map2.has(key)); - check(map1.isObjectType(key) == map2.isObjectType(key)); - check(map1.isIntType(key) == map2.isIntType(key)); - Object o1 = map1.getObject(key); - Object o2 = map2.getObject(key); - if (map1.isObjectType(key)) { - check(o1.equals(o2)); - }else { - check(map1.getObject(key) == null); - check(map2.getObject(key) == null); - } - if (map1.isIntType(key)) { - check(map1.getExistingInt(key) == map2.getExistingInt(key)); - }else { - check(map1.getInt(key, -10) == -10); - check(map1.getInt(key, -11) == -11); - check(map2.getInt(key, -10) == -10); - check(map2.getInt(key, -11) == -11); - } - } - } - - private static void check(boolean condition) { - if (!condition) Kit.codeBug(); - } - - private static Object writeAndRead(Object obj) { - try { - java.io.ByteArrayOutputStream - bos = new java.io.ByteArrayOutputStream(); - java.io.ObjectOutputStream - out = new java.io.ObjectOutputStream(bos); - out.writeObject(obj); - out.close(); - byte[] data = bos.toByteArray(); - java.io.ByteArrayInputStream - bis = new java.io.ByteArrayInputStream(data); - java.io.ObjectInputStream - in = new java.io.ObjectInputStream(bis); - Object result = in.readObject(); - in.close(); - return result; - }catch (Exception ex) { - ex.printStackTrace(); - throw new RuntimeException("Unexpected"); - } - } - -// TEST END */ -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Undefined.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Undefined.java deleted file mode 100644 index 472f26c..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Undefined.java +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Serializable; - -/** - * This class implements the Undefined value in JavaScript. - */ -public class Undefined implements Serializable -{ - static final long serialVersionUID = 9195680630202616767L; - - public static final Object instance = new Undefined(); - - private Undefined() - { - } - - public Object readResolve() - { - return instance; - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/UniqueTag.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/UniqueTag.java deleted file mode 100644 index 33f96eb..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/UniqueTag.java +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Serializable; - -/** - * Class instances represent serializable tags to mark special Object values. - * <p> - * Compatibility note: under jdk 1.1 use - * org.mozilla.javascript.serialize.ScriptableInputStream to read serialized - * instances of UniqueTag as under this JDK version the default - * ObjectInputStream would not restore them correctly as it lacks support - * for readResolve method - */ -public final class UniqueTag implements Serializable -{ - static final long serialVersionUID = -4320556826714577259L; - - private static final int ID_NOT_FOUND = 1; - private static final int ID_NULL_VALUE = 2; - private static final int ID_DOUBLE_MARK = 3; - - /** - * Tag to mark non-existing values. - */ - public static final UniqueTag - NOT_FOUND = new UniqueTag(ID_NOT_FOUND); - - /** - * Tag to distinguish between uninitialized and null values. - */ - public static final UniqueTag - NULL_VALUE = new UniqueTag(ID_NULL_VALUE); - - /** - * Tag to indicate that a object represents "double" with the real value - * stored somewhere else. - */ - public static final UniqueTag - DOUBLE_MARK = new UniqueTag(ID_DOUBLE_MARK); - - private final int tagId; - - private UniqueTag(int tagId) - { - this.tagId = tagId; - } - - public Object readResolve() - { - switch (tagId) { - case ID_NOT_FOUND: - return NOT_FOUND; - case ID_NULL_VALUE: - return NULL_VALUE; - case ID_DOUBLE_MARK: - return DOUBLE_MARK; - } - throw new IllegalStateException(String.valueOf(tagId)); - } - -// Overridden for better debug printouts - public String toString() - { - String name; - switch (tagId) { - case ID_NOT_FOUND: - name = "NOT_FOUND"; - break; - case ID_NULL_VALUE: - name = "NULL_VALUE"; - break; - case ID_DOUBLE_MARK: - name = "DOUBLE_MARK"; - break; - default: - throw Kit.codeBug(); - } - return super.toString()+": "+name; - } - -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/VMBridge.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/VMBridge.java deleted file mode 100644 index 5fba4a5..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/VMBridge.java +++ /dev/null @@ -1,183 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -import java.lang.reflect.Method; -import java.lang.reflect.Member; -import java.util.Iterator; - -public abstract class VMBridge -{ - - static final VMBridge instance = makeInstance(); - - private static VMBridge makeInstance() - { - String[] classNames = { - "org.mozilla.javascript.VMBridge_custom", - "org.mozilla.javascript.jdk15.VMBridge_jdk15", - "org.mozilla.javascript.jdk13.VMBridge_jdk13", - "org.mozilla.javascript.jdk11.VMBridge_jdk11", - }; - for (int i = 0; i != classNames.length; ++i) { - String className = classNames[i]; - Class cl = Kit.classOrNull(className); - if (cl != null) { - VMBridge bridge = (VMBridge)Kit.newInstanceOrNull(cl); - if (bridge != null) { - return bridge; - } - } - } - throw new IllegalStateException("Failed to create VMBridge instance"); - } - - /** - * Return a helper object to optimize {@link Context} access. - * <p> - * The runtime will pass the resulting helper object to the subsequent - * calls to {@link #getContext(Object contextHelper)} and - * {@link #setContext(Object contextHelper, Context cx)} methods. - * In this way the implementation can use the helper to cache - * information about current thread to make {@link Context} access faster. - */ - protected abstract Object getThreadContextHelper(); - - /** - * Get {@link Context} instance associated with the current thread - * or null if none. - * - * @param contextHelper The result of {@link #getThreadContextHelper()} - * called from the current thread. - */ - protected abstract Context getContext(Object contextHelper); - - /** - * Associate {@link Context} instance with the current thread or remove - * the current association if <tt>cx</tt> is null. - * - * @param contextHelper The result of {@link #getThreadContextHelper()} - * called from the current thread. - */ - protected abstract void setContext(Object contextHelper, Context cx); - - /** - * Return the ClassLoader instance associated with the current thread. - */ - protected abstract ClassLoader getCurrentThreadClassLoader(); - - /** - * In many JVMSs, public methods in private - * classes are not accessible by default (Sun Bug #4071593). - * VMBridge instance should try to workaround that via, for example, - * calling method.setAccessible(true) when it is available. - * The implementation is responsible to catch all possible exceptions - * like SecurityException if the workaround is not available. - * - * @return true if it was possible to make method accessible - * or false otherwise. - */ - protected abstract boolean tryToMakeAccessible(Object accessibleObject); - - /** - * Create helper object to create later proxies implementing the specified - * interfaces later. Under JDK 1.3 the implementation can look like: - * <pre> - * return java.lang.reflect.Proxy.getProxyClass(..., interfaces). - * getConstructor(new Class[] { - * java.lang.reflect.InvocationHandler.class }); - * </pre> - * - * @param interfaces Array with one or more interface class objects. - */ - protected Object getInterfaceProxyHelper(ContextFactory cf, - Class[] interfaces) - { - throw Context.reportRuntimeError( - "VMBridge.getInterfaceProxyHelper is not supported"); - } - - /** - * Create proxy object for {@link InterfaceAdapter}. The proxy should call - * {@link InterfaceAdapter#invoke(ContextFactory cf, - * Object target, - * Scriptable topScope, - * Method method, - * Object[] args)} - * as implementation of interface methods associated with - * <tt>proxyHelper</tt>. - * - * @param proxyHelper The result of the previous call to - * {@link #getInterfaceProxyHelper(ContextFactory, Class[])}. - */ - protected Object newInterfaceProxy(Object proxyHelper, - ContextFactory cf, - InterfaceAdapter adapter, - Object target, - Scriptable topScope) - { - throw Context.reportRuntimeError( - "VMBridge.newInterfaceProxy is not supported"); - } - - /** - * Returns whether or not a given member (method or constructor) - * has variable arguments. - * Variable argument methods have only been supported in Java since - * JDK 1.5. - */ - protected abstract boolean isVarArgs(Member member); - - /** - * If "obj" is a java.util.Iterator or a java.lang.Iterable, return a - * wrapping as a JavaScript Iterator. Otherwise, return null. - * This method is in VMBridge since Iterable is a JDK 1.5 addition. - */ - public Iterator getJavaIterator(Context cx, Scriptable scope, Object obj) { - if (obj instanceof Wrapper) { - Object unwrapped = ((Wrapper) obj).unwrap(); - Iterator iterator = null; - if (unwrapped instanceof Iterator) - iterator = (Iterator) unwrapped; - return iterator; - } - return null; - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/WrapFactory.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/WrapFactory.java deleted file mode 100644 index 3edc203..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/WrapFactory.java +++ /dev/null @@ -1,183 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * Embeddings that wish to provide their own custom wrappings for Java - * objects may extend this class and call - * {@link Context#setWrapFactory(WrapFactory)} - * Once an instance of this class or an extension of this class is enabled - * for a given context (by calling setWrapFactory on that context), Rhino - * will call the methods of this class whenever it needs to wrap a value - * resulting from a call to a Java method or an access to a Java field. - * - * @see org.mozilla.javascript.Context#setWrapFactory(WrapFactory) - * @since 1.5 Release 4 - */ -public class WrapFactory -{ - /** - * Wrap the object. - * <p> - * The value returned must be one of - * <UL> - * <LI>java.lang.Boolean</LI> - * <LI>java.lang.String</LI> - * <LI>java.lang.Number</LI> - * <LI>org.mozilla.javascript.Scriptable objects</LI> - * <LI>The value returned by Context.getUndefinedValue()</LI> - * <LI>null</LI> - * </UL> - * @param cx the current Context for this thread - * @param scope the scope of the executing script - * @param obj the object to be wrapped. Note it can be null. - * @param staticType type hint. If security restrictions prevent to wrap - object based on its class, staticType will be used instead. - * @return the wrapped value. - */ - public Object wrap(Context cx, Scriptable scope, - Object obj, Class staticType) - { - if (obj == null || obj == Undefined.instance - || obj instanceof Scriptable) - { - return obj; - } - if (staticType != null && staticType.isPrimitive()) { - if (staticType == Void.TYPE) - return Undefined.instance; - if (staticType == Character.TYPE) - return new Integer(((Character) obj).charValue()); - return obj; - } - if (!isJavaPrimitiveWrap()) { - if (obj instanceof String || obj instanceof Number - || obj instanceof Boolean) - { - return obj; - } else if (obj instanceof Character) { - return String.valueOf(((Character)obj).charValue()); - } - } - Class cls = obj.getClass(); - if (cls.isArray()) { - return NativeJavaArray.wrap(scope, obj); - } - return wrapAsJavaObject(cx, scope, obj, staticType); - } - - /** - * Wrap an object newly created by a constructor call. - * @param cx the current Context for this thread - * @param scope the scope of the executing script - * @param obj the object to be wrapped - * @return the wrapped value. - */ - public Scriptable wrapNewObject(Context cx, Scriptable scope, Object obj) - { - if (obj instanceof Scriptable) { - return (Scriptable)obj; - } - Class cls = obj.getClass(); - if (cls.isArray()) { - return NativeJavaArray.wrap(scope, obj); - } - return wrapAsJavaObject(cx, scope, obj, null); - } - - /** - * Wrap Java object as Scriptable instance to allow full access to its - * methods and fields from JavaScript. - * <p> - * {@link #wrap(Context, Scriptable, Object, Class)} and - * {@link #wrapNewObject(Context, Scriptable, Object)} call this method - * when they can not convert <tt>javaObject</tt> to JavaScript primitive - * value or JavaScript array. - * <p> - * Subclasses can override the method to provide custom wrappers - * for Java objects. - * @param cx the current Context for this thread - * @param scope the scope of the executing script - * @param javaObject the object to be wrapped - * @param staticType type hint. If security restrictions prevent to wrap - object based on its class, staticType will be used instead. - * @return the wrapped value which shall not be null - */ - public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, - Object javaObject, Class staticType) - { - Scriptable wrap; - wrap = new NativeJavaObject(scope, javaObject, staticType); - return wrap; - } - - /** - * Return <code>false</code> if result of Java method, which is instance of - * <code>String</code>, <code>Number</code>, <code>Boolean</code> and - * <code>Character</code>, should be used directly as JavaScript primitive - * type. - * By default the method returns true to indicate that instances of - * <code>String</code>, <code>Number</code>, <code>Boolean</code> and - * <code>Character</code> should be wrapped as any other Java object and - * scripts can access any Java method available in these objects. - * Use {@link #setJavaPrimitiveWrap(boolean)} to change this. - */ - public final boolean isJavaPrimitiveWrap() - { - return javaPrimitiveWrap; - } - - /** - * @see #isJavaPrimitiveWrap() - */ - public final void setJavaPrimitiveWrap(boolean value) - { - Context cx = Context.getCurrentContext(); - if (cx != null && cx.isSealed()) { - Context.onSealedMutation(); - } - javaPrimitiveWrap = value; - } - - private boolean javaPrimitiveWrap = true; - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/WrappedException.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/WrappedException.java deleted file mode 100644 index c749f74..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/WrappedException.java +++ /dev/null @@ -1,93 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * A wrapper for runtime exceptions. - * - * Used by the JavaScript runtime to wrap and propagate exceptions that occur - * during runtime. - * - * @author Norris Boyd - */ -public class WrappedException extends EvaluatorException -{ - static final long serialVersionUID = -1551979216966520648L; - - /** - * @see Context#throwAsScriptRuntimeEx(Throwable e) - */ - public WrappedException(Throwable exception) - { - super("Wrapped "+exception.toString()); - this.exception = exception; - Kit.initCause(this, exception); - - int[] linep = { 0 }; - String sourceName = Context.getSourcePositionFromStack(linep); - int lineNumber = linep[0]; - if (sourceName != null) { - initSourceName(sourceName); - } - if (lineNumber != 0) { - initLineNumber(lineNumber); - } - } - - /** - * Get the wrapped exception. - * - * @return the exception that was presented as a argument to the - * constructor when this object was created - */ - public Throwable getWrappedException() - { - return exception; - } - - /** - * @deprecated Use {@link #getWrappedException()} instead. - */ - public Object unwrap() - { - return getWrappedException(); - } - - private Throwable exception; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Wrapper.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Wrapper.java deleted file mode 100644 index cb2d2f5..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/Wrapper.java +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript; - -/** - * Objects that can wrap other values for reflection in the JS environment - * will implement Wrapper. - * - * Wrapper defines a single method that can be called to unwrap the object. - */ - -public interface Wrapper { - - /** - * Unwrap the object by returning the wrapped value. - * - * @return a wrapped value - */ - public Object unwrap(); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/continuations/Continuation.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/continuations/Continuation.java deleted file mode 100644 index c6d3966..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/continuations/Continuation.java +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.continuations; - -import org.mozilla.javascript.*; - -public final class Continuation extends IdScriptableObject implements Function -{ - static final long serialVersionUID = 1794167133757605367L; - - private static final Object FTAG = new Object(); - - private Object implementation; - - public static void init(Context cx, Scriptable scope, boolean sealed) - { - Continuation obj = new Continuation(); - obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); - } - - public Object getImplementation() - { - return implementation; - } - - public void initImplementation(Object implementation) - { - this.implementation = implementation; - } - - public String getClassName() - { - return "Continuation"; - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) - { - throw Context.reportRuntimeError("Direct call is not supported"); - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - return Interpreter.restartContinuation(this, cx, scope, args); - } - - public static boolean isContinuationConstructor(IdFunctionObject f) - { - if (f.hasTag(FTAG) && f.methodId() == Id_constructor) { - return true; - } - return false; - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_constructor: arity=0; s="constructor"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(FTAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(FTAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case Id_constructor: - throw Context.reportRuntimeError("Direct call is not supported"); - } - throw new IllegalArgumentException(String.valueOf(id)); - } - -// #string_id_map# - - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:16:40 EDT - L0: { id = 0; String X = null; - if (s.length()==11) { X="constructor";id=Id_constructor; } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_constructor = 1, - MAX_PROTOTYPE_ID = 1; - -// #/string_id_map# -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/DebugFrame.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/DebugFrame.java deleted file mode 100644 index ef15710..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/DebugFrame.java +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript.debug; - -import org.mozilla.javascript.Context; -import org.mozilla.javascript.Scriptable; - -/** -Interface to implement if the application is interested in receiving debug -information during execution of a particular script or function. -*/ -public interface DebugFrame { - -/** -Called when execution is ready to start bytecode interpretation for entered a particular function or script. - -@param cx current Context for this thread -@param activation the activation scope for the function or script. -@param thisObj value of the JavaScript <code>this</code> object -@param args the array of arguments -*/ - public void onEnter(Context cx, Scriptable activation, - Scriptable thisObj, Object[] args); -/** -Called when executed code reaches new line in the source. -@param cx current Context for this thread -@param lineNumber current line number in the script source -*/ - public void onLineChange(Context cx, int lineNumber); - -/** -Called when thrown exception is handled by the function or script. -@param cx current Context for this thread -@param ex exception object -*/ - public void onExceptionThrown(Context cx, Throwable ex); - -/** -Called when the function or script for this frame is about to return. -@param cx current Context for this thread -@param byThrow if true function will leave by throwing exception, otherwise it - will execute normal return -@param resultOrException function result in case of normal return or - exception object if about to throw exception -*/ - public void onExit(Context cx, boolean byThrow, Object resultOrException); - -/** -Called when the function or script executes a 'debugger' statement. -@param cx current Context for this thread -*/ - public void onDebuggerStatement(Context cx); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/DebuggableObject.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/DebuggableObject.java deleted file mode 100644 index 23e7421..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/DebuggableObject.java +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript.debug; - -/** - * This interface exposes debugging information from objects. - */ -public interface DebuggableObject { - - /** - * Returns an array of ids for the properties of the object. - * - * <p>All properties, even those with attribute {DontEnum}, are listed. - * This allows the debugger to display all properties of the object.<p> - * - * @return an array of java.lang.Objects with an entry for every - * listed property. Properties accessed via an integer index will - * have a corresponding - * Integer entry in the returned array. Properties accessed by - * a String will have a String entry in the returned array. - */ - public Object[] getAllIds(); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/DebuggableScript.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/DebuggableScript.java deleted file mode 100644 index 705e442..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/DebuggableScript.java +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript.debug; - -/** - * This interface exposes debugging information from executable - * code (either functions or top-level scripts). - */ -public interface DebuggableScript -{ - public boolean isTopLevel(); - - /** - * Returns true if this is a function, false if it is a script. - */ - public boolean isFunction(); - - /** - * Get name of the function described by this script. - * Return null or an empty string if this script is not a function. - */ - public String getFunctionName(); - - /** - * Get number of declared parameters in the function. - * Return 0 if this script is not a function. - * - * @see #getParamAndVarCount() - * @see #getParamOrVarName(int index) - */ - public int getParamCount(); - - /** - * Get number of declared parameters and local variables. - * Return number of declared global variables if this script is not a - * function. - * - * @see #getParamCount() - * @see #getParamOrVarName(int index) - */ - public int getParamAndVarCount(); - - /** - * Get name of a declared parameter or local variable. - * <tt>index</tt> should be less then {@link #getParamAndVarCount()}. - * If <tt>index < {@link #getParamCount()}</tt>, return - * the name of the corresponding parameter, otherwise return the name - * of variable. - * If this script is not function, return the name of the declared - * global variable. - */ - public String getParamOrVarName(int index); - - /** - * Get the name of the source (usually filename or URL) - * of the script. - */ - public String getSourceName(); - - /** - * Returns true if this script or function were runtime-generated - * from JavaScript using <tt>eval</tt> function or <tt>Function</tt> - * or <tt>Script</tt> constructors. - */ - public boolean isGeneratedScript(); - - /** - * Get array containing the line numbers that - * that can be passed to <code>DebugFrame.onLineChange()<code>. - * Note that line order in the resulting array is arbitrary - */ - public int[] getLineNumbers(); - - public int getFunctionCount(); - - public DebuggableScript getFunction(int index); - - public DebuggableScript getParent(); - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/Debugger.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/Debugger.java deleted file mode 100644 index bfac153..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/debug/Debugger.java +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript.debug; - -import org.mozilla.javascript.Context; - -/** -Interface to implement if the application is interested in receiving debug -information. -*/ -public interface Debugger { - -/** -Called when compilation of a particular function or script into internal -bytecode is done. - -@param cx current Context for this thread -@param fnOrScript object describing the function or script -@param source the function or script source -*/ - void handleCompilationDone(Context cx, DebuggableScript fnOrScript, - String source); - -/** -Called when execution entered a particular function or script. - -@return implementation of DebugFrame which receives debug information during - the function or script execution or null otherwise -*/ - DebugFrame getFrame(Context cx, DebuggableScript fnOrScript); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/jdk11/VMBridge_jdk11.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/jdk11/VMBridge_jdk11.java deleted file mode 100644 index f5d1522..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/jdk11/VMBridge_jdk11.java +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.jdk11; - -import java.lang.reflect.Member; -import java.util.Hashtable; - -import org.mozilla.javascript.*; - -public class VMBridge_jdk11 extends VMBridge -{ - private Hashtable threadsWithContext = new Hashtable(); - - protected Object getThreadContextHelper() - { - return Thread.currentThread(); - } - - protected Context getContext(Object contextHelper) - { - Thread t = (Thread)contextHelper; - return (Context)threadsWithContext.get(t); - } - - protected void setContext(Object contextHelper, Context cx) - { - Thread t = (Thread)contextHelper; - if (cx == null) { - // Allow to garbage collect thread reference - threadsWithContext.remove(t); - } else { - threadsWithContext.put(t, cx); - } - } - - protected ClassLoader getCurrentThreadClassLoader() - { - return null; - } - - protected boolean tryToMakeAccessible(Object accessibleObject) - { - return false; - } - - protected boolean isVarArgs(Member member) { - return false; - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/jdk13/VMBridge_jdk13.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/jdk13/VMBridge_jdk13.java deleted file mode 100644 index c33e9b4..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/jdk13/VMBridge_jdk13.java +++ /dev/null @@ -1,157 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.jdk13; - -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Member; -import java.lang.reflect.Proxy; - -import org.mozilla.javascript.*; - -public class VMBridge_jdk13 extends VMBridge -{ - private ThreadLocal contextLocal = new ThreadLocal(); - - protected Object getThreadContextHelper() - { - // To make subsequent batch calls to getContext/setContext faster - // associate permanently one element array with contextLocal - // so getContext/setContext would need just to read/write the first - // array element. - // Note that it is necessary to use Object[], not Context[] to allow - // garbage collection of Rhino classes. For details see comments - // by Attila Szegedi in - // https://bugzilla.mozilla.org/show_bug.cgi?id=281067#c5 - - Object[] storage = (Object[])contextLocal.get(); - if (storage == null) { - storage = new Object[1]; - contextLocal.set(storage); - } - return storage; - } - - protected Context getContext(Object contextHelper) - { - Object[] storage = (Object[])contextHelper; - return (Context)storage[0]; - } - - protected void setContext(Object contextHelper, Context cx) - { - Object[] storage = (Object[])contextHelper; - storage[0] = cx; - } - - protected ClassLoader getCurrentThreadClassLoader() - { - return Thread.currentThread().getContextClassLoader(); - } - - protected boolean tryToMakeAccessible(Object accessibleObject) - { - if (!(accessibleObject instanceof AccessibleObject)) { - return false; - } - AccessibleObject accessible = (AccessibleObject)accessibleObject; - if (accessible.isAccessible()) { - return true; - } - try { - accessible.setAccessible(true); - } catch (Exception ex) { } - - return accessible.isAccessible(); - } - - protected Object getInterfaceProxyHelper(ContextFactory cf, - Class[] interfaces) - { - // XXX: How to handle interfaces array withclasses from different - // class loaders? Using cf.getApplicationClassLoader() ? - ClassLoader loader = interfaces[0].getClassLoader(); - Class cl = Proxy.getProxyClass(loader, interfaces); - Constructor c; - try { - c = cl.getConstructor(new Class[] { InvocationHandler.class }); - } catch (NoSuchMethodException ex) { - // Should not happen - throw Kit.initCause(new IllegalStateException(), ex); - } - return c; - } - - protected Object newInterfaceProxy(Object proxyHelper, - final ContextFactory cf, - final InterfaceAdapter adapter, - final Object target, - final Scriptable topScope) - { - Constructor c = (Constructor)proxyHelper; - - InvocationHandler handler = new InvocationHandler() { - public Object invoke(Object proxy, - Method method, - Object[] args) - { - return adapter.invoke(cf, target, topScope, method, args); - } - }; - Object proxy; - try { - proxy = c.newInstance(new Object[] { handler }); - } catch (InvocationTargetException ex) { - throw Context.throwAsScriptRuntimeEx(ex); - } catch (IllegalAccessException ex) { - // Shouls not happen - throw Kit.initCause(new IllegalStateException(), ex); - } catch (InstantiationException ex) { - // Shouls not happen - throw Kit.initCause(new IllegalStateException(), ex); - } - return proxy; - } - - protected boolean isVarArgs(Member member) { - return false; - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/jdk15/VMBridge_jdk15.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/jdk15/VMBridge_jdk15.java deleted file mode 100644 index 0ffaf9d..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/jdk15/VMBridge_jdk15.java +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.jdk15; - -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Constructor; -import java.util.Iterator; -import org.mozilla.javascript.*; - -public class VMBridge_jdk15 extends org.mozilla.javascript.jdk13.VMBridge_jdk13 -{ - public VMBridge_jdk15() throws SecurityException, InstantiationException { - try { - // Just try and see if we can access the isVarArgs method. - // We want to fail loading if the method does not exist - // so that we can load a bridge to an older JDK instead. - Method.class.getMethod("isVarArgs", (Class[]) null); - } catch (NoSuchMethodException e) { - // Throw a fitting exception that is handled by - // org.mozilla.javascript.Kit.newInstanceOrNull: - throw new InstantiationException(e.getMessage()); - } - } - - public boolean isVarArgs(Member member) { - if (member instanceof Method) - return ((Method) member).isVarArgs(); - else if (member instanceof Constructor) - return ((Constructor) member).isVarArgs(); - else - return false; - } - - /** - * If "obj" is a java.util.Iterator or a java.lang.Iterable, return a - * wrapping as a JavaScript Iterator. Otherwise, return null. - * This method is in VMBridge since Iterable is a JDK 1.5 addition. - */ - public Iterator getJavaIterator(Context cx, Scriptable scope, Object obj) { - if (obj instanceof Wrapper) { - Object unwrapped = ((Wrapper) obj).unwrap(); - Iterator iterator = null; - if (unwrapped instanceof Iterator) - iterator = (Iterator) unwrapped; - if (unwrapped instanceof Iterable) - iterator = ((Iterable)unwrapped).iterator(); - return iterator; - } - return null; - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/Block.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/Block.java deleted file mode 100644 index bd56714..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/Block.java +++ /dev/null @@ -1,615 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.optimizer; - -import org.mozilla.javascript.*; - -import java.util.Hashtable; - -import java.io.PrintWriter; -import java.io.StringWriter; - -class Block -{ - - private static class FatBlock - { - - private static Block[] reduceToArray(ObjToIntMap map) - { - Block[] result = null; - if (!map.isEmpty()) { - result = new Block[map.size()]; - int i = 0; - ObjToIntMap.Iterator iter = map.newIterator(); - for (iter.start(); !iter.done(); iter.next()) { - FatBlock fb = (FatBlock)(iter.getKey()); - result[i++] = fb.realBlock; - } - } - return result; - } - - void addSuccessor(FatBlock b) { successors.put(b, 0); } - void addPredecessor(FatBlock b) { predecessors.put(b, 0); } - - Block[] getSuccessors() { return reduceToArray(successors); } - Block[] getPredecessors() { return reduceToArray(predecessors); } - - // all the Blocks that come immediately after this - private ObjToIntMap successors = new ObjToIntMap(); - // all the Blocks that come immediately before this - private ObjToIntMap predecessors = new ObjToIntMap(); - - Block realBlock; - } - - Block(int startNodeIndex, int endNodeIndex) - { - itsStartNodeIndex = startNodeIndex; - itsEndNodeIndex = endNodeIndex; - } - - static void runFlowAnalyzes(OptFunctionNode fn, Node[] statementNodes) - { - int paramCount = fn.fnode.getParamCount(); - int varCount = fn.fnode.getParamAndVarCount(); - int[] varTypes = new int[varCount]; - // If the variable is a parameter, it could have any type. - for (int i = 0; i != paramCount; ++i) { - varTypes[i] = Optimizer.AnyType; - } - // If the variable is from a "var" statement, its typeEvent will be set - // when we see the setVar node. - for (int i = paramCount; i != varCount; ++i) { - varTypes[i] = Optimizer.NoType; - } - - Block[] theBlocks = buildBlocks(statementNodes); - - if (DEBUG) { - ++debug_blockCount; - System.out.println("-------------------"+fn.fnode.getFunctionName()+" "+debug_blockCount+"--------"); - System.out.println(toString(theBlocks, statementNodes)); - } - - reachingDefDataFlow(fn, statementNodes, theBlocks, varTypes); - typeFlow(fn, statementNodes, theBlocks, varTypes); - - if (DEBUG) { - for (int i = 0; i < theBlocks.length; i++) { - System.out.println("For block " + theBlocks[i].itsBlockID); - theBlocks[i].printLiveOnEntrySet(fn); - } - System.out.println("Variable Table, size = " + varCount); - for (int i = 0; i != varCount; i++) { - System.out.println("["+i+"] type: "+varTypes[i]); - } - } - - for (int i = paramCount; i != varCount; i++) { - if (varTypes[i] == Optimizer.NumberType) { - fn.setIsNumberVar(i); - } - } - - } - - private static Block[] buildBlocks(Node[] statementNodes) - { - // a mapping from each target node to the block it begins - Hashtable theTargetBlocks = new Hashtable(); - ObjArray theBlocks = new ObjArray(); - - // there's a block that starts at index 0 - int beginNodeIndex = 0; - - for (int i = 0; i < statementNodes.length; i++) { - switch (statementNodes[i].getType()) { - case Token.TARGET : - { - if (i != beginNodeIndex) { - FatBlock fb = newFatBlock(beginNodeIndex, i - 1); - if (statementNodes[beginNodeIndex].getType() - == Token.TARGET) - theTargetBlocks.put(statementNodes[beginNodeIndex], fb); - theBlocks.add(fb); - // start the next block at this node - beginNodeIndex = i; - } - } - break; - case Token.IFNE : - case Token.IFEQ : - case Token.GOTO : - { - FatBlock fb = newFatBlock(beginNodeIndex, i); - if (statementNodes[beginNodeIndex].getType() - == Token.TARGET) - theTargetBlocks.put(statementNodes[beginNodeIndex], fb); - theBlocks.add(fb); - // start the next block at the next node - beginNodeIndex = i + 1; - } - break; - } - } - - if (beginNodeIndex != statementNodes.length) { - FatBlock fb = newFatBlock(beginNodeIndex, statementNodes.length - 1); - if (statementNodes[beginNodeIndex].getType() == Token.TARGET) - theTargetBlocks.put(statementNodes[beginNodeIndex], fb); - theBlocks.add(fb); - } - - // build successor and predecessor links - - for (int i = 0; i < theBlocks.size(); i++) { - FatBlock fb = (FatBlock)(theBlocks.get(i)); - - Node blockEndNode = statementNodes[fb.realBlock.itsEndNodeIndex]; - int blockEndNodeType = blockEndNode.getType(); - - if ((blockEndNodeType != Token.GOTO) - && (i < (theBlocks.size() - 1))) { - FatBlock fallThruTarget = (FatBlock)(theBlocks.get(i + 1)); - fb.addSuccessor(fallThruTarget); - fallThruTarget.addPredecessor(fb); - } - - - if ( (blockEndNodeType == Token.IFNE) - || (blockEndNodeType == Token.IFEQ) - || (blockEndNodeType == Token.GOTO) ) { - Node target = ((Node.Jump)blockEndNode).target; - FatBlock branchTargetBlock - = (FatBlock)(theTargetBlocks.get(target)); - target.putProp(Node.TARGETBLOCK_PROP, - branchTargetBlock.realBlock); - fb.addSuccessor(branchTargetBlock); - branchTargetBlock.addPredecessor(fb); - } - } - - Block[] result = new Block[theBlocks.size()]; - - for (int i = 0; i < theBlocks.size(); i++) { - FatBlock fb = (FatBlock)(theBlocks.get(i)); - Block b = fb.realBlock; - b.itsSuccessors = fb.getSuccessors(); - b.itsPredecessors = fb.getPredecessors(); - b.itsBlockID = i; - result[i] = b; - } - - return result; - } - - private static FatBlock newFatBlock(int startNodeIndex, int endNodeIndex) - { - FatBlock fb = new FatBlock(); - fb.realBlock = new Block(startNodeIndex, endNodeIndex); - return fb; - } - - private static String toString(Block[] blockList, Node[] statementNodes) - { - if (!DEBUG) return null; - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - - pw.println(blockList.length + " Blocks"); - for (int i = 0; i < blockList.length; i++) { - Block b = blockList[i]; - pw.println("#" + b.itsBlockID); - pw.println("from " + b.itsStartNodeIndex - + " " - + statementNodes[b.itsStartNodeIndex].toString()); - pw.println("thru " + b.itsEndNodeIndex - + " " - + statementNodes[b.itsEndNodeIndex].toString()); - pw.print("Predecessors "); - if (b.itsPredecessors != null) { - for (int j = 0; j < b.itsPredecessors.length; j++) - pw.print(b.itsPredecessors[j].itsBlockID + " "); - pw.println(); - } - else - pw.println("none"); - pw.print("Successors "); - if (b.itsSuccessors != null) { - for (int j = 0; j < b.itsSuccessors.length; j++) - pw.print(b.itsSuccessors[j].itsBlockID + " "); - pw.println(); - } - else - pw.println("none"); - } - return sw.toString(); - } - - private static void reachingDefDataFlow(OptFunctionNode fn, Node[] statementNodes, Block theBlocks[], int[] varTypes) - { -/* - initialize the liveOnEntry and liveOnExit sets, then discover the variables - that are def'd by each function, and those that are used before being def'd - (hence liveOnEntry) -*/ - for (int i = 0; i < theBlocks.length; i++) { - theBlocks[i].initLiveOnEntrySets(fn, statementNodes); - } -/* - this visits every block starting at the last, re-adding the predecessors of - any block whose inputs change as a result of the dataflow. - REMIND, better would be to visit in CFG postorder -*/ - boolean visit[] = new boolean[theBlocks.length]; - boolean doneOnce[] = new boolean[theBlocks.length]; - int vIndex = theBlocks.length - 1; - boolean needRescan = false; - visit[vIndex] = true; - while (true) { - if (visit[vIndex] || !doneOnce[vIndex]) { - doneOnce[vIndex] = true; - visit[vIndex] = false; - if (theBlocks[vIndex].doReachedUseDataFlow()) { - Block pred[] = theBlocks[vIndex].itsPredecessors; - if (pred != null) { - for (int i = 0; i < pred.length; i++) { - int index = pred[i].itsBlockID; - visit[index] = true; - needRescan |= (index > vIndex); - } - } - } - } - if (vIndex == 0) { - if (needRescan) { - vIndex = theBlocks.length - 1; - needRescan = false; - } - else - break; - } - else - vIndex--; - } -/* - if any variable is live on entry to block 0, we have to mark it as - not jRegable - since it means that someone is trying to access the - 'undefined'-ness of that variable. -*/ - - theBlocks[0].markAnyTypeVariables(varTypes); - } - - private static void typeFlow(OptFunctionNode fn, Node[] statementNodes, Block theBlocks[], int[] varTypes) - { - boolean visit[] = new boolean[theBlocks.length]; - boolean doneOnce[] = new boolean[theBlocks.length]; - int vIndex = 0; - boolean needRescan = false; - visit[vIndex] = true; - while (true) { - if (visit[vIndex] || !doneOnce[vIndex]) { - doneOnce[vIndex] = true; - visit[vIndex] = false; - if (theBlocks[vIndex].doTypeFlow(fn, statementNodes, varTypes)) - { - Block succ[] = theBlocks[vIndex].itsSuccessors; - if (succ != null) { - for (int i = 0; i < succ.length; i++) { - int index = succ[i].itsBlockID; - visit[index] = true; - needRescan |= (index < vIndex); - } - } - } - } - if (vIndex == (theBlocks.length - 1)) { - if (needRescan) { - vIndex = 0; - needRescan = false; - } - else - break; - } - else - vIndex++; - } - } - - private static boolean assignType(int[] varTypes, int index, int type) - { - return type != (varTypes[index] |= type); - } - - private void markAnyTypeVariables(int[] varTypes) - { - for (int i = 0; i != varTypes.length; i++) { - if (itsLiveOnEntrySet.test(i)) { - assignType(varTypes, i, Optimizer.AnyType); - } - } - - } - - /* - We're tracking uses and defs - in order to - build the def set and to identify the last use - nodes. - - The itsNotDefSet is built reversed then flipped later. - - */ - private void lookForVariableAccess(OptFunctionNode fn, Node n) - { - switch (n.getType()) { - case Token.DEC : - case Token.INC : - { - Node child = n.getFirstChild(); - if (child.getType() == Token.GETVAR) { - int varIndex = fn.getVarIndex(child); - if (!itsNotDefSet.test(varIndex)) - itsUseBeforeDefSet.set(varIndex); - itsNotDefSet.set(varIndex); - } - } - break; - case Token.SETVAR : - { - Node lhs = n.getFirstChild(); - Node rhs = lhs.getNext(); - lookForVariableAccess(fn, rhs); - itsNotDefSet.set(fn.getVarIndex(n)); - } - break; - case Token.GETVAR : - { - int varIndex = fn.getVarIndex(n); - if (!itsNotDefSet.test(varIndex)) - itsUseBeforeDefSet.set(varIndex); - } - break; - default : - Node child = n.getFirstChild(); - while (child != null) { - lookForVariableAccess(fn, child); - child = child.getNext(); - } - break; - } - } - - /* - build the live on entry/exit sets. - Then walk the trees looking for defs/uses of variables - and build the def and useBeforeDef sets. - */ - private void initLiveOnEntrySets(OptFunctionNode fn, Node[] statementNodes) - { - int listLength = fn.getVarCount(); - itsUseBeforeDefSet = new DataFlowBitSet(listLength); - itsNotDefSet = new DataFlowBitSet(listLength); - itsLiveOnEntrySet = new DataFlowBitSet(listLength); - itsLiveOnExitSet = new DataFlowBitSet(listLength); - for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) { - Node n = statementNodes[i]; - lookForVariableAccess(fn, n); - } - itsNotDefSet.not(); // truth in advertising - } - - /* - the liveOnEntry of each successor is the liveOnExit for this block. - The liveOnEntry for this block is - - liveOnEntry = liveOnExit - defsInThisBlock + useBeforeDefsInThisBlock - - */ - private boolean doReachedUseDataFlow() - { - itsLiveOnExitSet.clear(); - if (itsSuccessors != null) - for (int i = 0; i < itsSuccessors.length; i++) - itsLiveOnExitSet.or(itsSuccessors[i].itsLiveOnEntrySet); - return itsLiveOnEntrySet.df2(itsLiveOnExitSet, - itsUseBeforeDefSet, itsNotDefSet); - } - - /* - the type of an expression is relatively unknown. Cases we can be sure - about are - - Literals, - Arithmetic operations - always return a Number - */ - private static int findExpressionType(OptFunctionNode fn, Node n, - int[] varTypes) - { - switch (n.getType()) { - case Token.NUMBER : - return Optimizer.NumberType; - - case Token.CALL : - case Token.NEW : - case Token.REF_CALL : - return Optimizer.AnyType; - - case Token.GETELEM : - return Optimizer.AnyType; - - case Token.GETVAR : - return varTypes[fn.getVarIndex(n)]; - - case Token.INC : - case Token.DEC : - case Token.DIV: - case Token.MOD: - case Token.BITOR: - case Token.BITXOR: - case Token.BITAND: - case Token.LSH: - case Token.RSH: - case Token.URSH: - case Token.SUB : - return Optimizer.NumberType; - - case Token.ARRAYLIT: - case Token.OBJECTLIT: - return Optimizer.AnyType; // XXX: actually, we know it's not - // number, but no type yet for that - - case Token.ADD : { - // if the lhs & rhs are known to be numbers, we can be sure that's - // the result, otherwise it could be a string. - Node child = n.getFirstChild(); - int lType = findExpressionType(fn, child, varTypes); - int rType = findExpressionType(fn, child.getNext(), varTypes); - return lType | rType; // we're not distinguishing strings yet - } - } - - Node child = n.getFirstChild(); - if (child == null) { - return Optimizer.AnyType; - } else { - int result = Optimizer.NoType; - while (child != null) { - result |= findExpressionType(fn, child, varTypes); - child = child.getNext(); - } - return result; - } - } - - private static boolean findDefPoints(OptFunctionNode fn, Node n, - int[] varTypes) - { - boolean result = false; - Node child = n.getFirstChild(); - switch (n.getType()) { - default : - while (child != null) { - result |= findDefPoints(fn, child, varTypes); - child = child.getNext(); - } - break; - case Token.DEC : - case Token.INC : - if (child.getType() == Token.GETVAR) { - // theVar is a Number now - int i = fn.getVarIndex(child); - result |= assignType(varTypes, i, Optimizer.NumberType); - } - break; - case Token.SETPROP : - case Token.SETPROP_OP : - if (child.getType() == Token.GETVAR) { - int i = fn.getVarIndex(child); - assignType(varTypes, i, Optimizer.AnyType); - } - while (child != null) { - result |= findDefPoints(fn, child, varTypes); - child = child.getNext(); - } - break; - case Token.SETVAR : { - Node rValue = child.getNext(); - int theType = findExpressionType(fn, rValue, varTypes); - int i = fn.getVarIndex(n); - result |= assignType(varTypes, i, theType); - break; - } - } - return result; - } - - private boolean doTypeFlow(OptFunctionNode fn, Node[] statementNodes, - int[] varTypes) - { - boolean changed = false; - - for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) { - Node n = statementNodes[i]; - if (n != null) - changed |= findDefPoints(fn, n, varTypes); - } - - return changed; - } - - private void printLiveOnEntrySet(OptFunctionNode fn) - { - if (DEBUG) { - for (int i = 0; i < fn.getVarCount(); i++) { - String name = fn.fnode.getParamOrVarName(i); - if (itsUseBeforeDefSet.test(i)) - System.out.println(name + " is used before def'd"); - if (itsNotDefSet.test(i)) - System.out.println(name + " is not def'd"); - if (itsLiveOnEntrySet.test(i)) - System.out.println(name + " is live on entry"); - if (itsLiveOnExitSet.test(i)) - System.out.println(name + " is live on exit"); - } - } - } - - // all the Blocks that come immediately after this - private Block[] itsSuccessors; - // all the Blocks that come immediately before this - private Block[] itsPredecessors; - - private int itsStartNodeIndex; // the Node at the start of the block - private int itsEndNodeIndex; // the Node at the end of the block - - private int itsBlockID; // a unique index for each block - -// reaching def bit sets - - private DataFlowBitSet itsLiveOnEntrySet; - private DataFlowBitSet itsLiveOnExitSet; - private DataFlowBitSet itsUseBeforeDefSet; - private DataFlowBitSet itsNotDefSet; - - static final boolean DEBUG = false; - private static int debug_blockCount; - -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/ClassCompiler.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/ClassCompiler.java deleted file mode 100644 index 4a69c6a..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/ClassCompiler.java +++ /dev/null @@ -1,214 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.optimizer; - -import org.mozilla.javascript.*; - -/** - * Generates class files from script sources. - * - * since 1.5 Release 5 - * @author Igor Bukanov - */ - -public class ClassCompiler -{ - /** - * Construct ClassCompiler that uses the specified compiler environment - * when generating classes. - */ - public ClassCompiler(CompilerEnvirons compilerEnv) - { - if (compilerEnv == null) throw new IllegalArgumentException(); - this.compilerEnv = compilerEnv; - this.mainMethodClassName = Codegen.DEFAULT_MAIN_METHOD_CLASS; - } - - /** - * Set the class name to use for main method implementation. - * The class must have a method matching - * <tt>public static void main(Script sc, String[] args)</tt>, it will be - * called when <tt>main(String[] args)</tt> is called in the generated - * class. The class name should be fully qulified name and include the - * package name like in <tt>org.foo.Bar<tt>. - */ - public void setMainMethodClass(String className) - { - // XXX Should this check for a valid class name? - mainMethodClassName = className; - } - - /** - * Get the name of the class for main method implementation. - * @see #setMainMethodClass(String) - */ - public String getMainMethodClass() - { - return mainMethodClassName; - } - - /** - * Get the compiler environment the compiler uses. - */ - public CompilerEnvirons getCompilerEnv() - { - return compilerEnv; - } - - /** - * Get the class that the generated target will extend. - */ - public Class getTargetExtends() - { - return targetExtends; - } - - /** - * Set the class that the generated target will extend. - * - * @param extendsClass the class it extends - */ - public void setTargetExtends(Class extendsClass) - { - targetExtends = extendsClass; - } - - /** - * Get the interfaces that the generated target will implement. - */ - public Class[] getTargetImplements() - { - return targetImplements == null ? null : (Class[])targetImplements.clone(); - } - - /** - * Set the interfaces that the generated target will implement. - * - * @param implementsClasses an array of Class objects, one for each - * interface the target will extend - */ - public void setTargetImplements(Class[] implementsClasses) - { - targetImplements = implementsClasses == null ? null : (Class[])implementsClasses.clone(); - } - - /** - * Build class name for a auxiliary class generated by compiler. - * If the compiler needs to generate extra classes beyond the main class, - * it will call this function to build the auxiliary class name. - * The default implementation simply appends auxMarker to mainClassName - * but this can be overridden. - */ - protected String makeAuxiliaryClassName(String mainClassName, - String auxMarker) - { - return mainClassName+auxMarker; - } - - /** - * Compile JavaScript source into one or more Java class files. - * The first compiled class will have name mainClassName. - * If the results of {@link #getTargetExtends()} or - * {@link #getTargetImplements()} are not null, then the first compiled - * class will extend the specified super class and implement - * specified interfaces. - * - * @return array where elements with even indexes specifies class name - * and the following odd index gives class file body as byte[] - * array. The initial element of the array always holds - * mainClassName and array[1] holds its byte code. - */ - public Object[] compileToClassFiles(String source, - String sourceLocation, - int lineno, - String mainClassName) - { - /*APPJET*/ - Parser p = - InformativeParser.makeParser(compilerEnv, - compilerEnv.getErrorReporter()); - ScriptOrFnNode tree = p.parse(source, sourceLocation, lineno); - String encodedSource = p.getEncodedSource(); - - Class superClass = getTargetExtends(); - Class[] interfaces = getTargetImplements(); - String scriptClassName; - boolean isPrimary = (interfaces == null && superClass == null); - if (isPrimary) { - scriptClassName = mainClassName; - } else { - scriptClassName = makeAuxiliaryClassName(mainClassName, "1"); - } - - Codegen codegen = new Codegen(); - codegen.setMainMethodClass(mainMethodClassName); - byte[] scriptClassBytes - = codegen.compileToClassFile(compilerEnv, scriptClassName, - tree, encodedSource, - false); - - if (isPrimary) { - return new Object[] { scriptClassName, scriptClassBytes }; - } - int functionCount = tree.getFunctionCount(); - ObjToIntMap functionNames = new ObjToIntMap(functionCount); - for (int i = 0; i != functionCount; ++i) { - FunctionNode ofn = tree.getFunctionNode(i); - String name = ofn.getFunctionName(); - if (name != null && name.length() != 0) { - functionNames.put(name, ofn.getParamCount()); - } - } - if (superClass == null) { - superClass = ScriptRuntime.ObjectClass; - } - byte[] mainClassBytes - = JavaAdapter.createAdapterCode( - functionNames, mainClassName, - superClass, interfaces, scriptClassName); - - return new Object[] { mainClassName, mainClassBytes, - scriptClassName, scriptClassBytes }; - } - - private String mainMethodClassName; - private CompilerEnvirons compilerEnv; - private Class targetExtends; - private Class[] targetImplements; - -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/Codegen.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/Codegen.java deleted file mode 100644 index 64952bf..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/Codegen.java +++ /dev/null @@ -1,5031 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Kemal Bayram - * Igor Bukanov - * Bob Jervis - * Roger Lawrence - * Andi Vajda - * Hannes Wallnoefer - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - - -package org.mozilla.javascript.optimizer; - -import org.mozilla.javascript.*; -import org.mozilla.classfile.*; -import java.util.*; -import java.lang.reflect.Constructor; -import java.util.Hashtable; - -/** - * This class generates code for a given IR tree. - * - * @author Norris Boyd - * @author Roger Lawrence - */ - -public class Codegen implements Evaluator -{ - public void captureStackInfo(RhinoException ex) { - throw new UnsupportedOperationException(); - } - - public String getSourcePositionFromStack(Context cx, int[] linep) { - throw new UnsupportedOperationException(); - } - - public String getPatchedStack(RhinoException ex, String nativeStackTrace) { - throw new UnsupportedOperationException(); - } - - public List getScriptStack(RhinoException ex) { - throw new UnsupportedOperationException(); - } - - public void setEvalScriptFlag(Script script) { - throw new UnsupportedOperationException(); - } - - public Object compile(CompilerEnvirons compilerEnv, - ScriptOrFnNode tree, - String encodedSource, - boolean returnFunction) - { - int serial; - synchronized (globalLock) { - serial = ++globalSerialClassCounter; - } - String mainClassName = "org.mozilla.javascript.gen.c"+serial; - - byte[] mainClassBytes = compileToClassFile(compilerEnv, mainClassName, - tree, encodedSource, - returnFunction); - - return new Object[] { mainClassName, mainClassBytes }; - } - - public Script createScriptObject(Object bytecode, - Object staticSecurityDomain) - { - Class cl = defineClass(bytecode, staticSecurityDomain); - - Script script; - try { - script = (Script)cl.newInstance(); - } catch (Exception ex) { - throw new RuntimeException - ("Unable to instantiate compiled class:"+ex.toString()); - } - return script; - } - - public Function createFunctionObject(Context cx, Scriptable scope, - Object bytecode, - Object staticSecurityDomain) - { - Class cl = defineClass(bytecode, staticSecurityDomain); - - NativeFunction f; - try { - Constructor ctor = cl.getConstructors()[0]; - Object[] initArgs = { scope, cx, new Integer(0) }; - f = (NativeFunction)ctor.newInstance(initArgs); - } catch (Exception ex) { - throw new RuntimeException - ("Unable to instantiate compiled class:"+ex.toString()); - } - return f; - } - - private Class defineClass(Object bytecode, - Object staticSecurityDomain) - { - Object[] nameBytesPair = (Object[])bytecode; - String className = (String)nameBytesPair[0]; - byte[] classBytes = (byte[])nameBytesPair[1]; - - // The generated classes in this case refer only to Rhino classes - // which must be accessible through this class loader - ClassLoader rhinoLoader = getClass().getClassLoader(); - GeneratedClassLoader loader; - loader = SecurityController.createLoader(rhinoLoader, - staticSecurityDomain); - Exception e; - try { - Class cl = loader.defineClass(className, classBytes); - loader.linkClass(cl); - return cl; - } catch (SecurityException x) { - e = x; - } catch (IllegalArgumentException x) { - e = x; - } - throw new RuntimeException("Malformed optimizer package " + e); - } - - byte[] compileToClassFile(CompilerEnvirons compilerEnv, - String mainClassName, - ScriptOrFnNode scriptOrFn, - String encodedSource, - boolean returnFunction) - { - this.compilerEnv = compilerEnv; - - transform(scriptOrFn); - - if (Token.printTrees) { - /*APPJET*///System.out.println(scriptOrFn.toStringTree(scriptOrFn)); - } - - if (returnFunction) { - scriptOrFn = scriptOrFn.getFunctionNode(0); - } - - initScriptOrFnNodesData(scriptOrFn); - - this.mainClassName = mainClassName; - this.mainClassSignature - = ClassFileWriter.classNameToSignature(mainClassName); - - try { - return generateCode(encodedSource); - } catch (ClassFileWriter.ClassFileFormatException e) { - throw reportClassFileFormatException(scriptOrFn, e.getMessage()); - } - } - - private RuntimeException reportClassFileFormatException( - ScriptOrFnNode scriptOrFn, - String message) - { - String msg = scriptOrFn instanceof FunctionNode - ? ScriptRuntime.getMessage2("msg.while.compiling.fn", - ((FunctionNode)scriptOrFn).getFunctionName(), message) - : ScriptRuntime.getMessage1("msg.while.compiling.script", message); - return Context.reportRuntimeError(msg, scriptOrFn.getSourceName(), - scriptOrFn.getLineno(), null, 0); - } - - private void transform(ScriptOrFnNode tree) - { - initOptFunctions_r(tree); - - int optLevel = compilerEnv.getOptimizationLevel(); - - Hashtable possibleDirectCalls = null; - if (optLevel > 0) { - /* - * Collect all of the contained functions into a hashtable - * so that the call optimizer can access the class name & parameter - * count for any call it encounters - */ - if (tree.getType() == Token.SCRIPT) { - int functionCount = tree.getFunctionCount(); - for (int i = 0; i != functionCount; ++i) { - OptFunctionNode ofn = OptFunctionNode.get(tree, i); - if (ofn.fnode.getFunctionType() - == FunctionNode.FUNCTION_STATEMENT) - { - String name = ofn.fnode.getFunctionName(); - if (name.length() != 0) { - if (possibleDirectCalls == null) { - possibleDirectCalls = new Hashtable(); - } - possibleDirectCalls.put(name, ofn); - } - } - } - } - } - - if (possibleDirectCalls != null) { - directCallTargets = new ObjArray(); - } - - OptTransformer ot = new OptTransformer(possibleDirectCalls, - directCallTargets); - ot.transform(tree); - - if (optLevel > 0) { - (new Optimizer()).optimize(tree); - } - } - - private static void initOptFunctions_r(ScriptOrFnNode scriptOrFn) - { - for (int i = 0, N = scriptOrFn.getFunctionCount(); i != N; ++i) { - FunctionNode fn = scriptOrFn.getFunctionNode(i); - new OptFunctionNode(fn); - initOptFunctions_r(fn); - } - } - - private void initScriptOrFnNodesData(ScriptOrFnNode scriptOrFn) - { - ObjArray x = new ObjArray(); - collectScriptOrFnNodes_r(scriptOrFn, x); - - int count = x.size(); - scriptOrFnNodes = new ScriptOrFnNode[count]; - x.toArray(scriptOrFnNodes); - - scriptOrFnIndexes = new ObjToIntMap(count); - for (int i = 0; i != count; ++i) { - scriptOrFnIndexes.put(scriptOrFnNodes[i], i); - } - } - - private static void collectScriptOrFnNodes_r(ScriptOrFnNode n, - ObjArray x) - { - x.add(n); - int nestedCount = n.getFunctionCount(); - for (int i = 0; i != nestedCount; ++i) { - collectScriptOrFnNodes_r(n.getFunctionNode(i), x); - } - } - - private byte[] generateCode(String encodedSource) - { - boolean hasScript = (scriptOrFnNodes[0].getType() == Token.SCRIPT); - boolean hasFunctions = (scriptOrFnNodes.length > 1 || !hasScript); - - String sourceFile = null; - if (compilerEnv.isGenerateDebugInfo()) { - sourceFile = scriptOrFnNodes[0].getSourceName(); - } - - ClassFileWriter cfw = new ClassFileWriter(mainClassName, - SUPER_CLASS_NAME, - sourceFile); - cfw.addField(ID_FIELD_NAME, "I", - ClassFileWriter.ACC_PRIVATE); - cfw.addField(DIRECT_CALL_PARENT_FIELD, mainClassSignature, - ClassFileWriter.ACC_PRIVATE); - cfw.addField(REGEXP_ARRAY_FIELD_NAME, REGEXP_ARRAY_FIELD_TYPE, - ClassFileWriter.ACC_PRIVATE); - - if (hasFunctions) { - generateFunctionConstructor(cfw); - } - - if (hasScript) { - cfw.addInterface("org/mozilla/javascript/Script"); - generateScriptCtor(cfw); - generateMain(cfw); - generateExecute(cfw); - } - - generateCallMethod(cfw); - generateResumeGenerator(cfw); - - generateNativeFunctionOverrides(cfw, encodedSource); - - int count = scriptOrFnNodes.length; - for (int i = 0; i != count; ++i) { - ScriptOrFnNode n = scriptOrFnNodes[i]; - - BodyCodegen bodygen = new BodyCodegen(); - bodygen.cfw = cfw; - bodygen.codegen = this; - bodygen.compilerEnv = compilerEnv; - bodygen.scriptOrFn = n; - bodygen.scriptOrFnIndex = i; - - try { - bodygen.generateBodyCode(); - } catch (ClassFileWriter.ClassFileFormatException e) { - throw reportClassFileFormatException(n, e.getMessage()); - } - - if (n.getType() == Token.FUNCTION) { - OptFunctionNode ofn = OptFunctionNode.get(n); - generateFunctionInit(cfw, ofn); - if (ofn.isTargetOfDirectCall()) { - emitDirectConstructor(cfw, ofn); - } - } - } - - if (directCallTargets != null) { - int N = directCallTargets.size(); - for (int j = 0; j != N; ++j) { - cfw.addField(getDirectTargetFieldName(j), - mainClassSignature, - ClassFileWriter.ACC_PRIVATE); - } - } - - emitRegExpInit(cfw); - emitConstantDudeInitializers(cfw); - - return cfw.toByteArray(); - } - - private void emitDirectConstructor(ClassFileWriter cfw, - OptFunctionNode ofn) - { -/* - we generate .. - Scriptable directConstruct(<directCallArgs>) { - Scriptable newInstance = createObject(cx, scope); - Object val = <body-name>(cx, scope, newInstance, <directCallArgs>); - if (val instanceof Scriptable) { - return (Scriptable) val; - } - return newInstance; - } -*/ - cfw.startMethod(getDirectCtorName(ofn.fnode), - getBodyMethodSignature(ofn.fnode), - (short)(ClassFileWriter.ACC_STATIC - | ClassFileWriter.ACC_PRIVATE)); - - int argCount = ofn.fnode.getParamCount(); - int firstLocal = (4 + argCount * 3) + 1; - - cfw.addALoad(0); // this - cfw.addALoad(1); // cx - cfw.addALoad(2); // scope - cfw.addInvoke(ByteCode.INVOKEVIRTUAL, - "org/mozilla/javascript/BaseFunction", - "createObject", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(firstLocal); - - cfw.addALoad(0); - cfw.addALoad(1); - cfw.addALoad(2); - cfw.addALoad(firstLocal); - for (int i = 0; i < argCount; i++) { - cfw.addALoad(4 + (i * 3)); - cfw.addDLoad(5 + (i * 3)); - } - cfw.addALoad(4 + argCount * 3); - cfw.addInvoke(ByteCode.INVOKESTATIC, - mainClassName, - getBodyMethodName(ofn.fnode), - getBodyMethodSignature(ofn.fnode)); - int exitLabel = cfw.acquireLabel(); - cfw.add(ByteCode.DUP); // make a copy of direct call result - cfw.add(ByteCode.INSTANCEOF, "org/mozilla/javascript/Scriptable"); - cfw.add(ByteCode.IFEQ, exitLabel); - // cast direct call result - cfw.add(ByteCode.CHECKCAST, "org/mozilla/javascript/Scriptable"); - cfw.add(ByteCode.ARETURN); - cfw.markLabel(exitLabel); - - cfw.addALoad(firstLocal); - cfw.add(ByteCode.ARETURN); - - cfw.stopMethod((short)(firstLocal + 1)); - } - - static boolean isGenerator(ScriptOrFnNode node) - { - return (node.getType() == Token.FUNCTION ) && - ((FunctionNode)node).isGenerator(); - } - - // How dispatch to generators works: - // Two methods are generated corresponding to a user-written generator. - // One of these creates a generator object (NativeGenerator), which is - // returned to the user. The other method contains all of the body code - // of the generator. - // When a user calls a generator, the call() method dispatches control to - // to the method that creates the NativeGenerator object. Subsequently when - // the user invokes .next(), .send() or any such method on the generator - // object, the resumeGenerator() below dispatches the call to the - // method corresponding to the generator body. As a matter of convention - // the generator body is given the name of the generator activation function - // appended by "_gen". - private void generateResumeGenerator(ClassFileWriter cfw) - { - boolean hasGenerators = false; - for (int i=0; i < scriptOrFnNodes.length; i++) { - if (isGenerator(scriptOrFnNodes[i])) - hasGenerators = true; - } - - // if there are no generators defined, we don't implement a - // resumeGenerator(). The base class provides a default implementation. - if (!hasGenerators) - return; - - cfw.startMethod("resumeGenerator", - "(Lorg/mozilla/javascript/Context;" + - "Lorg/mozilla/javascript/Scriptable;" + - "ILjava/lang/Object;" + - "Ljava/lang/Object;)Ljava/lang/Object;", - (short)(ClassFileWriter.ACC_PUBLIC - | ClassFileWriter.ACC_FINAL)); - - // load arguments for dispatch to the corresponding *_gen method - cfw.addALoad(0); - cfw.addALoad(1); - cfw.addALoad(2); - cfw.addALoad(4); - cfw.addALoad(5); - cfw.addILoad(3); - - cfw.addLoadThis(); - cfw.add(ByteCode.GETFIELD, cfw.getClassName(), ID_FIELD_NAME, "I"); - - int startSwitch = cfw.addTableSwitch(0, scriptOrFnNodes.length - 1); - cfw.markTableSwitchDefault(startSwitch); - int endlabel = cfw.acquireLabel(); - - for (int i = 0; i < scriptOrFnNodes.length; i++) { - ScriptOrFnNode n = scriptOrFnNodes[i]; - cfw.markTableSwitchCase(startSwitch, i, (short)6); - if (isGenerator(n)) { - String type = "(" + - mainClassSignature + - "Lorg/mozilla/javascript/Context;" + - "Lorg/mozilla/javascript/Scriptable;" + - "Ljava/lang/Object;" + - "Ljava/lang/Object;I)Ljava/lang/Object;"; - cfw.addInvoke(ByteCode.INVOKESTATIC, - mainClassName, - getBodyMethodName(n) + "_gen", - type); - cfw.add(ByteCode.ARETURN); - } else { - cfw.add(ByteCode.GOTO, endlabel); - } - } - - cfw.markLabel(endlabel); - pushUndefined(cfw); - cfw.add(ByteCode.ARETURN); - - - // this method uses as many locals as there are arguments (hence 6) - cfw.stopMethod((short)6); - } - - private void generateCallMethod(ClassFileWriter cfw) - { - cfw.startMethod("call", - "(Lorg/mozilla/javascript/Context;" + - "Lorg/mozilla/javascript/Scriptable;" + - "Lorg/mozilla/javascript/Scriptable;" + - "[Ljava/lang/Object;)Ljava/lang/Object;", - (short)(ClassFileWriter.ACC_PUBLIC - | ClassFileWriter.ACC_FINAL)); - - // Generate code for: - // if (!ScriptRuntime.hasTopCall(cx)) { - // return ScriptRuntime.doTopCall(this, cx, scope, thisObj, args); - // } - - int nonTopCallLabel = cfw.acquireLabel(); - cfw.addALoad(1); //cx - cfw.addInvoke(ByteCode.INVOKESTATIC, - "org/mozilla/javascript/ScriptRuntime", - "hasTopCall", - "(Lorg/mozilla/javascript/Context;" - +")Z"); - cfw.add(ByteCode.IFNE, nonTopCallLabel); - cfw.addALoad(0); - cfw.addALoad(1); - cfw.addALoad(2); - cfw.addALoad(3); - cfw.addALoad(4); - cfw.addInvoke(ByteCode.INVOKESTATIC, - "org/mozilla/javascript/ScriptRuntime", - "doTopCall", - "(Lorg/mozilla/javascript/Callable;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +")Ljava/lang/Object;"); - cfw.add(ByteCode.ARETURN); - cfw.markLabel(nonTopCallLabel); - - // Now generate switch to call the real methods - cfw.addALoad(0); - cfw.addALoad(1); - cfw.addALoad(2); - cfw.addALoad(3); - cfw.addALoad(4); - - int end = scriptOrFnNodes.length; - boolean generateSwitch = (2 <= end); - - int switchStart = 0; - int switchStackTop = 0; - if (generateSwitch) { - cfw.addLoadThis(); - cfw.add(ByteCode.GETFIELD, cfw.getClassName(), ID_FIELD_NAME, "I"); - // do switch from (1, end - 1) mapping 0 to - // the default case - switchStart = cfw.addTableSwitch(1, end - 1); - } - - for (int i = 0; i != end; ++i) { - ScriptOrFnNode n = scriptOrFnNodes[i]; - if (generateSwitch) { - if (i == 0) { - cfw.markTableSwitchDefault(switchStart); - switchStackTop = cfw.getStackTop(); - } else { - cfw.markTableSwitchCase(switchStart, i - 1, - switchStackTop); - } - } - if (n.getType() == Token.FUNCTION) { - OptFunctionNode ofn = OptFunctionNode.get(n); - if (ofn.isTargetOfDirectCall()) { - int pcount = ofn.fnode.getParamCount(); - if (pcount != 0) { - // loop invariant: - // stack top == arguments array from addALoad4() - for (int p = 0; p != pcount; ++p) { - cfw.add(ByteCode.ARRAYLENGTH); - cfw.addPush(p); - int undefArg = cfw.acquireLabel(); - int beyond = cfw.acquireLabel(); - cfw.add(ByteCode.IF_ICMPLE, undefArg); - // get array[p] - cfw.addALoad(4); - cfw.addPush(p); - cfw.add(ByteCode.AALOAD); - cfw.add(ByteCode.GOTO, beyond); - cfw.markLabel(undefArg); - pushUndefined(cfw); - cfw.markLabel(beyond); - // Only one push - cfw.adjustStackTop(-1); - cfw.addPush(0.0); - // restore invariant - cfw.addALoad(4); - } - } - } - } - cfw.addInvoke(ByteCode.INVOKESTATIC, - mainClassName, - getBodyMethodName(n), - getBodyMethodSignature(n)); - cfw.add(ByteCode.ARETURN); - } - cfw.stopMethod((short)5); - // 5: this, cx, scope, js this, args[] - } - - private void generateMain(ClassFileWriter cfw) - { - cfw.startMethod("main", "([Ljava/lang/String;)V", - (short)(ClassFileWriter.ACC_PUBLIC - | ClassFileWriter.ACC_STATIC)); - - // load new ScriptImpl() - cfw.add(ByteCode.NEW, cfw.getClassName()); - cfw.add(ByteCode.DUP); - cfw.addInvoke(ByteCode.INVOKESPECIAL, cfw.getClassName(), - "<init>", "()V"); - // load 'args' - cfw.add(ByteCode.ALOAD_0); - // Call mainMethodClass.main(Script script, String[] args) - cfw.addInvoke(ByteCode.INVOKESTATIC, - mainMethodClass, - "main", - "(Lorg/mozilla/javascript/Script;[Ljava/lang/String;)V"); - cfw.add(ByteCode.RETURN); - // 1 = String[] args - cfw.stopMethod((short)1); - } - - private void generateExecute(ClassFileWriter cfw) - { - cfw.startMethod("exec", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;", - (short)(ClassFileWriter.ACC_PUBLIC - | ClassFileWriter.ACC_FINAL)); - - final int CONTEXT_ARG = 1; - final int SCOPE_ARG = 2; - - cfw.addLoadThis(); - cfw.addALoad(CONTEXT_ARG); - cfw.addALoad(SCOPE_ARG); - cfw.add(ByteCode.DUP); - cfw.add(ByteCode.ACONST_NULL); - cfw.addInvoke(ByteCode.INVOKEVIRTUAL, - cfw.getClassName(), - "call", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +")Ljava/lang/Object;"); - - cfw.add(ByteCode.ARETURN); - // 3 = this + context + scope - cfw.stopMethod((short)3); - } - - private void generateScriptCtor(ClassFileWriter cfw) - { - cfw.startMethod("<init>", "()V", ClassFileWriter.ACC_PUBLIC); - - cfw.addLoadThis(); - cfw.addInvoke(ByteCode.INVOKESPECIAL, SUPER_CLASS_NAME, - "<init>", "()V"); - // set id to 0 - cfw.addLoadThis(); - cfw.addPush(0); - cfw.add(ByteCode.PUTFIELD, cfw.getClassName(), ID_FIELD_NAME, "I"); - - cfw.add(ByteCode.RETURN); - // 1 parameter = this - cfw.stopMethod((short)1); - } - - private void generateFunctionConstructor(ClassFileWriter cfw) - { - final int SCOPE_ARG = 1; - final int CONTEXT_ARG = 2; - final int ID_ARG = 3; - - cfw.startMethod("<init>", FUNCTION_CONSTRUCTOR_SIGNATURE, - ClassFileWriter.ACC_PUBLIC); - cfw.addALoad(0); - cfw.addInvoke(ByteCode.INVOKESPECIAL, SUPER_CLASS_NAME, - "<init>", "()V"); - - cfw.addLoadThis(); - cfw.addILoad(ID_ARG); - cfw.add(ByteCode.PUTFIELD, cfw.getClassName(), ID_FIELD_NAME, "I"); - - cfw.addLoadThis(); - cfw.addALoad(CONTEXT_ARG); - cfw.addALoad(SCOPE_ARG); - - int start = (scriptOrFnNodes[0].getType() == Token.SCRIPT) ? 1 : 0; - int end = scriptOrFnNodes.length; - if (start == end) throw badTree(); - boolean generateSwitch = (2 <= end - start); - - int switchStart = 0; - int switchStackTop = 0; - if (generateSwitch) { - cfw.addILoad(ID_ARG); - // do switch from (start + 1, end - 1) mapping start to - // the default case - switchStart = cfw.addTableSwitch(start + 1, end - 1); - } - - for (int i = start; i != end; ++i) { - if (generateSwitch) { - if (i == start) { - cfw.markTableSwitchDefault(switchStart); - switchStackTop = cfw.getStackTop(); - } else { - cfw.markTableSwitchCase(switchStart, i - 1 - start, - switchStackTop); - } - } - OptFunctionNode ofn = OptFunctionNode.get(scriptOrFnNodes[i]); - cfw.addInvoke(ByteCode.INVOKEVIRTUAL, - mainClassName, - getFunctionInitMethodName(ofn), - FUNCTION_INIT_SIGNATURE); - cfw.add(ByteCode.RETURN); - } - - // 4 = this + scope + context + id - cfw.stopMethod((short)4); - } - - private void generateFunctionInit(ClassFileWriter cfw, - OptFunctionNode ofn) - { - final int CONTEXT_ARG = 1; - final int SCOPE_ARG = 2; - cfw.startMethod(getFunctionInitMethodName(ofn), - FUNCTION_INIT_SIGNATURE, - (short)(ClassFileWriter.ACC_PRIVATE - | ClassFileWriter.ACC_FINAL)); - - // Call NativeFunction.initScriptFunction - cfw.addLoadThis(); - cfw.addALoad(CONTEXT_ARG); - cfw.addALoad(SCOPE_ARG); - cfw.addInvoke(ByteCode.INVOKEVIRTUAL, - "org/mozilla/javascript/NativeFunction", - "initScriptFunction", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")V"); - - // precompile all regexp literals - int regexpCount = ofn.fnode.getRegexpCount(); - if (regexpCount != 0) { - cfw.addLoadThis(); - pushRegExpArray(cfw, ofn.fnode, CONTEXT_ARG, SCOPE_ARG); - cfw.add(ByteCode.PUTFIELD, mainClassName, - REGEXP_ARRAY_FIELD_NAME, REGEXP_ARRAY_FIELD_TYPE); - } - - cfw.add(ByteCode.RETURN); - // 3 = (scriptThis/functionRef) + scope + context - cfw.stopMethod((short)3); - } - - private void generateNativeFunctionOverrides(ClassFileWriter cfw, - String encodedSource) - { - // Override NativeFunction.getLanguageVersion() with - // public int getLanguageVersion() { return <version-constant>; } - - cfw.startMethod("getLanguageVersion", "()I", - ClassFileWriter.ACC_PUBLIC); - - cfw.addPush(compilerEnv.getLanguageVersion()); - cfw.add(ByteCode.IRETURN); - - // 1: this and no argument or locals - cfw.stopMethod((short)1); - - // The rest of NativeFunction overrides require specific code for each - // script/function id - - final int Do_getFunctionName = 0; - final int Do_getParamCount = 1; - final int Do_getParamAndVarCount = 2; - final int Do_getParamOrVarName = 3; - final int Do_getEncodedSource = 4; - final int Do_getParamOrVarConst = 5; - final int SWITCH_COUNT = 6; - - for (int methodIndex = 0; methodIndex != SWITCH_COUNT; ++methodIndex) { - if (methodIndex == Do_getEncodedSource && encodedSource == null) { - continue; - } - - // Generate: - // prologue; - // switch over function id to implement function-specific action - // epilogue - - short methodLocals; - switch (methodIndex) { - case Do_getFunctionName: - methodLocals = 1; // Only this - cfw.startMethod("getFunctionName", "()Ljava/lang/String;", - ClassFileWriter.ACC_PUBLIC); - break; - case Do_getParamCount: - methodLocals = 1; // Only this - cfw.startMethod("getParamCount", "()I", - ClassFileWriter.ACC_PUBLIC); - break; - case Do_getParamAndVarCount: - methodLocals = 1; // Only this - cfw.startMethod("getParamAndVarCount", "()I", - ClassFileWriter.ACC_PUBLIC); - break; - case Do_getParamOrVarName: - methodLocals = 1 + 1; // this + paramOrVarIndex - cfw.startMethod("getParamOrVarName", "(I)Ljava/lang/String;", - ClassFileWriter.ACC_PUBLIC); - break; - case Do_getParamOrVarConst: - methodLocals = 1 + 1 + 1; // this + paramOrVarName - cfw.startMethod("getParamOrVarConst", "(I)Z", - ClassFileWriter.ACC_PUBLIC); - break; - case Do_getEncodedSource: - methodLocals = 1; // Only this - cfw.startMethod("getEncodedSource", "()Ljava/lang/String;", - ClassFileWriter.ACC_PUBLIC); - cfw.addPush(encodedSource); - break; - default: - throw Kit.codeBug(); - } - - int count = scriptOrFnNodes.length; - - int switchStart = 0; - int switchStackTop = 0; - if (count > 1) { - // Generate switch but only if there is more then one - // script/function - cfw.addLoadThis(); - cfw.add(ByteCode.GETFIELD, cfw.getClassName(), - ID_FIELD_NAME, "I"); - - // do switch from 1 .. count - 1 mapping 0 to the default case - switchStart = cfw.addTableSwitch(1, count - 1); - } - - for (int i = 0; i != count; ++i) { - ScriptOrFnNode n = scriptOrFnNodes[i]; - if (i == 0) { - if (count > 1) { - cfw.markTableSwitchDefault(switchStart); - switchStackTop = cfw.getStackTop(); - } - } else { - cfw.markTableSwitchCase(switchStart, i - 1, - switchStackTop); - } - - // Impelemnet method-specific switch code - switch (methodIndex) { - case Do_getFunctionName: - // Push function name - if (n.getType() == Token.SCRIPT) { - cfw.addPush(""); - } else { - String name = ((FunctionNode)n).getFunctionName(); - cfw.addPush(name); - } - cfw.add(ByteCode.ARETURN); - break; - - case Do_getParamCount: - // Push number of defined parameters - cfw.addPush(n.getParamCount()); - cfw.add(ByteCode.IRETURN); - break; - - case Do_getParamAndVarCount: - // Push number of defined parameters and declared variables - cfw.addPush(n.getParamAndVarCount()); - cfw.add(ByteCode.IRETURN); - break; - - case Do_getParamOrVarName: - // Push name of parameter using another switch - // over paramAndVarCount - int paramAndVarCount = n.getParamAndVarCount(); - if (paramAndVarCount == 0) { - // The runtime should never call the method in this - // case but to make bytecode verifier happy return null - // as throwing execption takes more code - cfw.add(ByteCode.ACONST_NULL); - cfw.add(ByteCode.ARETURN); - } else if (paramAndVarCount == 1) { - // As above do not check for valid index but always - // return the name of the first param - cfw.addPush(n.getParamOrVarName(0)); - cfw.add(ByteCode.ARETURN); - } else { - // Do switch over getParamOrVarName - cfw.addILoad(1); // param or var index - // do switch from 1 .. paramAndVarCount - 1 mapping 0 - // to the default case - int paramSwitchStart = cfw.addTableSwitch( - 1, paramAndVarCount - 1); - for (int j = 0; j != paramAndVarCount; ++j) { - if (cfw.getStackTop() != 0) Kit.codeBug(); - String s = n.getParamOrVarName(j); - if (j == 0) { - cfw.markTableSwitchDefault(paramSwitchStart); - } else { - cfw.markTableSwitchCase(paramSwitchStart, j - 1, - 0); - } - cfw.addPush(s); - cfw.add(ByteCode.ARETURN); - } - } - break; - - case Do_getParamOrVarConst: - // Push name of parameter using another switch - // over paramAndVarCount - paramAndVarCount = n.getParamAndVarCount(); - boolean [] constness = n.getParamAndVarConst(); - if (paramAndVarCount == 0) { - // The runtime should never call the method in this - // case but to make bytecode verifier happy return null - // as throwing execption takes more code - cfw.add(ByteCode.ICONST_0); - cfw.add(ByteCode.IRETURN); - } else if (paramAndVarCount == 1) { - // As above do not check for valid index but always - // return the name of the first param - cfw.addPush(constness[0]); - cfw.add(ByteCode.IRETURN); - } else { - // Do switch over getParamOrVarName - cfw.addILoad(1); // param or var index - // do switch from 1 .. paramAndVarCount - 1 mapping 0 - // to the default case - int paramSwitchStart = cfw.addTableSwitch( - 1, paramAndVarCount - 1); - for (int j = 0; j != paramAndVarCount; ++j) { - if (cfw.getStackTop() != 0) Kit.codeBug(); - if (j == 0) { - cfw.markTableSwitchDefault(paramSwitchStart); - } else { - cfw.markTableSwitchCase(paramSwitchStart, j - 1, - 0); - } - cfw.addPush(constness[j]); - cfw.add(ByteCode.IRETURN); - } - } - break; - - case Do_getEncodedSource: - // Push number encoded source start and end - // to prepare for encodedSource.substring(start, end) - cfw.addPush(n.getEncodedSourceStart()); - cfw.addPush(n.getEncodedSourceEnd()); - cfw.addInvoke(ByteCode.INVOKEVIRTUAL, - "java/lang/String", - "substring", - "(II)Ljava/lang/String;"); - cfw.add(ByteCode.ARETURN); - break; - - default: - throw Kit.codeBug(); - } - } - - cfw.stopMethod(methodLocals); - } - } - - private void emitRegExpInit(ClassFileWriter cfw) - { - // precompile all regexp literals - - int totalRegCount = 0; - for (int i = 0; i != scriptOrFnNodes.length; ++i) { - totalRegCount += scriptOrFnNodes[i].getRegexpCount(); - } - if (totalRegCount == 0) { - return; - } - - cfw.startMethod(REGEXP_INIT_METHOD_NAME, REGEXP_INIT_METHOD_SIGNATURE, - (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE - | ClassFileWriter.ACC_SYNCHRONIZED)); - cfw.addField("_reInitDone", "Z", - (short)(ClassFileWriter.ACC_STATIC - | ClassFileWriter.ACC_PRIVATE)); - cfw.add(ByteCode.GETSTATIC, mainClassName, "_reInitDone", "Z"); - int doInit = cfw.acquireLabel(); - cfw.add(ByteCode.IFEQ, doInit); - cfw.add(ByteCode.RETURN); - cfw.markLabel(doInit); - - for (int i = 0; i != scriptOrFnNodes.length; ++i) { - ScriptOrFnNode n = scriptOrFnNodes[i]; - int regCount = n.getRegexpCount(); - for (int j = 0; j != regCount; ++j) { - String reFieldName = getCompiledRegexpName(n, j); - String reFieldType = "Ljava/lang/Object;"; - String reString = n.getRegexpString(j); - String reFlags = n.getRegexpFlags(j); - cfw.addField(reFieldName, reFieldType, - (short)(ClassFileWriter.ACC_STATIC - | ClassFileWriter.ACC_PRIVATE)); - cfw.addALoad(0); // proxy - cfw.addALoad(1); // context - cfw.addPush(reString); - if (reFlags == null) { - cfw.add(ByteCode.ACONST_NULL); - } else { - cfw.addPush(reFlags); - } - /*APPJET*/cfw.addLineNumberEntry((short)n.getRegexpLineno(j)); - cfw.addInvoke(ByteCode.INVOKEINTERFACE, - "org/mozilla/javascript/RegExpProxy", - "compileRegExp", - "(Lorg/mozilla/javascript/Context;" - +"Ljava/lang/String;Ljava/lang/String;" - +")Ljava/lang/Object;"); - cfw.add(ByteCode.PUTSTATIC, mainClassName, - reFieldName, reFieldType); - } - } - - cfw.addPush(1); - cfw.add(ByteCode.PUTSTATIC, mainClassName, "_reInitDone", "Z"); - cfw.add(ByteCode.RETURN); - cfw.stopMethod((short)2); - } - - private void emitConstantDudeInitializers(ClassFileWriter cfw) - { - int N = itsConstantListSize; - if (N == 0) - return; - - cfw.startMethod("<clinit>", "()V", - (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_FINAL)); - - double[] array = itsConstantList; - for (int i = 0; i != N; ++i) { - double num = array[i]; - String constantName = "_k" + i; - String constantType = getStaticConstantWrapperType(num); - cfw.addField(constantName, constantType, - (short)(ClassFileWriter.ACC_STATIC - | ClassFileWriter.ACC_PRIVATE)); - int inum = (int)num; - if (inum == num) { - cfw.add(ByteCode.NEW, "java/lang/Integer"); - cfw.add(ByteCode.DUP); - cfw.addPush(inum); - cfw.addInvoke(ByteCode.INVOKESPECIAL, "java/lang/Integer", - "<init>", "(I)V"); - } else { - cfw.addPush(num); - addDoubleWrap(cfw); - } - cfw.add(ByteCode.PUTSTATIC, mainClassName, - constantName, constantType); - } - - cfw.add(ByteCode.RETURN); - cfw.stopMethod((short)0); - } - - void pushRegExpArray(ClassFileWriter cfw, ScriptOrFnNode n, - int contextArg, int scopeArg) - { - int regexpCount = n.getRegexpCount(); - if (regexpCount == 0) throw badTree(); - - cfw.addPush(regexpCount); - cfw.add(ByteCode.ANEWARRAY, "java/lang/Object"); - - cfw.addALoad(contextArg); - cfw.addInvoke(ByteCode.INVOKESTATIC, - "org/mozilla/javascript/ScriptRuntime", - "checkRegExpProxy", - "(Lorg/mozilla/javascript/Context;" - +")Lorg/mozilla/javascript/RegExpProxy;"); - // Stack: proxy, array - cfw.add(ByteCode.DUP); - cfw.addALoad(contextArg); - cfw.addInvoke(ByteCode.INVOKESTATIC, mainClassName, - REGEXP_INIT_METHOD_NAME, REGEXP_INIT_METHOD_SIGNATURE); - for (int i = 0; i != regexpCount; ++i) { - // Stack: proxy, array - cfw.add(ByteCode.DUP2); - cfw.addALoad(contextArg); - cfw.addALoad(scopeArg); - cfw.add(ByteCode.GETSTATIC, mainClassName, - getCompiledRegexpName(n, i), "Ljava/lang/Object;"); - // Stack: compiledRegExp, scope, cx, proxy, array, proxy, array - cfw.addInvoke(ByteCode.INVOKEINTERFACE, - "org/mozilla/javascript/RegExpProxy", - "wrapRegExp", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/Object;" - +")Lorg/mozilla/javascript/Scriptable;"); - // Stack: wrappedRegExp, array, proxy, array - cfw.addPush(i); - cfw.add(ByteCode.SWAP); - cfw.add(ByteCode.AASTORE); - // Stack: proxy, array - } - // remove proxy - cfw.add(ByteCode.POP); - } - - void pushNumberAsObject(ClassFileWriter cfw, double num) - { - if (num == 0.0) { - if (1 / num > 0) { - // +0.0 - cfw.add(ByteCode.GETSTATIC, - "org/mozilla/javascript/optimizer/OptRuntime", - "zeroObj", "Ljava/lang/Double;"); - } else { - cfw.addPush(num); - addDoubleWrap(cfw); - } - - } else if (num == 1.0) { - cfw.add(ByteCode.GETSTATIC, - "org/mozilla/javascript/optimizer/OptRuntime", - "oneObj", "Ljava/lang/Double;"); - return; - - } else if (num == -1.0) { - cfw.add(ByteCode.GETSTATIC, - "org/mozilla/javascript/optimizer/OptRuntime", - "minusOneObj", "Ljava/lang/Double;"); - - } else if (num != num) { - cfw.add(ByteCode.GETSTATIC, - "org/mozilla/javascript/ScriptRuntime", - "NaNobj", "Ljava/lang/Double;"); - - } else if (itsConstantListSize >= 2000) { - // There appears to be a limit in the JVM on either the number - // of static fields in a class or the size of the class - // initializer. Either way, we can't have any more than 2000 - // statically init'd constants. - cfw.addPush(num); - addDoubleWrap(cfw); - - } else { - int N = itsConstantListSize; - int index = 0; - if (N == 0) { - itsConstantList = new double[64]; - } else { - double[] array = itsConstantList; - while (index != N && array[index] != num) { - ++index; - } - if (N == array.length) { - array = new double[N * 2]; - System.arraycopy(itsConstantList, 0, array, 0, N); - itsConstantList = array; - } - } - if (index == N) { - itsConstantList[N] = num; - itsConstantListSize = N + 1; - } - String constantName = "_k" + index; - String constantType = getStaticConstantWrapperType(num); - cfw.add(ByteCode.GETSTATIC, mainClassName, - constantName, constantType); - } - } - - private static void addDoubleWrap(ClassFileWriter cfw) - { - cfw.addInvoke(ByteCode.INVOKESTATIC, - "org/mozilla/javascript/optimizer/OptRuntime", - "wrapDouble", "(D)Ljava/lang/Double;"); - } - - private static String getStaticConstantWrapperType(double num) - { - int inum = (int)num; - if (inum == num) { - return "Ljava/lang/Integer;"; - } else { - return "Ljava/lang/Double;"; - } - } - static void pushUndefined(ClassFileWriter cfw) - { - cfw.add(ByteCode.GETSTATIC, "org/mozilla/javascript/Undefined", - "instance", "Ljava/lang/Object;"); - } - - int getIndex(ScriptOrFnNode n) - { - return scriptOrFnIndexes.getExisting(n); - } - - static String getDirectTargetFieldName(int i) - { - return "_dt" + i; - } - - String getDirectCtorName(ScriptOrFnNode n) - { - return "_n"+getIndex(n); - } - - String getBodyMethodName(ScriptOrFnNode n) - { - return "_c"+getIndex(n); - } - - String getBodyMethodSignature(ScriptOrFnNode n) - { - StringBuffer sb = new StringBuffer(); - sb.append('('); - sb.append(mainClassSignature); - sb.append("Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Scriptable;"); - if (n.getType() == Token.FUNCTION) { - OptFunctionNode ofn = OptFunctionNode.get(n); - if (ofn.isTargetOfDirectCall()) { - int pCount = ofn.fnode.getParamCount(); - for (int i = 0; i != pCount; i++) { - sb.append("Ljava/lang/Object;D"); - } - } - } - sb.append("[Ljava/lang/Object;)Ljava/lang/Object;"); - return sb.toString(); - } - - String getFunctionInitMethodName(OptFunctionNode ofn) - { - return "_i"+getIndex(ofn.fnode); - } - - String getCompiledRegexpName(ScriptOrFnNode n, int regexpIndex) - { - return "_re"+getIndex(n)+"_"+regexpIndex; - } - - static RuntimeException badTree() - { - throw new RuntimeException("Bad tree in codegen"); - } - - void setMainMethodClass(String className) - { - mainMethodClass = className; - } - - static final String DEFAULT_MAIN_METHOD_CLASS - = "org.mozilla.javascript.optimizer.OptRuntime"; - - private static final String SUPER_CLASS_NAME - = "org.mozilla.javascript.NativeFunction"; - - static final String DIRECT_CALL_PARENT_FIELD = "_dcp"; - private static final String ID_FIELD_NAME = "_id"; - - private static final String REGEXP_INIT_METHOD_NAME = "_reInit"; - private static final String REGEXP_INIT_METHOD_SIGNATURE - = "(Lorg/mozilla/javascript/RegExpProxy;" - +"Lorg/mozilla/javascript/Context;" - +")V"; - static final String REGEXP_ARRAY_FIELD_NAME = "_re"; - static final String REGEXP_ARRAY_FIELD_TYPE = "[Ljava/lang/Object;"; - - static final String FUNCTION_INIT_SIGNATURE - = "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")V"; - - static final String FUNCTION_CONSTRUCTOR_SIGNATURE - = "(Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Context;I)V"; - - private static final Object globalLock = new Object(); - private static int globalSerialClassCounter; - - private CompilerEnvirons compilerEnv; - - private ObjArray directCallTargets; - ScriptOrFnNode[] scriptOrFnNodes; - private ObjToIntMap scriptOrFnIndexes; - - private String mainMethodClass = DEFAULT_MAIN_METHOD_CLASS; - - String mainClassName; - String mainClassSignature; - - private double[] itsConstantList; - private int itsConstantListSize; -} - - -class BodyCodegen -{ - void generateBodyCode() - { - isGenerator = Codegen.isGenerator(scriptOrFn); - - // generate the body of the current function or script object - initBodyGeneration(); - - if (isGenerator) { - - // All functions in the generated bytecode have a unique name. Every - // generator has a unique prefix followed by _gen - String type = "(" + - codegen.mainClassSignature + - "Lorg/mozilla/javascript/Context;" + - "Lorg/mozilla/javascript/Scriptable;" + - "Ljava/lang/Object;" + - "Ljava/lang/Object;I)Ljava/lang/Object;"; - cfw.startMethod(codegen.getBodyMethodName(scriptOrFn) + "_gen", - type, - (short)(ClassFileWriter.ACC_STATIC - | ClassFileWriter.ACC_PRIVATE)); - } else { - cfw.startMethod(codegen.getBodyMethodName(scriptOrFn), - codegen.getBodyMethodSignature(scriptOrFn), - (short)(ClassFileWriter.ACC_STATIC - | ClassFileWriter.ACC_PRIVATE)); - } - - generatePrologue(); - Node treeTop; - if (fnCurrent != null) { - treeTop = scriptOrFn.getLastChild(); - } else { - treeTop = scriptOrFn; - } - generateStatement(treeTop); - generateEpilogue(); - - cfw.stopMethod((short)(localsMax + 1)); - - if (isGenerator) { - // generate the user visible method which when invoked will - // return a generator object - generateGenerator(); - } - } - - // This creates a the user-facing function that returns a NativeGenerator - // object. - private void generateGenerator() - { - cfw.startMethod(codegen.getBodyMethodName(scriptOrFn), - codegen.getBodyMethodSignature(scriptOrFn), - (short)(ClassFileWriter.ACC_STATIC - | ClassFileWriter.ACC_PRIVATE)); - - initBodyGeneration(); - argsLocal = firstFreeLocal++; - localsMax = firstFreeLocal; - - // get top level scope - if (fnCurrent != null && !inDirectCallFunction - && (!compilerEnv.isUseDynamicScope() - || fnCurrent.fnode.getIgnoreDynamicScope())) - { - // Unless we're either in a direct call or using dynamic scope, - // use the enclosing scope of the function as our variable object. - cfw.addALoad(funObjLocal); - cfw.addInvoke(ByteCode.INVOKEINTERFACE, - "org/mozilla/javascript/Scriptable", - "getParentScope", - "()Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(variableObjectLocal); - } - - // generators are forced to have an activation record - cfw.addALoad(funObjLocal); - cfw.addALoad(variableObjectLocal); - cfw.addALoad(argsLocal); - addScriptRuntimeInvoke("createFunctionActivation", - "(Lorg/mozilla/javascript/NativeFunction;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(variableObjectLocal); - - // create a function object - cfw.add(ByteCode.NEW, codegen.mainClassName); - // Call function constructor - cfw.add(ByteCode.DUP); - cfw.addALoad(variableObjectLocal); - cfw.addALoad(contextLocal); // load 'cx' - cfw.addPush(scriptOrFnIndex); - cfw.addInvoke(ByteCode.INVOKESPECIAL, codegen.mainClassName, - "<init>", Codegen.FUNCTION_CONSTRUCTOR_SIGNATURE); - - // Init mainScript field - cfw.add(ByteCode.DUP); - if (isTopLevel) Kit.codeBug(); // Only functions can be generators - cfw.add(ByteCode.ALOAD_0); - cfw.add(ByteCode.GETFIELD, - codegen.mainClassName, - Codegen.DIRECT_CALL_PARENT_FIELD, - codegen.mainClassSignature); - cfw.add(ByteCode.PUTFIELD, - codegen.mainClassName, - Codegen.DIRECT_CALL_PARENT_FIELD, - codegen.mainClassSignature); - - generateNestedFunctionInits(); - - // create the NativeGenerator object that we return - cfw.addALoad(variableObjectLocal); - cfw.addALoad(thisObjLocal); - cfw.addLoadConstant(maxLocals); - cfw.addLoadConstant(maxStack); - addOptRuntimeInvoke("createNativeGenerator", - "(Lorg/mozilla/javascript/NativeFunction;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Scriptable;II" - +")Lorg/mozilla/javascript/Scriptable;"); - - cfw.add(ByteCode.ARETURN); - cfw.stopMethod((short)(localsMax + 1)); - } - - private void generateNestedFunctionInits() - { - int functionCount = scriptOrFn.getFunctionCount(); - for (int i = 0; i != functionCount; i++) { - OptFunctionNode ofn = OptFunctionNode.get(scriptOrFn, i); - if (ofn.fnode.getFunctionType() - == FunctionNode.FUNCTION_STATEMENT) - { - visitFunction(ofn, FunctionNode.FUNCTION_STATEMENT); - } - } - } - - private void initBodyGeneration() - { - isTopLevel = (scriptOrFn == codegen.scriptOrFnNodes[0]); - - varRegisters = null; - if (scriptOrFn.getType() == Token.FUNCTION) { - fnCurrent = OptFunctionNode.get(scriptOrFn); - hasVarsInRegs = !fnCurrent.fnode.requiresActivation(); - if (hasVarsInRegs) { - int n = fnCurrent.fnode.getParamAndVarCount(); - if (n != 0) { - varRegisters = new short[n]; - } - } - inDirectCallFunction = fnCurrent.isTargetOfDirectCall(); - if (inDirectCallFunction && !hasVarsInRegs) Codegen.badTree(); - } else { - fnCurrent = null; - hasVarsInRegs = false; - inDirectCallFunction = false; - } - - locals = new int[MAX_LOCALS]; - - funObjLocal = 0; - contextLocal = 1; - variableObjectLocal = 2; - thisObjLocal = 3; - localsMax = (short) 4; // number of parms + "this" - firstFreeLocal = 4; - - popvLocal = -1; - argsLocal = -1; - itsZeroArgArray = -1; - itsOneArgArray = -1; - scriptRegexpLocal = -1; - epilogueLabel = -1; - enterAreaStartLabel = -1; - generatorStateLocal = -1; - } - - /** - * Generate the prologue for a function or script. - */ - private void generatePrologue() - { - if (inDirectCallFunction) { - int directParameterCount = scriptOrFn.getParamCount(); - // 0 is reserved for function Object 'this' - // 1 is reserved for context - // 2 is reserved for parentScope - // 3 is reserved for script 'this' - if (firstFreeLocal != 4) Kit.codeBug(); - for (int i = 0; i != directParameterCount; ++i) { - varRegisters[i] = firstFreeLocal; - // 3 is 1 for Object parm and 2 for double parm - firstFreeLocal += 3; - } - if (!fnCurrent.getParameterNumberContext()) { - // make sure that all parameters are objects - itsForcedObjectParameters = true; - for (int i = 0; i != directParameterCount; ++i) { - short reg = varRegisters[i]; - cfw.addALoad(reg); - cfw.add(ByteCode.GETSTATIC, - "java/lang/Void", - "TYPE", - "Ljava/lang/Class;"); - int isObjectLabel = cfw.acquireLabel(); - cfw.add(ByteCode.IF_ACMPNE, isObjectLabel); - cfw.addDLoad(reg + 1); - addDoubleWrap(); - cfw.addAStore(reg); - cfw.markLabel(isObjectLabel); - } - } - } - - if (fnCurrent != null && !inDirectCallFunction - && (!compilerEnv.isUseDynamicScope() - || fnCurrent.fnode.getIgnoreDynamicScope())) - { - // Unless we're either in a direct call or using dynamic scope, - // use the enclosing scope of the function as our variable object. - cfw.addALoad(funObjLocal); - cfw.addInvoke(ByteCode.INVOKEINTERFACE, - "org/mozilla/javascript/Scriptable", - "getParentScope", - "()Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(variableObjectLocal); - } - - // reserve 'args[]' - argsLocal = firstFreeLocal++; - localsMax = firstFreeLocal; - - // Generate Generator specific prelude - if (isGenerator) { - - // reserve 'args[]' - operationLocal = firstFreeLocal++; - localsMax = firstFreeLocal; - - // Local 3 is a reference to a GeneratorState object. The rest - // of codegen expects local 3 to be a reference to the thisObj. - // So move the value in local 3 to generatorStateLocal, and load - // the saved thisObj from the GeneratorState object. - cfw.addALoad(thisObjLocal); - generatorStateLocal = firstFreeLocal++; - localsMax = firstFreeLocal; - cfw.add(ByteCode.CHECKCAST, OptRuntime.GeneratorState.CLASS_NAME); - cfw.add(ByteCode.DUP); - cfw.addAStore(generatorStateLocal); - cfw.add(ByteCode.GETFIELD, - OptRuntime.GeneratorState.CLASS_NAME, - OptRuntime.GeneratorState.thisObj_NAME, - OptRuntime.GeneratorState.thisObj_TYPE); - cfw.addAStore(thisObjLocal); - - if (epilogueLabel == -1) { - epilogueLabel = cfw.acquireLabel(); - } - - ArrayList targets = ((FunctionNode)scriptOrFn).getResumptionPoints(); - if (targets != null) { - // get resumption point - generateGetGeneratorResumptionPoint(); - - // generate dispatch table - generatorSwitch = cfw.addTableSwitch(0, - targets.size() + GENERATOR_START); - generateCheckForThrowOrClose(-1, false, GENERATOR_START); - } - } - - if (fnCurrent == null) { - // See comments in case Token.REGEXP - if (scriptOrFn.getRegexpCount() != 0) { - scriptRegexpLocal = getNewWordLocal(); - codegen.pushRegExpArray(cfw, scriptOrFn, contextLocal, - variableObjectLocal); - cfw.addAStore(scriptRegexpLocal); - } - } - - if (compilerEnv.isGenerateObserverCount()) - saveCurrentCodeOffset(); - - if (hasVarsInRegs) { - // No need to create activation. Pad arguments if need be. - int parmCount = scriptOrFn.getParamCount(); - if (parmCount > 0 && !inDirectCallFunction) { - // Set up args array - // check length of arguments, pad if need be - cfw.addALoad(argsLocal); - cfw.add(ByteCode.ARRAYLENGTH); - cfw.addPush(parmCount); - int label = cfw.acquireLabel(); - cfw.add(ByteCode.IF_ICMPGE, label); - cfw.addALoad(argsLocal); - cfw.addPush(parmCount); - addScriptRuntimeInvoke("padArguments", - "([Ljava/lang/Object;I" - +")[Ljava/lang/Object;"); - cfw.addAStore(argsLocal); - cfw.markLabel(label); - } - - int paramCount = fnCurrent.fnode.getParamCount(); - int varCount = fnCurrent.fnode.getParamAndVarCount(); - boolean [] constDeclarations = fnCurrent.fnode.getParamAndVarConst(); - - // REMIND - only need to initialize the vars that don't get a value - // before the next call and are used in the function - short firstUndefVar = -1; - for (int i = 0; i != varCount; ++i) { - short reg = -1; - if (i < paramCount) { - if (!inDirectCallFunction) { - reg = getNewWordLocal(); - cfw.addALoad(argsLocal); - cfw.addPush(i); - cfw.add(ByteCode.AALOAD); - cfw.addAStore(reg); - } - } else if (fnCurrent.isNumberVar(i)) { - reg = getNewWordPairLocal(constDeclarations[i]); - cfw.addPush(0.0); - cfw.addDStore(reg); - } else { - reg = getNewWordLocal(constDeclarations[i]); - if (firstUndefVar == -1) { - Codegen.pushUndefined(cfw); - firstUndefVar = reg; - } else { - cfw.addALoad(firstUndefVar); - } - cfw.addAStore(reg); - } - if (reg >= 0) { - if (constDeclarations[i]) { - cfw.addPush(0); - cfw.addIStore(reg + (fnCurrent.isNumberVar(i) ? 2 : 1)); - } - varRegisters[i] = reg; - } - - // Add debug table entry if we're generating debug info - if (compilerEnv.isGenerateDebugInfo()) { - String name = fnCurrent.fnode.getParamOrVarName(i); - String type = fnCurrent.isNumberVar(i) - ? "D" : "Ljava/lang/Object;"; - int startPC = cfw.getCurrentCodeOffset(); - if (reg < 0) { - reg = varRegisters[i]; - } - cfw.addVariableDescriptor(name, type, startPC, reg); - } - } - - // Skip creating activation object. - return; - } - - // skip creating activation object for the body of a generator. The - // activation record required by a generator has already been created - // in generateGenerator(). - if (isGenerator) - return; - - - String debugVariableName; - if (fnCurrent != null) { - debugVariableName = "activation"; - cfw.addALoad(funObjLocal); - cfw.addALoad(variableObjectLocal); - cfw.addALoad(argsLocal); - addScriptRuntimeInvoke("createFunctionActivation", - "(Lorg/mozilla/javascript/NativeFunction;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(variableObjectLocal); - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke("enterActivationFunction", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")V"); - } else { - debugVariableName = "global"; - cfw.addALoad(funObjLocal); - cfw.addALoad(thisObjLocal); - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - cfw.addPush(0); // false to indicate it is not eval script - addScriptRuntimeInvoke("initScript", - "(Lorg/mozilla/javascript/NativeFunction;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Z" - +")V"); - } - - enterAreaStartLabel = cfw.acquireLabel(); - epilogueLabel = cfw.acquireLabel(); - cfw.markLabel(enterAreaStartLabel); - - generateNestedFunctionInits(); - - // default is to generate debug info - if (compilerEnv.isGenerateDebugInfo()) { - cfw.addVariableDescriptor(debugVariableName, - "Lorg/mozilla/javascript/Scriptable;", - cfw.getCurrentCodeOffset(), variableObjectLocal); - } - - if (fnCurrent == null) { - // OPT: use dataflow to prove that this assignment is dead - popvLocal = getNewWordLocal(); - Codegen.pushUndefined(cfw); - cfw.addAStore(popvLocal); - - int linenum = scriptOrFn.getEndLineno(); - if (linenum != -1) - cfw.addLineNumberEntry((short)linenum); - - } else { - if (fnCurrent.itsContainsCalls0) { - itsZeroArgArray = getNewWordLocal(); - cfw.add(ByteCode.GETSTATIC, - "org/mozilla/javascript/ScriptRuntime", - "emptyArgs", "[Ljava/lang/Object;"); - cfw.addAStore(itsZeroArgArray); - } - if (fnCurrent.itsContainsCalls1) { - itsOneArgArray = getNewWordLocal(); - cfw.addPush(1); - cfw.add(ByteCode.ANEWARRAY, "java/lang/Object"); - cfw.addAStore(itsOneArgArray); - } - } - } - - private void generateGetGeneratorResumptionPoint() - { - cfw.addALoad(generatorStateLocal); - cfw.add(ByteCode.GETFIELD, - OptRuntime.GeneratorState.CLASS_NAME, - OptRuntime.GeneratorState.resumptionPoint_NAME, - OptRuntime.GeneratorState.resumptionPoint_TYPE); - } - - private void generateSetGeneratorResumptionPoint(int nextState) - { - cfw.addALoad(generatorStateLocal); - cfw.addLoadConstant(nextState); - cfw.add(ByteCode.PUTFIELD, - OptRuntime.GeneratorState.CLASS_NAME, - OptRuntime.GeneratorState.resumptionPoint_NAME, - OptRuntime.GeneratorState.resumptionPoint_TYPE); - } - - private void generateGetGeneratorStackState() - { - cfw.addALoad(generatorStateLocal); - addOptRuntimeInvoke("getGeneratorStackState", - "(Ljava/lang/Object;)[Ljava/lang/Object;"); - } - - private void generateEpilogue() - { - if (compilerEnv.isGenerateObserverCount()) - addInstructionCount(); - if (isGenerator) { - // generate locals initialization - HashMap liveLocals = ((FunctionNode)scriptOrFn).getLiveLocals(); - if (liveLocals != null) { - ArrayList nodes = ((FunctionNode)scriptOrFn).getResumptionPoints(); - for (int i = 0; i < nodes.size(); i++) { - Node node = (Node) nodes.get(i); - int[] live = (int [])liveLocals.get(node); - if (live != null) { - cfw.markTableSwitchCase(generatorSwitch, - getNextGeneratorState(node)); - generateGetGeneratorLocalsState(); - for (int j = 0; j < live.length; j++) { - cfw.add(ByteCode.DUP); - cfw.addLoadConstant(j); - cfw.add(ByteCode.AALOAD); - cfw.addAStore(live[j]); - } - cfw.add(ByteCode.POP); - cfw.add(ByteCode.GOTO, getTargetLabel(node)); - } - } - } - - // generate dispatch tables for finally - if (finallys != null) { - Enumeration en = finallys.keys(); - while(en.hasMoreElements()) { - Node n = (Node) en.nextElement(); - if (n.getType() == Token.FINALLY) { - FinallyReturnPoint ret = - (FinallyReturnPoint)finallys.get(n); - // the finally will jump here - cfw.markLabel(ret.tableLabel, (short)1); - - // start generating a dispatch table - int startSwitch = cfw.addTableSwitch(0, - ret.jsrPoints.size() - 1); - int c = 0; - cfw.markTableSwitchDefault(startSwitch); - for (int i = 0; i < ret.jsrPoints.size(); i++) { - // generate gotos back to the JSR location - cfw.markTableSwitchCase(startSwitch, c); - cfw.add(ByteCode.GOTO, - ((Integer)ret.jsrPoints.get(i)).intValue()); - c++; - } - } - } - } - } - - if (epilogueLabel != -1) { - cfw.markLabel(epilogueLabel); - } - - if (hasVarsInRegs) { - cfw.add(ByteCode.ARETURN); - return; - } else if (isGenerator) { - if (((FunctionNode)scriptOrFn).getResumptionPoints() != null) { - cfw.markTableSwitchDefault(generatorSwitch); - } - - // change state for re-entry - generateSetGeneratorResumptionPoint(GENERATOR_TERMINATE); - - // throw StopIteration - cfw.addALoad(variableObjectLocal); - addOptRuntimeInvoke("throwStopIteration", - "(Ljava/lang/Object;)V"); - - Codegen.pushUndefined(cfw); - cfw.add(ByteCode.ARETURN); - - } else if (fnCurrent == null) { - cfw.addALoad(popvLocal); - cfw.add(ByteCode.ARETURN); - } else { - generateActivationExit(); - cfw.add(ByteCode.ARETURN); - - // Generate catch block to catch all and rethrow to call exit code - // under exception propagation as well. - - int finallyHandler = cfw.acquireLabel(); - cfw.markHandler(finallyHandler); - short exceptionObject = getNewWordLocal(); - cfw.addAStore(exceptionObject); - - // Duplicate generateActivationExit() in the catch block since it - // takes less space then full-featured ByteCode.JSR/ByteCode.RET - generateActivationExit(); - - cfw.addALoad(exceptionObject); - releaseWordLocal(exceptionObject); - // rethrow - cfw.add(ByteCode.ATHROW); - - // mark the handler - cfw.addExceptionHandler(enterAreaStartLabel, epilogueLabel, - finallyHandler, null); // catch any - } - } - - private void generateGetGeneratorLocalsState() { - cfw.addALoad(generatorStateLocal); - addOptRuntimeInvoke("getGeneratorLocalsState", - "(Ljava/lang/Object;)[Ljava/lang/Object;"); - } - - private void generateActivationExit() - { - if (fnCurrent == null || hasVarsInRegs) throw Kit.codeBug(); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke("exitActivationFunction", - "(Lorg/mozilla/javascript/Context;)V"); - } - - private void generateStatement(Node node) - { - updateLineNumber(node); - int type = node.getType(); - Node child = node.getFirstChild(); - switch (type) { - case Token.LOOP: - case Token.LABEL: - case Token.WITH: - case Token.SCRIPT: - case Token.BLOCK: - case Token.EMPTY: - // no-ops. - while (child != null) { - generateStatement(child); - child = child.getNext(); - } - break; - - case Token.LOCAL_BLOCK: { - int local = getNewWordLocal(); - if (isGenerator) { - cfw.add(ByteCode.ACONST_NULL); - cfw.addAStore(local); - } - node.putIntProp(Node.LOCAL_PROP, local); - while (child != null) { - generateStatement(child); - child = child.getNext(); - } - releaseWordLocal((short)local); - node.removeProp(Node.LOCAL_PROP); - break; - } - - case Token.FUNCTION: { - int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); - OptFunctionNode ofn = OptFunctionNode.get(scriptOrFn, fnIndex); - int t = ofn.fnode.getFunctionType(); - if (t == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) { - visitFunction(ofn, t); - } else { - if (t != FunctionNode.FUNCTION_STATEMENT) { - throw Codegen.badTree(); - } - } - break; - } - - case Token.TRY: - visitTryCatchFinally((Node.Jump)node, child); - break; - - case Token.CATCH_SCOPE: - { - // nothing stays on the stack on entry into a catch scope - cfw.setStackTop((short) 0); - - int local = getLocalBlockRegister(node); - int scopeIndex - = node.getExistingIntProp(Node.CATCH_SCOPE_PROP); - - String name = child.getString(); // name of exception - child = child.getNext(); - generateExpression(child, node); // load expression object - if (scopeIndex == 0) { - cfw.add(ByteCode.ACONST_NULL); - } else { - // Load previous catch scope object - cfw.addALoad(local); - } - cfw.addPush(name); - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - - addScriptRuntimeInvoke( - "newCatchScope", - "(Ljava/lang/Throwable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(local); - } - break; - - case Token.THROW: - generateExpression(child, node); - if (compilerEnv.isGenerateObserverCount()) - addInstructionCount(); - generateThrowJavaScriptException(); - break; - - case Token.RETHROW: - if (compilerEnv.isGenerateObserverCount()) - addInstructionCount(); - cfw.addALoad(getLocalBlockRegister(node)); - cfw.add(ByteCode.ATHROW); - break; - - case Token.RETURN_RESULT: - case Token.RETURN: - if (!isGenerator) { - if (child != null) { - generateExpression(child, node); - } else if (type == Token.RETURN) { - Codegen.pushUndefined(cfw); - } else { - if (popvLocal < 0) throw Codegen.badTree(); - cfw.addALoad(popvLocal); - } - } - if (compilerEnv.isGenerateObserverCount()) - addInstructionCount(); - if (epilogueLabel == -1) { - if (!hasVarsInRegs) throw Codegen.badTree(); - epilogueLabel = cfw.acquireLabel(); - } - cfw.add(ByteCode.GOTO, epilogueLabel); - break; - - case Token.SWITCH: - if (compilerEnv.isGenerateObserverCount()) - addInstructionCount(); - visitSwitch((Node.Jump)node, child); - break; - - case Token.ENTERWITH: - generateExpression(child, node); - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke( - "enterWith", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(variableObjectLocal); - incReferenceWordLocal(variableObjectLocal); - break; - - case Token.LEAVEWITH: - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke( - "leaveWith", - "(Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(variableObjectLocal); - decReferenceWordLocal(variableObjectLocal); - break; - - case Token.ENUM_INIT_KEYS: - case Token.ENUM_INIT_VALUES: - case Token.ENUM_INIT_ARRAY: - generateExpression(child, node); - cfw.addALoad(contextLocal); - int enumType = type == Token.ENUM_INIT_KEYS - ? ScriptRuntime.ENUMERATE_KEYS : - type == Token.ENUM_INIT_VALUES - ? ScriptRuntime.ENUMERATE_VALUES : - ScriptRuntime.ENUMERATE_ARRAY; - cfw.addPush(enumType); - addScriptRuntimeInvoke("enumInit", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"I" - +")Ljava/lang/Object;"); - cfw.addAStore(getLocalBlockRegister(node)); - break; - - case Token.EXPR_VOID: - if (child.getType() == Token.SETVAR) { - /* special case this so as to avoid unnecessary - load's & pop's */ - visitSetVar(child, child.getFirstChild(), false); - } - else if (child.getType() == Token.SETCONSTVAR) { - /* special case this so as to avoid unnecessary - load's & pop's */ - visitSetConstVar(child, child.getFirstChild(), false); - } - else if (child.getType() == Token.YIELD) { - generateYieldPoint(child, false); - } - else { - generateExpression(child, node); - if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) - cfw.add(ByteCode.POP2); - else - cfw.add(ByteCode.POP); - } - break; - - case Token.EXPR_RESULT: - generateExpression(child, node); - if (popvLocal < 0) { - popvLocal = getNewWordLocal(); - } - cfw.addAStore(popvLocal); - break; - - case Token.TARGET: - { - if (compilerEnv.isGenerateObserverCount()) - addInstructionCount(); - int label = getTargetLabel(node); - cfw.markLabel(label); - if (compilerEnv.isGenerateObserverCount()) - saveCurrentCodeOffset(); - } - break; - - case Token.JSR: - case Token.GOTO: - case Token.IFEQ: - case Token.IFNE: - if (compilerEnv.isGenerateObserverCount()) - addInstructionCount(); - visitGoto((Node.Jump)node, type, child); - break; - - case Token.FINALLY: - { - if (compilerEnv.isGenerateObserverCount()) - saveCurrentCodeOffset(); - // there is exactly one value on the stack when enterring - // finally blocks: the return address (or its int encoding) - cfw.setStackTop((short)1); - - // Save return address in a new local - int finallyRegister = getNewWordLocal(); - if (isGenerator) - generateIntegerWrap(); - cfw.addAStore(finallyRegister); - - while (child != null) { - generateStatement(child); - child = child.getNext(); - } - if (isGenerator) { - cfw.addALoad(finallyRegister); - cfw.add(ByteCode.CHECKCAST, "java/lang/Integer"); - generateIntegerUnwrap(); - FinallyReturnPoint ret = - (FinallyReturnPoint)finallys.get(node); - ret.tableLabel = cfw.acquireLabel(); - cfw.add(ByteCode.GOTO, ret.tableLabel); - } else { - cfw.add(ByteCode.RET, finallyRegister); - } - releaseWordLocal((short)finallyRegister); - } - break; - - case Token.DEBUGGER: - break; - - default: - throw Codegen.badTree(); - } - - } - - private void generateIntegerWrap() - { - cfw.addInvoke(ByteCode.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;"); - } - - - private void generateIntegerUnwrap() - { - cfw.addInvoke(ByteCode.INVOKEVIRTUAL, "java/lang/Integer", - "intValue", "()I"); - } - - - private void generateThrowJavaScriptException() - { - cfw.add(ByteCode.NEW, - "org/mozilla/javascript/JavaScriptException"); - cfw.add(ByteCode.DUP_X1); - cfw.add(ByteCode.SWAP); - cfw.addPush(scriptOrFn.getSourceName()); - cfw.addPush(itsLineNumber); - cfw.addInvoke( - ByteCode.INVOKESPECIAL, - "org/mozilla/javascript/JavaScriptException", - "<init>", - "(Ljava/lang/Object;Ljava/lang/String;I)V"); - cfw.add(ByteCode.ATHROW); - } - - private int getNextGeneratorState(Node node) - { - int nodeIndex = ((FunctionNode)scriptOrFn).getResumptionPoints() - .indexOf(node); - return nodeIndex + GENERATOR_YIELD_START; - } - - private void generateExpression(Node node, Node parent) - { - int type = node.getType(); - Node child = node.getFirstChild(); - switch (type) { - case Token.USE_STACK: - break; - - case Token.FUNCTION: - if (fnCurrent != null || parent.getType() != Token.SCRIPT) { - int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); - OptFunctionNode ofn = OptFunctionNode.get(scriptOrFn, - fnIndex); - int t = ofn.fnode.getFunctionType(); - if (t != FunctionNode.FUNCTION_EXPRESSION) { - throw Codegen.badTree(); - } - visitFunction(ofn, t); - } - break; - - case Token.NAME: - { - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - cfw.addPush(node.getString()); - addScriptRuntimeInvoke( - "name", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +")Ljava/lang/Object;"); - } - break; - - case Token.CALL: - case Token.NEW: - { - int specialType = node.getIntProp(Node.SPECIALCALL_PROP, - Node.NON_SPECIALCALL); - if (specialType == Node.NON_SPECIALCALL) { - OptFunctionNode target; - target = (OptFunctionNode)node.getProp( - Node.DIRECTCALL_PROP); - - if (target != null) { - visitOptimizedCall(node, target, type, child); - } else if (type == Token.CALL) { - visitStandardCall(node, child); - } else { - visitStandardNew(node, child); - } - } else { - visitSpecialCall(node, type, specialType, child); - } - } - break; - - case Token.REF_CALL: - generateFunctionAndThisObj(child, node); - // stack: ... functionObj thisObj - child = child.getNext(); - generateCallArgArray(node, child, false); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "callRef", - "(Lorg/mozilla/javascript/Callable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Lorg/mozilla/javascript/Ref;"); - break; - - case Token.NUMBER: - { - double num = node.getDouble(); - if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { - cfw.addPush(num); - } else { - codegen.pushNumberAsObject(cfw, num); - } - } - break; - - case Token.STRING: - cfw.addPush(node.getString()); - break; - - case Token.THIS: - cfw.addALoad(thisObjLocal); - break; - - case Token.THISFN: - cfw.add(ByteCode.ALOAD_0); - break; - - case Token.NULL: - cfw.add(ByteCode.ACONST_NULL); - break; - - case Token.TRUE: - cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", - "TRUE", "Ljava/lang/Boolean;"); - break; - - case Token.FALSE: - cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", - "FALSE", "Ljava/lang/Boolean;"); - break; - - case Token.REGEXP: - { - int i = node.getExistingIntProp(Node.REGEXP_PROP); - // Scripts can not use REGEXP_ARRAY_FIELD_NAME since - // it it will make script.exec non-reentrant so they - // store regexp array in a local variable while - // functions always access precomputed - // REGEXP_ARRAY_FIELD_NAME not to consume locals - if (fnCurrent == null) { - cfw.addALoad(scriptRegexpLocal); - } else { - cfw.addALoad(funObjLocal); - cfw.add(ByteCode.GETFIELD, codegen.mainClassName, - Codegen.REGEXP_ARRAY_FIELD_NAME, - Codegen.REGEXP_ARRAY_FIELD_TYPE); - } - cfw.addPush(i); - cfw.add(ByteCode.AALOAD); - } - break; - - case Token.COMMA: { - Node next = child.getNext(); - while (next != null) { - generateExpression(child, node); - cfw.add(ByteCode.POP); - child = next; - next = next.getNext(); - } - generateExpression(child, node); - break; - } - - case Token.ENUM_NEXT: - case Token.ENUM_ID: { - int local = getLocalBlockRegister(node); - cfw.addALoad(local); - if (type == Token.ENUM_NEXT) { - addScriptRuntimeInvoke( - "enumNext", "(Ljava/lang/Object;)Ljava/lang/Boolean;"); - } else { - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke("enumId", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - break; - } - - case Token.ARRAYLIT: - visitArrayLiteral(node, child); - break; - - case Token.OBJECTLIT: - visitObjectLiteral(node, child); - break; - - case Token.NOT: { - int trueTarget = cfw.acquireLabel(); - int falseTarget = cfw.acquireLabel(); - int beyond = cfw.acquireLabel(); - generateIfJump(child, node, trueTarget, falseTarget); - - cfw.markLabel(trueTarget); - cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", - "FALSE", "Ljava/lang/Boolean;"); - cfw.add(ByteCode.GOTO, beyond); - cfw.markLabel(falseTarget); - cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", - "TRUE", "Ljava/lang/Boolean;"); - cfw.markLabel(beyond); - cfw.adjustStackTop(-1); - break; - } - - case Token.BITNOT: - generateExpression(child, node); - addScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I"); - cfw.addPush(-1); // implement ~a as (a ^ -1) - cfw.add(ByteCode.IXOR); - cfw.add(ByteCode.I2D); - addDoubleWrap(); - break; - - case Token.VOID: - generateExpression(child, node); - cfw.add(ByteCode.POP); - Codegen.pushUndefined(cfw); - break; - - case Token.TYPEOF: - generateExpression(child, node); - addScriptRuntimeInvoke("typeof", - "(Ljava/lang/Object;" - +")Ljava/lang/String;"); - break; - - case Token.TYPEOFNAME: - visitTypeofname(node); - break; - - case Token.INC: - case Token.DEC: - visitIncDec(node); - break; - - case Token.OR: - case Token.AND: { - generateExpression(child, node); - cfw.add(ByteCode.DUP); - addScriptRuntimeInvoke("toBoolean", - "(Ljava/lang/Object;)Z"); - int falseTarget = cfw.acquireLabel(); - if (type == Token.AND) - cfw.add(ByteCode.IFEQ, falseTarget); - else - cfw.add(ByteCode.IFNE, falseTarget); - cfw.add(ByteCode.POP); - generateExpression(child.getNext(), node); - cfw.markLabel(falseTarget); - } - break; - - case Token.HOOK : { - Node ifThen = child.getNext(); - Node ifElse = ifThen.getNext(); - generateExpression(child, node); - addScriptRuntimeInvoke("toBoolean", - "(Ljava/lang/Object;)Z"); - int elseTarget = cfw.acquireLabel(); - cfw.add(ByteCode.IFEQ, elseTarget); - short stack = cfw.getStackTop(); - generateExpression(ifThen, node); - int afterHook = cfw.acquireLabel(); - cfw.add(ByteCode.GOTO, afterHook); - cfw.markLabel(elseTarget, stack); - generateExpression(ifElse, node); - cfw.markLabel(afterHook); - } - break; - - case Token.ADD: { - generateExpression(child, node); - generateExpression(child.getNext(), node); - switch (node.getIntProp(Node.ISNUMBER_PROP, -1)) { - case Node.BOTH: - cfw.add(ByteCode.DADD); - break; - case Node.LEFT: - addOptRuntimeInvoke("add", - "(DLjava/lang/Object;)Ljava/lang/Object;"); - break; - case Node.RIGHT: - addOptRuntimeInvoke("add", - "(Ljava/lang/Object;D)Ljava/lang/Object;"); - break; - default: - if (child.getType() == Token.STRING) { - addScriptRuntimeInvoke("add", - "(Ljava/lang/String;" - +"Ljava/lang/Object;" - +")Ljava/lang/String;"); - } else if (child.getNext().getType() == Token.STRING) { - addScriptRuntimeInvoke("add", - "(Ljava/lang/Object;" - +"Ljava/lang/String;" - +")Ljava/lang/String;"); - } else { - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke("add", - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - } - } - break; - - case Token.MUL: - visitArithmetic(node, ByteCode.DMUL, child, parent); - break; - - case Token.SUB: - visitArithmetic(node, ByteCode.DSUB, child, parent); - break; - - case Token.DIV: - case Token.MOD: - visitArithmetic(node, type == Token.DIV - ? ByteCode.DDIV - : ByteCode.DREM, child, parent); - break; - - case Token.BITOR: - case Token.BITXOR: - case Token.BITAND: - case Token.LSH: - case Token.RSH: - case Token.URSH: - visitBitOp(node, type, child); - break; - - case Token.POS: - case Token.NEG: - generateExpression(child, node); - addObjectToDouble(); - if (type == Token.NEG) { - cfw.add(ByteCode.DNEG); - } - addDoubleWrap(); - break; - - case Token.TO_DOUBLE: - // cnvt to double (not Double) - generateExpression(child, node); - addObjectToDouble(); - break; - - case Token.TO_OBJECT: { - // convert from double - int prop = -1; - if (child.getType() == Token.NUMBER) { - prop = child.getIntProp(Node.ISNUMBER_PROP, -1); - } - if (prop != -1) { - child.removeProp(Node.ISNUMBER_PROP); - generateExpression(child, node); - child.putIntProp(Node.ISNUMBER_PROP, prop); - } else { - generateExpression(child, node); - addDoubleWrap(); - } - break; - } - - case Token.IN: - case Token.INSTANCEOF: - case Token.LE: - case Token.LT: - case Token.GE: - case Token.GT: { - int trueGOTO = cfw.acquireLabel(); - int falseGOTO = cfw.acquireLabel(); - visitIfJumpRelOp(node, child, trueGOTO, falseGOTO); - addJumpedBooleanWrap(trueGOTO, falseGOTO); - break; - } - - case Token.EQ: - case Token.NE: - case Token.SHEQ: - case Token.SHNE: { - int trueGOTO = cfw.acquireLabel(); - int falseGOTO = cfw.acquireLabel(); - visitIfJumpEqOp(node, child, trueGOTO, falseGOTO); - addJumpedBooleanWrap(trueGOTO, falseGOTO); - break; - } - - case Token.GETPROP: - case Token.GETPROPNOWARN: - visitGetProp(node, child); - break; - - case Token.GETELEM: - generateExpression(child, node); // object - generateExpression(child.getNext(), node); // id - cfw.addALoad(contextLocal); - if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { - addScriptRuntimeInvoke( - "getObjectIndex", - "(Ljava/lang/Object;D" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - else { - addScriptRuntimeInvoke( - "getObjectElem", - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - break; - - case Token.GET_REF: - generateExpression(child, node); // reference - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "refGet", - "(Lorg/mozilla/javascript/Ref;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - break; - - case Token.GETVAR: - visitGetVar(node); - break; - - case Token.SETVAR: - visitSetVar(node, child, true); - break; - - case Token.SETNAME: - visitSetName(node, child); - break; - - case Token.SETCONST: - visitSetConst(node, child); - break; - - case Token.SETCONSTVAR: - visitSetConstVar(node, child, true); - break; - - case Token.SETPROP: - case Token.SETPROP_OP: - visitSetProp(type, node, child); - break; - - case Token.SETELEM: - case Token.SETELEM_OP: - visitSetElem(type, node, child); - break; - - case Token.SET_REF: - case Token.SET_REF_OP: - { - generateExpression(child, node); - child = child.getNext(); - if (type == Token.SET_REF_OP) { - cfw.add(ByteCode.DUP); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "refGet", - "(Lorg/mozilla/javascript/Ref;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - generateExpression(child, node); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "refSet", - "(Lorg/mozilla/javascript/Ref;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - break; - - case Token.DEL_REF: - generateExpression(child, node); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke("refDel", - "(Lorg/mozilla/javascript/Ref;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - break; - - case Token.DELPROP: - generateExpression(child, node); - child = child.getNext(); - generateExpression(child, node); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke("delete", - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - break; - - case Token.BINDNAME: - { - while (child != null) { - generateExpression(child, node); - child = child.getNext(); - } - // Generate code for "ScriptRuntime.bind(varObj, "s")" - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - cfw.addPush(node.getString()); - addScriptRuntimeInvoke( - "bind", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +")Lorg/mozilla/javascript/Scriptable;"); - } - break; - - case Token.LOCAL_LOAD: - cfw.addALoad(getLocalBlockRegister(node)); - break; - - case Token.REF_SPECIAL: - { - String special = (String)node.getProp(Node.NAME_PROP); - generateExpression(child, node); - cfw.addPush(special); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "specialRef", - "(Ljava/lang/Object;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +")Lorg/mozilla/javascript/Ref;"); - } - break; - - case Token.REF_MEMBER: - case Token.REF_NS_MEMBER: - case Token.REF_NAME: - case Token.REF_NS_NAME: - { - int memberTypeFlags - = node.getIntProp(Node.MEMBER_TYPE_PROP, 0); - // generate possible target, possible namespace and member - do { - generateExpression(child, node); - child = child.getNext(); - } while (child != null); - cfw.addALoad(contextLocal); - String methodName, signature; - switch (type) { - case Token.REF_MEMBER: - methodName = "memberRef"; - signature = "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"I" - +")Lorg/mozilla/javascript/Ref;"; - break; - case Token.REF_NS_MEMBER: - methodName = "memberRef"; - signature = "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"I" - +")Lorg/mozilla/javascript/Ref;"; - break; - case Token.REF_NAME: - methodName = "nameRef"; - signature = "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"I" - +")Lorg/mozilla/javascript/Ref;"; - cfw.addALoad(variableObjectLocal); - break; - case Token.REF_NS_NAME: - methodName = "nameRef"; - signature = "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"I" - +")Lorg/mozilla/javascript/Ref;"; - cfw.addALoad(variableObjectLocal); - break; - default: - throw Kit.codeBug(); - } - cfw.addPush(memberTypeFlags); - addScriptRuntimeInvoke(methodName, signature); - } - break; - - case Token.DOTQUERY: - visitDotQuery(node, child); - break; - - case Token.ESCXMLATTR: - generateExpression(child, node); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke("escapeAttributeValue", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/String;"); - break; - - case Token.ESCXMLTEXT: - generateExpression(child, node); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke("escapeTextValue", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/String;"); - break; - - case Token.DEFAULTNAMESPACE: - generateExpression(child, node); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke("setDefaultNamespace", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - break; - - case Token.YIELD: - generateYieldPoint(node, true); - break; - - case Token.WITHEXPR: { - Node enterWith = child; - Node with = enterWith.getNext(); - Node leaveWith = with.getNext(); - generateStatement(enterWith); - generateExpression(with.getFirstChild(), with); - generateStatement(leaveWith); - break; - } - - case Token.ARRAYCOMP: { - Node initStmt = child; - Node expr = child.getNext(); - generateStatement(initStmt); - generateExpression(expr, node); - break; - } - - default: - throw new RuntimeException("Unexpected node type "+type); - } - - } - - private void generateYieldPoint(Node node, boolean exprContext) { - // save stack state - int top = cfw.getStackTop(); - maxStack = maxStack > top ? maxStack : top; - if (cfw.getStackTop() != 0) { - generateGetGeneratorStackState(); - for (int i = 0; i < top; i++) { - cfw.add(ByteCode.DUP_X1); - cfw.add(ByteCode.SWAP); - cfw.addLoadConstant(i); - cfw.add(ByteCode.SWAP); - cfw.add(ByteCode.AASTORE); - } - // pop the array object - cfw.add(ByteCode.POP); - } - - // generate the yield argument - Node child = node.getFirstChild(); - if (child != null) - generateExpression(child, node); - else - Codegen.pushUndefined(cfw); - - // change the resumption state - int nextState = getNextGeneratorState(node); - generateSetGeneratorResumptionPoint(nextState); - - boolean hasLocals = generateSaveLocals(node); - - cfw.add(ByteCode.ARETURN); - - generateCheckForThrowOrClose(getTargetLabel(node), - hasLocals, nextState); - - // reconstruct the stack - if (top != 0) { - generateGetGeneratorStackState(); - for (int i = 0; i < top; i++) { - cfw.add(ByteCode.DUP); - cfw.addLoadConstant(top - i - 1); - cfw.add(ByteCode.AALOAD); - cfw.add(ByteCode.SWAP); - } - cfw.add(ByteCode.POP); - } - - // load return value from yield - if (exprContext) { - cfw.addALoad(argsLocal); - } - } - - private void generateCheckForThrowOrClose(int label, - boolean hasLocals, - int nextState) { - int throwLabel = cfw.acquireLabel(); - int closeLabel = cfw.acquireLabel(); - - // throw the user provided object, if the operation is .throw() - cfw.markLabel(throwLabel); - cfw.addALoad(argsLocal); - generateThrowJavaScriptException(); - - // throw our special internal exception if the generator is being closed - cfw.markLabel(closeLabel); - cfw.addALoad(argsLocal); - cfw.add(ByteCode.CHECKCAST, "java/lang/Throwable"); - cfw.add(ByteCode.ATHROW); - - // mark the re-entry point - // jump here after initializing the locals - if (label != -1) - cfw.markLabel(label); - if (!hasLocals) { - // jump here directly if there are no locals - cfw.markTableSwitchCase(generatorSwitch, nextState); - } - - // see if we need to dispatch for .close() or .throw() - cfw.addILoad(operationLocal); - cfw.addLoadConstant(NativeGenerator.GENERATOR_CLOSE); - cfw.add(ByteCode.IF_ICMPEQ, closeLabel); - cfw.addILoad(operationLocal); - cfw.addLoadConstant(NativeGenerator.GENERATOR_THROW); - cfw.add(ByteCode.IF_ICMPEQ, throwLabel); - } - - private void generateIfJump(Node node, Node parent, - int trueLabel, int falseLabel) - { - // System.out.println("gen code for " + node.toString()); - - int type = node.getType(); - Node child = node.getFirstChild(); - - switch (type) { - case Token.NOT: - generateIfJump(child, node, falseLabel, trueLabel); - break; - - case Token.OR: - case Token.AND: { - int interLabel = cfw.acquireLabel(); - if (type == Token.AND) { - generateIfJump(child, node, interLabel, falseLabel); - } - else { - generateIfJump(child, node, trueLabel, interLabel); - } - cfw.markLabel(interLabel); - child = child.getNext(); - generateIfJump(child, node, trueLabel, falseLabel); - break; - } - - case Token.IN: - case Token.INSTANCEOF: - case Token.LE: - case Token.LT: - case Token.GE: - case Token.GT: - visitIfJumpRelOp(node, child, trueLabel, falseLabel); - break; - - case Token.EQ: - case Token.NE: - case Token.SHEQ: - case Token.SHNE: - visitIfJumpEqOp(node, child, trueLabel, falseLabel); - break; - - default: - // Generate generic code for non-optimized jump - generateExpression(node, parent); - addScriptRuntimeInvoke("toBoolean", "(Ljava/lang/Object;)Z"); - cfw.add(ByteCode.IFNE, trueLabel); - cfw.add(ByteCode.GOTO, falseLabel); - } - } - - private void visitFunction(OptFunctionNode ofn, int functionType) - { - int fnIndex = codegen.getIndex(ofn.fnode); - cfw.add(ByteCode.NEW, codegen.mainClassName); - // Call function constructor - cfw.add(ByteCode.DUP); - cfw.addALoad(variableObjectLocal); - cfw.addALoad(contextLocal); // load 'cx' - cfw.addPush(fnIndex); - cfw.addInvoke(ByteCode.INVOKESPECIAL, codegen.mainClassName, - "<init>", Codegen.FUNCTION_CONSTRUCTOR_SIGNATURE); - - // Init mainScript field; - cfw.add(ByteCode.DUP); - if (isTopLevel) { - cfw.add(ByteCode.ALOAD_0); - } else { - cfw.add(ByteCode.ALOAD_0); - cfw.add(ByteCode.GETFIELD, - codegen.mainClassName, - Codegen.DIRECT_CALL_PARENT_FIELD, - codegen.mainClassSignature); - } - cfw.add(ByteCode.PUTFIELD, - codegen.mainClassName, - Codegen.DIRECT_CALL_PARENT_FIELD, - codegen.mainClassSignature); - - int directTargetIndex = ofn.getDirectTargetIndex(); - if (directTargetIndex >= 0) { - cfw.add(ByteCode.DUP); - if (isTopLevel) { - cfw.add(ByteCode.ALOAD_0); - } else { - cfw.add(ByteCode.ALOAD_0); - cfw.add(ByteCode.GETFIELD, - codegen.mainClassName, - Codegen.DIRECT_CALL_PARENT_FIELD, - codegen.mainClassSignature); - } - cfw.add(ByteCode.SWAP); - cfw.add(ByteCode.PUTFIELD, - codegen.mainClassName, - Codegen.getDirectTargetFieldName(directTargetIndex), - codegen.mainClassSignature); - } - - if (functionType == FunctionNode.FUNCTION_EXPRESSION) { - // Leave closure object on stack and do not pass it to - // initFunction which suppose to connect statements to scope - return; - } - cfw.addPush(functionType); - cfw.addALoad(variableObjectLocal); - cfw.addALoad(contextLocal); // load 'cx' - addOptRuntimeInvoke("initFunction", - "(Lorg/mozilla/javascript/NativeFunction;" - +"I" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Context;" - +")V"); - } - - private int getTargetLabel(Node target) - { - int labelId = target.labelId(); - if (labelId == -1) { - labelId = cfw.acquireLabel(); - target.labelId(labelId); - } - return labelId; - } - - private void visitGoto(Node.Jump node, int type, Node child) - { - Node target = node.target; - if (type == Token.IFEQ || type == Token.IFNE) { - if (child == null) throw Codegen.badTree(); - int targetLabel = getTargetLabel(target); - int fallThruLabel = cfw.acquireLabel(); - if (type == Token.IFEQ) - generateIfJump(child, node, targetLabel, fallThruLabel); - else - generateIfJump(child, node, fallThruLabel, targetLabel); - cfw.markLabel(fallThruLabel); - } else { - if (type == Token.JSR) { - if (isGenerator) { - addGotoWithReturn(target); - } else { - addGoto(target, ByteCode.JSR); - } - } else { - addGoto(target, ByteCode.GOTO); - } - } - } - - private void addGotoWithReturn(Node target) { - FinallyReturnPoint ret = - (FinallyReturnPoint)finallys.get(target); - cfw.addLoadConstant(ret.jsrPoints.size()); - addGoto(target, ByteCode.GOTO); - int retLabel = cfw.acquireLabel(); - cfw.markLabel(retLabel); - ret.jsrPoints.add(Integer.valueOf(retLabel)); - } - - private void visitArrayLiteral(Node node, Node child) - { - int count = 0; - for (Node cursor = child; cursor != null; cursor = cursor.getNext()) { - ++count; - } - // load array to store array literal objects - addNewObjectArray(count); - for (int i = 0; i != count; ++i) { - cfw.add(ByteCode.DUP); - cfw.addPush(i); - generateExpression(child, node); - cfw.add(ByteCode.AASTORE); - child = child.getNext(); - } - int[] skipIndexes = (int[])node.getProp(Node.SKIP_INDEXES_PROP); - if (skipIndexes == null) { - cfw.add(ByteCode.ACONST_NULL); - cfw.add(ByteCode.ICONST_0); - } else { - cfw.addPush(OptRuntime.encodeIntArray(skipIndexes)); - cfw.addPush(skipIndexes.length); - } - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - addOptRuntimeInvoke("newArrayLiteral", - "([Ljava/lang/Object;" - +"Ljava/lang/String;" - +"I" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - } - - private void visitObjectLiteral(Node node, Node child) - { - Object[] properties = (Object[])node.getProp(Node.OBJECT_IDS_PROP); - int count = properties.length; - - // load array with property ids - addNewObjectArray(count); - for (int i = 0; i != count; ++i) { - cfw.add(ByteCode.DUP); - cfw.addPush(i); - Object id = properties[i]; - if (id instanceof String) { - cfw.addPush((String)id); - } else { - cfw.addPush(((Integer)id).intValue()); - addScriptRuntimeInvoke("wrapInt", "(I)Ljava/lang/Integer;"); - } - cfw.add(ByteCode.AASTORE); - } - // load array with property values - addNewObjectArray(count); - Node child2 = child; - for (int i = 0; i != count; ++i) { - cfw.add(ByteCode.DUP); - cfw.addPush(i); - int childType = child.getType(); - if (childType == Token.GET) { - generateExpression(child.getFirstChild(), node); - } else if (childType == Token.SET) { - generateExpression(child.getFirstChild(), node); - } else { - generateExpression(child, node); - } - cfw.add(ByteCode.AASTORE); - child = child.getNext(); - } - // load array with getterSetter values - cfw.addPush(count); - cfw.add(ByteCode.NEWARRAY, ByteCode.T_INT); - for (int i = 0; i != count; ++i) { - cfw.add(ByteCode.DUP); - cfw.addPush(i); - int childType = child2.getType(); - if (childType == Token.GET) { - cfw.add(ByteCode.ICONST_M1); - } else if (childType == Token.SET) { - cfw.add(ByteCode.ICONST_1); - } else { - cfw.add(ByteCode.ICONST_0); - } - cfw.add(ByteCode.IASTORE); - child2 = child2.getNext(); - } - - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke("newObjectLiteral", - "([Ljava/lang/Object;" - +"[Ljava/lang/Object;" - +"[I" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - } - - private void visitSpecialCall(Node node, int type, int specialType, - Node child) - { - cfw.addALoad(contextLocal); - - if (type == Token.NEW) { - generateExpression(child, node); - // stack: ... cx functionObj - } else { - generateFunctionAndThisObj(child, node); - // stack: ... cx functionObj thisObj - } - child = child.getNext(); - - generateCallArgArray(node, child, false); - - String methodName; - String callSignature; - - if (type == Token.NEW) { - methodName = "newObjectSpecial"; - callSignature = "(Lorg/mozilla/javascript/Context;" - +"Ljava/lang/Object;" - +"[Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"I" // call type - +")Ljava/lang/Object;"; - cfw.addALoad(variableObjectLocal); - cfw.addALoad(thisObjLocal); - cfw.addPush(specialType); - } else { - methodName = "callSpecial"; - callSignature = "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Callable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"I" // call type - +"Ljava/lang/String;I" // filename, linenumber - +")Ljava/lang/Object;"; - cfw.addALoad(variableObjectLocal); - cfw.addALoad(thisObjLocal); - cfw.addPush(specialType); - String sourceName = scriptOrFn.getSourceName(); - cfw.addPush(sourceName == null ? "" : sourceName); - cfw.addPush(itsLineNumber); - } - - addOptRuntimeInvoke(methodName, callSignature); - } - - private void visitStandardCall(Node node, Node child) - { - if (node.getType() != Token.CALL) throw Codegen.badTree(); - - Node firstArgChild = child.getNext(); - int childType = child.getType(); - - String methodName; - String signature; - - if (firstArgChild == null) { - if (childType == Token.NAME) { - // name() call - String name = child.getString(); - cfw.addPush(name); - methodName = "callName0"; - signature = "(Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"; - } else if (childType == Token.GETPROP) { - // x.name() call - Node propTarget = child.getFirstChild(); - generateExpression(propTarget, node); - Node id = propTarget.getNext(); - String property = id.getString(); - cfw.addPush(property); - methodName = "callProp0"; - signature = "(Ljava/lang/Object;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"; - } else if (childType == Token.GETPROPNOWARN) { - throw Kit.codeBug(); - } else { - generateFunctionAndThisObj(child, node); - methodName = "call0"; - signature = "(Lorg/mozilla/javascript/Callable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"; - } - - } else if (childType == Token.NAME) { - // XXX: this optimization is only possible if name - // resolution - // is not affected by arguments evaluation and currently - // there are no checks for it - String name = child.getString(); - generateCallArgArray(node, firstArgChild, false); - cfw.addPush(name); - methodName = "callName"; - signature = "([Ljava/lang/Object;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"; - } else { - int argCount = 0; - for (Node arg = firstArgChild; arg != null; arg = arg.getNext()) { - ++argCount; - } - generateFunctionAndThisObj(child, node); - // stack: ... functionObj thisObj - if (argCount == 1) { - generateExpression(firstArgChild, node); - methodName = "call1"; - signature = "(Lorg/mozilla/javascript/Callable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"; - } else if (argCount == 2) { - generateExpression(firstArgChild, node); - generateExpression(firstArgChild.getNext(), node); - methodName = "call2"; - signature = "(Lorg/mozilla/javascript/Callable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"; - } else { - generateCallArgArray(node, firstArgChild, false); - methodName = "callN"; - signature = "(Lorg/mozilla/javascript/Callable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"; - } - } - - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - addOptRuntimeInvoke(methodName, signature); - } - - private void visitStandardNew(Node node, Node child) - { - if (node.getType() != Token.NEW) throw Codegen.badTree(); - - Node firstArgChild = child.getNext(); - - generateExpression(child, node); - // stack: ... functionObj - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - // stack: ... functionObj cx scope - generateCallArgArray(node, firstArgChild, false); - addScriptRuntimeInvoke( - "newObject", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +")Lorg/mozilla/javascript/Scriptable;"); - } - - private void visitOptimizedCall(Node node, OptFunctionNode target, - int type, Node child) - { - Node firstArgChild = child.getNext(); - - short thisObjLocal = 0; - if (type == Token.NEW) { - generateExpression(child, node); - } else { - generateFunctionAndThisObj(child, node); - thisObjLocal = getNewWordLocal(); - cfw.addAStore(thisObjLocal); - } - // stack: ... functionObj - - int beyond = cfw.acquireLabel(); - - int directTargetIndex = target.getDirectTargetIndex(); - if (isTopLevel) { - cfw.add(ByteCode.ALOAD_0); - } else { - cfw.add(ByteCode.ALOAD_0); - cfw.add(ByteCode.GETFIELD, codegen.mainClassName, - Codegen.DIRECT_CALL_PARENT_FIELD, - codegen.mainClassSignature); - } - cfw.add(ByteCode.GETFIELD, codegen.mainClassName, - Codegen.getDirectTargetFieldName(directTargetIndex), - codegen.mainClassSignature); - - cfw.add(ByteCode.DUP2); - // stack: ... functionObj directFunct functionObj directFunct - - int regularCall = cfw.acquireLabel(); - cfw.add(ByteCode.IF_ACMPNE, regularCall); - - // stack: ... functionObj directFunct - short stackHeight = cfw.getStackTop(); - cfw.add(ByteCode.SWAP); - cfw.add(ByteCode.POP); - // stack: ... directFunct - if (compilerEnv.isUseDynamicScope()) { - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - } else { - cfw.add(ByteCode.DUP); - // stack: ... directFunct directFunct - cfw.addInvoke(ByteCode.INVOKEINTERFACE, - "org/mozilla/javascript/Scriptable", - "getParentScope", - "()Lorg/mozilla/javascript/Scriptable;"); - // stack: ... directFunct scope - cfw.addALoad(contextLocal); - // stack: ... directFunct scope cx - cfw.add(ByteCode.SWAP); - } - // stack: ... directFunc cx scope - - if (type == Token.NEW) { - cfw.add(ByteCode.ACONST_NULL); - } else { - cfw.addALoad(thisObjLocal); - } - // stack: ... directFunc cx scope thisObj -/* -Remember that directCall parameters are paired in 1 aReg and 1 dReg -If the argument is an incoming arg, just pass the orginal pair thru. -Else, if the argument is known to be typed 'Number', pass Void.TYPE -in the aReg and the number is the dReg -Else pass the JS object in the aReg and 0.0 in the dReg. -*/ - Node argChild = firstArgChild; - while (argChild != null) { - int dcp_register = nodeIsDirectCallParameter(argChild); - if (dcp_register >= 0) { - cfw.addALoad(dcp_register); - cfw.addDLoad(dcp_register + 1); - } else if (argChild.getIntProp(Node.ISNUMBER_PROP, -1) - == Node.BOTH) - { - cfw.add(ByteCode.GETSTATIC, - "java/lang/Void", - "TYPE", - "Ljava/lang/Class;"); - generateExpression(argChild, node); - } else { - generateExpression(argChild, node); - cfw.addPush(0.0); - } - argChild = argChild.getNext(); - } - - cfw.add(ByteCode.GETSTATIC, - "org/mozilla/javascript/ScriptRuntime", - "emptyArgs", "[Ljava/lang/Object;"); - cfw.addInvoke(ByteCode.INVOKESTATIC, - codegen.mainClassName, - (type == Token.NEW) - ? codegen.getDirectCtorName(target.fnode) - : codegen.getBodyMethodName(target.fnode), - codegen.getBodyMethodSignature(target.fnode)); - - cfw.add(ByteCode.GOTO, beyond); - - cfw.markLabel(regularCall, stackHeight); - // stack: ... functionObj directFunct - cfw.add(ByteCode.POP); - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - // stack: ... functionObj cx scope - if (type != Token.NEW) { - cfw.addALoad(thisObjLocal); - releaseWordLocal(thisObjLocal); - // stack: ... functionObj cx scope thisObj - } - // XXX: this will generate code for the child array the second time, - // so expression code generation better not to alter tree structure... - generateCallArgArray(node, firstArgChild, true); - - if (type == Token.NEW) { - addScriptRuntimeInvoke( - "newObject", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +")Lorg/mozilla/javascript/Scriptable;"); - } else { - cfw.addInvoke(ByteCode.INVOKEINTERFACE, - "org/mozilla/javascript/Callable", - "call", - "(Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Lorg/mozilla/javascript/Scriptable;" - +"[Ljava/lang/Object;" - +")Ljava/lang/Object;"); - } - - cfw.markLabel(beyond); - } - - private void generateCallArgArray(Node node, Node argChild, boolean directCall) - { - int argCount = 0; - for (Node child = argChild; child != null; child = child.getNext()) { - ++argCount; - } - // load array object to set arguments - if (argCount == 1 && itsOneArgArray >= 0) { - cfw.addALoad(itsOneArgArray); - } else { - addNewObjectArray(argCount); - } - // Copy arguments into it - for (int i = 0; i != argCount; ++i) { - // If we are compiling a generator an argument could be the result - // of a yield. In that case we will have an immediate on the stack - // which we need to avoid - if (!isGenerator) { - cfw.add(ByteCode.DUP); - cfw.addPush(i); - } - - if (!directCall) { - generateExpression(argChild, node); - } else { - // If this has also been a directCall sequence, the Number - // flag will have remained set for any parameter so that - // the values could be copied directly into the outgoing - // args. Here we want to force it to be treated as not in - // a Number context, so we set the flag off. - int dcp_register = nodeIsDirectCallParameter(argChild); - if (dcp_register >= 0) { - dcpLoadAsObject(dcp_register); - } else { - generateExpression(argChild, node); - int childNumberFlag - = argChild.getIntProp(Node.ISNUMBER_PROP, -1); - if (childNumberFlag == Node.BOTH) { - addDoubleWrap(); - } - } - } - - // When compiling generators, any argument to a method may be a - // yield expression. Hence we compile the argument first and then - // load the argument index and assign the value to the args array. - if (isGenerator) { - short tempLocal = getNewWordLocal(); - cfw.addAStore(tempLocal); - cfw.add(ByteCode.CHECKCAST, "[Ljava/lang/Object;"); - cfw.add(ByteCode.DUP); - cfw.addPush(i); - cfw.addALoad(tempLocal); - releaseWordLocal(tempLocal); - } - - cfw.add(ByteCode.AASTORE); - - argChild = argChild.getNext(); - } - } - - private void generateFunctionAndThisObj(Node node, Node parent) - { - // Place on stack (function object, function this) pair - int type = node.getType(); - switch (node.getType()) { - case Token.GETPROPNOWARN: - throw Kit.codeBug(); - - case Token.GETPROP: - case Token.GETELEM: { - Node target = node.getFirstChild(); - generateExpression(target, node); - Node id = target.getNext(); - if (type == Token.GETPROP) { - String property = id.getString(); - cfw.addPush(property); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "getPropFunctionAndThis", - "(Ljava/lang/Object;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +")Lorg/mozilla/javascript/Callable;"); - } else { - // Optimizer do not optimize this case for now - if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) - throw Codegen.badTree(); - generateExpression(id, node); // id - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "getElemFunctionAndThis", - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Lorg/mozilla/javascript/Callable;"); - } - break; - } - - case Token.NAME: { - String name = node.getString(); - cfw.addPush(name); - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke( - "getNameFunctionAndThis", - "(Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Callable;"); - break; - } - - default: // including GETVAR - generateExpression(node, parent); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "getValueFunctionAndThis", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Lorg/mozilla/javascript/Callable;"); - break; - } - // Get thisObj prepared by get(Name|Prop|Elem|Value)FunctionAndThis - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "lastStoredScriptable", - "(Lorg/mozilla/javascript/Context;" - +")Lorg/mozilla/javascript/Scriptable;"); - } - - private void updateLineNumber(Node node) - { - itsLineNumber = node.getLineno(); - if (itsLineNumber == -1) - return; - cfw.addLineNumberEntry((short)itsLineNumber); - } - - private void visitTryCatchFinally(Node.Jump node, Node child) - { - /* Save the variable object, in case there are with statements - * enclosed by the try block and we catch some exception. - * We'll restore it for the catch block so that catch block - * statements get the right scope. - */ - - // OPT we only need to do this if there are enclosed WITH - // statements; could statically check and omit this if there aren't any. - - // XXX OPT Maybe instead do syntactic transforms to associate - // each 'with' with a try/finally block that does the exitwith. - - short savedVariableObject = getNewWordLocal(); - cfw.addALoad(variableObjectLocal); - cfw.addAStore(savedVariableObject); - - /* - * Generate the code for the tree; most of the work is done in IRFactory - * and NodeTransformer; Codegen just adds the java handlers for the - * javascript catch and finally clauses. */ - - int startLabel = cfw.acquireLabel(); - cfw.markLabel(startLabel, (short)0); - - Node catchTarget = node.target; - Node finallyTarget = node.getFinally(); - - // create a table for the equivalent of JSR returns - if (isGenerator && finallyTarget != null) { - FinallyReturnPoint ret = new FinallyReturnPoint(); - if (finallys == null) { - finallys = new Hashtable(); - } - // add the finally target to hashtable - finallys.put(finallyTarget, ret); - // add the finally node as well to the hash table - finallys.put(finallyTarget.getNext(), ret); - } - - while (child != null) { - generateStatement(child); - child = child.getNext(); - } - - // control flow skips the handlers - int realEnd = cfw.acquireLabel(); - cfw.add(ByteCode.GOTO, realEnd); - - int exceptionLocal = getLocalBlockRegister(node); - // javascript handler; unwrap exception and GOTO to javascript - // catch area. - if (catchTarget != null) { - // get the label to goto - int catchLabel = catchTarget.labelId(); - - generateCatchBlock(JAVASCRIPT_EXCEPTION, savedVariableObject, - catchLabel, startLabel, exceptionLocal); - /* - * catch WrappedExceptions, see if they are wrapped - * JavaScriptExceptions. Otherwise, rethrow. - */ - generateCatchBlock(EVALUATOR_EXCEPTION, savedVariableObject, - catchLabel, startLabel, exceptionLocal); - - /* - we also need to catch EcmaErrors and feed the - associated error object to the handler - */ - generateCatchBlock(ECMAERROR_EXCEPTION, savedVariableObject, - catchLabel, startLabel, exceptionLocal); - - Context cx = Context.getCurrentContext(); - if (cx != null && - cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS)) - { - generateCatchBlock(THROWABLE_EXCEPTION, savedVariableObject, - catchLabel, startLabel, exceptionLocal); - } - } - - // finally handler; catch all exceptions, store to a local; JSR to - // the finally, then re-throw. - if (finallyTarget != null) { - int finallyHandler = cfw.acquireLabel(); - cfw.markHandler(finallyHandler); - cfw.addAStore(exceptionLocal); - - // reset the variable object local - cfw.addALoad(savedVariableObject); - cfw.addAStore(variableObjectLocal); - - // get the label to JSR to - int finallyLabel = finallyTarget.labelId(); - if (isGenerator) - addGotoWithReturn(finallyTarget); - else - cfw.add(ByteCode.JSR, finallyLabel); - - // rethrow - cfw.addALoad(exceptionLocal); - if (isGenerator) - cfw.add(ByteCode.CHECKCAST, "java/lang/Throwable"); - cfw.add(ByteCode.ATHROW); - - // mark the handler - cfw.addExceptionHandler(startLabel, finallyLabel, - finallyHandler, null); // catch any - } - releaseWordLocal(savedVariableObject); - cfw.markLabel(realEnd); - } - - private static final int JAVASCRIPT_EXCEPTION = 0; - private static final int EVALUATOR_EXCEPTION = 1; - private static final int ECMAERROR_EXCEPTION = 2; - private static final int THROWABLE_EXCEPTION = 3; - - private void generateCatchBlock(int exceptionType, - short savedVariableObject, - int catchLabel, int startLabel, - int exceptionLocal) - { - int handler = cfw.acquireLabel(); - cfw.markHandler(handler); - - // MS JVM gets cranky if the exception object is left on the stack - cfw.addAStore(exceptionLocal); - - // reset the variable object local - cfw.addALoad(savedVariableObject); - cfw.addAStore(variableObjectLocal); - - String exceptionName; - if (exceptionType == JAVASCRIPT_EXCEPTION) { - exceptionName = "org/mozilla/javascript/JavaScriptException"; - } else if (exceptionType == EVALUATOR_EXCEPTION) { - exceptionName = "org/mozilla/javascript/EvaluatorException"; - } else if (exceptionType == ECMAERROR_EXCEPTION) { - exceptionName = "org/mozilla/javascript/EcmaError"; - } else if (exceptionType == THROWABLE_EXCEPTION) { - exceptionName = "java/lang/Throwable"; - } else { - throw Kit.codeBug(); - } - - // mark the handler - cfw.addExceptionHandler(startLabel, catchLabel, handler, - exceptionName); - - cfw.add(ByteCode.GOTO, catchLabel); - } - - - private boolean generateSaveLocals(Node node) - { - int count = 0; - for (int i = 0; i < firstFreeLocal; i++) { - if (locals[i] != 0) - count++; - } - - if (count == 0) { - ((FunctionNode)scriptOrFn).addLiveLocals(node, null); - return false; - } - - // calculate the max locals - maxLocals = maxLocals > count ? maxLocals : count; - - // create a locals list - int[] ls = new int[count]; - int s = 0; - for (int i = 0; i < firstFreeLocal; i++) { - if (locals[i] != 0) { - ls[s] = i; - s++; - } - } - - // save the locals - ((FunctionNode)scriptOrFn).addLiveLocals(node, ls); - - // save locals - generateGetGeneratorLocalsState(); - for (int i = 0; i < count; i++) { - cfw.add(ByteCode.DUP); - cfw.addLoadConstant(i); - cfw.addALoad(ls[i]); - cfw.add(ByteCode.AASTORE); - } - // pop the array off the stack - cfw.add(ByteCode.POP); - - return true; - } - - private void visitSwitch(Node.Jump switchNode, Node child) - { - // See comments in IRFactory.createSwitch() for description - // of SWITCH node - - generateExpression(child, switchNode); - // save selector value - short selector = getNewWordLocal(); - cfw.addAStore(selector); - - for (Node.Jump caseNode = (Node.Jump)child.getNext(); - caseNode != null; - caseNode = (Node.Jump)caseNode.getNext()) - { - if (caseNode.getType() != Token.CASE) - throw Codegen.badTree(); - Node test = caseNode.getFirstChild(); - generateExpression(test, caseNode); - cfw.addALoad(selector); - addScriptRuntimeInvoke("shallowEq", - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +")Z"); - addGoto(caseNode.target, ByteCode.IFNE); - } - releaseWordLocal(selector); - } - - private void visitTypeofname(Node node) - { - if (hasVarsInRegs) { - int varIndex = fnCurrent.fnode.getIndexForNameNode(node); - if (varIndex >= 0) { - if (fnCurrent.isNumberVar(varIndex)) { - cfw.addPush("number"); - } else if (varIsDirectCallParameter(varIndex)) { - int dcp_register = varRegisters[varIndex]; - cfw.addALoad(dcp_register); - cfw.add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", - "Ljava/lang/Class;"); - int isNumberLabel = cfw.acquireLabel(); - cfw.add(ByteCode.IF_ACMPEQ, isNumberLabel); - short stack = cfw.getStackTop(); - cfw.addALoad(dcp_register); - addScriptRuntimeInvoke("typeof", - "(Ljava/lang/Object;" - +")Ljava/lang/String;"); - int beyond = cfw.acquireLabel(); - cfw.add(ByteCode.GOTO, beyond); - cfw.markLabel(isNumberLabel, stack); - cfw.addPush("number"); - cfw.markLabel(beyond); - } else { - cfw.addALoad(varRegisters[varIndex]); - addScriptRuntimeInvoke("typeof", - "(Ljava/lang/Object;" - +")Ljava/lang/String;"); - } - return; - } - } - cfw.addALoad(variableObjectLocal); - cfw.addPush(node.getString()); - addScriptRuntimeInvoke("typeofName", - "(Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +")Ljava/lang/String;"); - } - - /** - * Save the current code offset. This saved code offset is used to - * compute instruction counts in subsequent calls to - * {@link #addInstructionCount}. - */ - private void saveCurrentCodeOffset() { - savedCodeOffset = cfw.getCurrentCodeOffset(); - } - - /** - * Generate calls to ScriptRuntime.addInstructionCount to keep track of - * executed instructions and call <code>observeInstructionCount()</code> - * if a threshold is exceeded. - */ - private void addInstructionCount() { - int count = cfw.getCurrentCodeOffset() - savedCodeOffset; - if (count == 0) - return; - cfw.addALoad(contextLocal); - cfw.addPush(count); - addScriptRuntimeInvoke("addInstructionCount", - "(Lorg/mozilla/javascript/Context;" - +"I)V"); - } - - private void visitIncDec(Node node) - { - int incrDecrMask = node.getExistingIntProp(Node.INCRDECR_PROP); - Node child = node.getFirstChild(); - switch (child.getType()) { - case Token.GETVAR: - if (!hasVarsInRegs) Kit.codeBug(); - if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { - boolean post = ((incrDecrMask & Node.POST_FLAG) != 0); - int varIndex = fnCurrent.getVarIndex(child); - short reg = varRegisters[varIndex]; - int offset = varIsDirectCallParameter(varIndex) ? 1 : 0; - cfw.addDLoad(reg + offset); - if (post) { - cfw.add(ByteCode.DUP2); - } - cfw.addPush(1.0); - if ((incrDecrMask & Node.DECR_FLAG) == 0) { - cfw.add(ByteCode.DADD); - } else { - cfw.add(ByteCode.DSUB); - } - if (!post) { - cfw.add(ByteCode.DUP2); - } - cfw.addDStore(reg + offset); - } else { - boolean post = ((incrDecrMask & Node.POST_FLAG) != 0); - int varIndex = fnCurrent.getVarIndex(child); - short reg = varRegisters[varIndex]; - cfw.addALoad(reg); - if (post) { - cfw.add(ByteCode.DUP); - } - addObjectToDouble(); - cfw.addPush(1.0); - if ((incrDecrMask & Node.DECR_FLAG) == 0) { - cfw.add(ByteCode.DADD); - } else { - cfw.add(ByteCode.DSUB); - } - addDoubleWrap(); - if (!post) { - cfw.add(ByteCode.DUP); - } - cfw.addAStore(reg); - break; - } - break; - case Token.NAME: - cfw.addALoad(variableObjectLocal); - cfw.addPush(child.getString()); // push name - cfw.addALoad(contextLocal); - cfw.addPush(incrDecrMask); - addScriptRuntimeInvoke("nameIncrDecr", - "(Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +"I)Ljava/lang/Object;"); - break; - case Token.GETPROPNOWARN: - throw Kit.codeBug(); - case Token.GETPROP: { - Node getPropChild = child.getFirstChild(); - generateExpression(getPropChild, node); - generateExpression(getPropChild.getNext(), node); - cfw.addALoad(contextLocal); - cfw.addPush(incrDecrMask); - addScriptRuntimeInvoke("propIncrDecr", - "(Ljava/lang/Object;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +"I)Ljava/lang/Object;"); - break; - } - case Token.GETELEM: { - Node elemChild = child.getFirstChild(); - generateExpression(elemChild, node); - generateExpression(elemChild.getNext(), node); - cfw.addALoad(contextLocal); - cfw.addPush(incrDecrMask); - if (elemChild.getNext().getIntProp(Node.ISNUMBER_PROP, -1) != -1) { - addOptRuntimeInvoke("elemIncrDecr", - "(Ljava/lang/Object;" - +"D" - +"Lorg/mozilla/javascript/Context;" - +"I" - +")Ljava/lang/Object;"); - } else { - addScriptRuntimeInvoke("elemIncrDecr", - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"I" - +")Ljava/lang/Object;"); - } - break; - } - case Token.GET_REF: { - Node refChild = child.getFirstChild(); - generateExpression(refChild, node); - cfw.addALoad(contextLocal); - cfw.addPush(incrDecrMask); - addScriptRuntimeInvoke( - "refIncrDecr", - "(Lorg/mozilla/javascript/Ref;" - +"Lorg/mozilla/javascript/Context;" - +"I)Ljava/lang/Object;"); - break; - } - default: - Codegen.badTree(); - } - } - - private static boolean isArithmeticNode(Node node) - { - int type = node.getType(); - return (type == Token.SUB) - || (type == Token.MOD) - || (type == Token.DIV) - || (type == Token.MUL); - } - - private void visitArithmetic(Node node, int opCode, Node child, - Node parent) - { - int childNumberFlag = node.getIntProp(Node.ISNUMBER_PROP, -1); - if (childNumberFlag != -1) { - generateExpression(child, node); - generateExpression(child.getNext(), node); - cfw.add(opCode); - } - else { - boolean childOfArithmetic = isArithmeticNode(parent); - generateExpression(child, node); - if (!isArithmeticNode(child)) - addObjectToDouble(); - generateExpression(child.getNext(), node); - if (!isArithmeticNode(child.getNext())) - addObjectToDouble(); - cfw.add(opCode); - if (!childOfArithmetic) { - addDoubleWrap(); - } - } - } - - private void visitBitOp(Node node, int type, Node child) - { - int childNumberFlag = node.getIntProp(Node.ISNUMBER_PROP, -1); - generateExpression(child, node); - - // special-case URSH; work with the target arg as a long, so - // that we can return a 32-bit unsigned value, and call - // toUint32 instead of toInt32. - if (type == Token.URSH) { - addScriptRuntimeInvoke("toUint32", "(Ljava/lang/Object;)J"); - generateExpression(child.getNext(), node); - addScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I"); - // Looks like we need to explicitly mask the shift to 5 bits - - // LUSHR takes 6 bits. - cfw.addPush(31); - cfw.add(ByteCode.IAND); - cfw.add(ByteCode.LUSHR); - cfw.add(ByteCode.L2D); - addDoubleWrap(); - return; - } - if (childNumberFlag == -1) { - addScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I"); - generateExpression(child.getNext(), node); - addScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I"); - } - else { - addScriptRuntimeInvoke("toInt32", "(D)I"); - generateExpression(child.getNext(), node); - addScriptRuntimeInvoke("toInt32", "(D)I"); - } - switch (type) { - case Token.BITOR: - cfw.add(ByteCode.IOR); - break; - case Token.BITXOR: - cfw.add(ByteCode.IXOR); - break; - case Token.BITAND: - cfw.add(ByteCode.IAND); - break; - case Token.RSH: - cfw.add(ByteCode.ISHR); - break; - case Token.LSH: - cfw.add(ByteCode.ISHL); - break; - default: - throw Codegen.badTree(); - } - cfw.add(ByteCode.I2D); - if (childNumberFlag == -1) { - addDoubleWrap(); - } - } - - private int nodeIsDirectCallParameter(Node node) - { - if (node.getType() == Token.GETVAR - && inDirectCallFunction && !itsForcedObjectParameters) - { - int varIndex = fnCurrent.getVarIndex(node); - if (fnCurrent.isParameter(varIndex)) { - return varRegisters[varIndex]; - } - } - return -1; - } - - private boolean varIsDirectCallParameter(int varIndex) - { - return fnCurrent.isParameter(varIndex) - && inDirectCallFunction && !itsForcedObjectParameters; - } - - private void genSimpleCompare(int type, int trueGOTO, int falseGOTO) - { - if (trueGOTO == -1) throw Codegen.badTree(); - switch (type) { - case Token.LE : - cfw.add(ByteCode.DCMPG); - cfw.add(ByteCode.IFLE, trueGOTO); - break; - case Token.GE : - cfw.add(ByteCode.DCMPL); - cfw.add(ByteCode.IFGE, trueGOTO); - break; - case Token.LT : - cfw.add(ByteCode.DCMPG); - cfw.add(ByteCode.IFLT, trueGOTO); - break; - case Token.GT : - cfw.add(ByteCode.DCMPL); - cfw.add(ByteCode.IFGT, trueGOTO); - break; - default : - throw Codegen.badTree(); - - } - if (falseGOTO != -1) - cfw.add(ByteCode.GOTO, falseGOTO); - } - - private void visitIfJumpRelOp(Node node, Node child, - int trueGOTO, int falseGOTO) - { - if (trueGOTO == -1 || falseGOTO == -1) throw Codegen.badTree(); - int type = node.getType(); - Node rChild = child.getNext(); - if (type == Token.INSTANCEOF || type == Token.IN) { - generateExpression(child, node); - generateExpression(rChild, node); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - (type == Token.INSTANCEOF) ? "instanceOf" : "in", - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Z"); - cfw.add(ByteCode.IFNE, trueGOTO); - cfw.add(ByteCode.GOTO, falseGOTO); - return; - } - int childNumberFlag = node.getIntProp(Node.ISNUMBER_PROP, -1); - int left_dcp_register = nodeIsDirectCallParameter(child); - int right_dcp_register = nodeIsDirectCallParameter(rChild); - if (childNumberFlag != -1) { - // Force numeric context on both parameters and optimize - // direct call case as Optimizer currently does not handle it - - if (childNumberFlag != Node.RIGHT) { - // Left already has number content - generateExpression(child, node); - } else if (left_dcp_register != -1) { - dcpLoadAsNumber(left_dcp_register); - } else { - generateExpression(child, node); - addObjectToDouble(); - } - - if (childNumberFlag != Node.LEFT) { - // Right already has number content - generateExpression(rChild, node); - } else if (right_dcp_register != -1) { - dcpLoadAsNumber(right_dcp_register); - } else { - generateExpression(rChild, node); - addObjectToDouble(); - } - - genSimpleCompare(type, trueGOTO, falseGOTO); - - } else { - if (left_dcp_register != -1 && right_dcp_register != -1) { - // Generate code to dynamically check for number content - // if both operands are dcp - short stack = cfw.getStackTop(); - int leftIsNotNumber = cfw.acquireLabel(); - cfw.addALoad(left_dcp_register); - cfw.add(ByteCode.GETSTATIC, - "java/lang/Void", - "TYPE", - "Ljava/lang/Class;"); - cfw.add(ByteCode.IF_ACMPNE, leftIsNotNumber); - cfw.addDLoad(left_dcp_register + 1); - dcpLoadAsNumber(right_dcp_register); - genSimpleCompare(type, trueGOTO, falseGOTO); - if (stack != cfw.getStackTop()) throw Codegen.badTree(); - - cfw.markLabel(leftIsNotNumber); - int rightIsNotNumber = cfw.acquireLabel(); - cfw.addALoad(right_dcp_register); - cfw.add(ByteCode.GETSTATIC, - "java/lang/Void", - "TYPE", - "Ljava/lang/Class;"); - cfw.add(ByteCode.IF_ACMPNE, rightIsNotNumber); - cfw.addALoad(left_dcp_register); - addObjectToDouble(); - cfw.addDLoad(right_dcp_register + 1); - genSimpleCompare(type, trueGOTO, falseGOTO); - if (stack != cfw.getStackTop()) throw Codegen.badTree(); - - cfw.markLabel(rightIsNotNumber); - // Load both register as objects to call generic cmp_* - cfw.addALoad(left_dcp_register); - cfw.addALoad(right_dcp_register); - - } else { - generateExpression(child, node); - generateExpression(rChild, node); - } - - if (type == Token.GE || type == Token.GT) { - cfw.add(ByteCode.SWAP); - } - String routine = ((type == Token.LT) - || (type == Token.GT)) ? "cmp_LT" : "cmp_LE"; - addScriptRuntimeInvoke(routine, - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +")Z"); - cfw.add(ByteCode.IFNE, trueGOTO); - cfw.add(ByteCode.GOTO, falseGOTO); - } - } - - private void visitIfJumpEqOp(Node node, Node child, - int trueGOTO, int falseGOTO) - { - if (trueGOTO == -1 || falseGOTO == -1) throw Codegen.badTree(); - - short stackInitial = cfw.getStackTop(); - int type = node.getType(); - Node rChild = child.getNext(); - - // Optimize if one of operands is null - if (child.getType() == Token.NULL || rChild.getType() == Token.NULL) { - // eq is symmetric in this case - if (child.getType() == Token.NULL) { - child = rChild; - } - generateExpression(child, node); - if (type == Token.SHEQ || type == Token.SHNE) { - int testCode = (type == Token.SHEQ) - ? ByteCode.IFNULL : ByteCode.IFNONNULL; - cfw.add(testCode, trueGOTO); - } else { - if (type != Token.EQ) { - // swap false/true targets for != - if (type != Token.NE) throw Codegen.badTree(); - int tmp = trueGOTO; - trueGOTO = falseGOTO; - falseGOTO = tmp; - } - cfw.add(ByteCode.DUP); - int undefCheckLabel = cfw.acquireLabel(); - cfw.add(ByteCode.IFNONNULL, undefCheckLabel); - short stack = cfw.getStackTop(); - cfw.add(ByteCode.POP); - cfw.add(ByteCode.GOTO, trueGOTO); - cfw.markLabel(undefCheckLabel, stack); - Codegen.pushUndefined(cfw); - cfw.add(ByteCode.IF_ACMPEQ, trueGOTO); - } - cfw.add(ByteCode.GOTO, falseGOTO); - } else { - int child_dcp_register = nodeIsDirectCallParameter(child); - if (child_dcp_register != -1 - && rChild.getType() == Token.TO_OBJECT) - { - Node convertChild = rChild.getFirstChild(); - if (convertChild.getType() == Token.NUMBER) { - cfw.addALoad(child_dcp_register); - cfw.add(ByteCode.GETSTATIC, - "java/lang/Void", - "TYPE", - "Ljava/lang/Class;"); - int notNumbersLabel = cfw.acquireLabel(); - cfw.add(ByteCode.IF_ACMPNE, notNumbersLabel); - cfw.addDLoad(child_dcp_register + 1); - cfw.addPush(convertChild.getDouble()); - cfw.add(ByteCode.DCMPL); - if (type == Token.EQ) - cfw.add(ByteCode.IFEQ, trueGOTO); - else - cfw.add(ByteCode.IFNE, trueGOTO); - cfw.add(ByteCode.GOTO, falseGOTO); - cfw.markLabel(notNumbersLabel); - // fall thru into generic handling - } - } - - generateExpression(child, node); - generateExpression(rChild, node); - - String name; - int testCode; - switch (type) { - case Token.EQ: - name = "eq"; - testCode = ByteCode.IFNE; - break; - case Token.NE: - name = "eq"; - testCode = ByteCode.IFEQ; - break; - case Token.SHEQ: - name = "shallowEq"; - testCode = ByteCode.IFNE; - break; - case Token.SHNE: - name = "shallowEq"; - testCode = ByteCode.IFEQ; - break; - default: - throw Codegen.badTree(); - } - addScriptRuntimeInvoke(name, - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +")Z"); - cfw.add(testCode, trueGOTO); - cfw.add(ByteCode.GOTO, falseGOTO); - } - if (stackInitial != cfw.getStackTop()) throw Codegen.badTree(); - } - - private void visitSetName(Node node, Node child) - { - String name = node.getFirstChild().getString(); - while (child != null) { - generateExpression(child, node); - child = child.getNext(); - } - cfw.addALoad(contextLocal); - cfw.addALoad(variableObjectLocal); - cfw.addPush(name); - addScriptRuntimeInvoke( - "setName", - "(Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +")Ljava/lang/Object;"); - } - - private void visitSetConst(Node node, Node child) - { - String name = node.getFirstChild().getString(); - while (child != null) { - generateExpression(child, node); - child = child.getNext(); - } - cfw.addALoad(contextLocal); - cfw.addPush(name); - addScriptRuntimeInvoke( - "setConst", - "(Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +"Ljava/lang/String;" - +")Ljava/lang/Object;"); - } - - private void visitGetVar(Node node) - { - if (!hasVarsInRegs) Kit.codeBug(); - int varIndex = fnCurrent.getVarIndex(node); - short reg = varRegisters[varIndex]; - if (varIsDirectCallParameter(varIndex)) { - // Remember that here the isNumber flag means that we - // want to use the incoming parameter in a Number - // context, so test the object type and convert the - // value as necessary. - if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { - dcpLoadAsNumber(reg); - } else { - dcpLoadAsObject(reg); - } - } else if (fnCurrent.isNumberVar(varIndex)) { - cfw.addDLoad(reg); - } else { - cfw.addALoad(reg); - } - } - - private void visitSetVar(Node node, Node child, boolean needValue) - { - if (!hasVarsInRegs) Kit.codeBug(); - int varIndex = fnCurrent.getVarIndex(node); - generateExpression(child.getNext(), node); - boolean isNumber = (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1); - short reg = varRegisters[varIndex]; - boolean [] constDeclarations = fnCurrent.fnode.getParamAndVarConst(); - if (constDeclarations[varIndex]) { - if (!needValue) { - if (isNumber) - cfw.add(ByteCode.POP2); - else - cfw.add(ByteCode.POP); - } - } - else if (varIsDirectCallParameter(varIndex)) { - if (isNumber) { - if (needValue) cfw.add(ByteCode.DUP2); - cfw.addALoad(reg); - cfw.add(ByteCode.GETSTATIC, - "java/lang/Void", - "TYPE", - "Ljava/lang/Class;"); - int isNumberLabel = cfw.acquireLabel(); - int beyond = cfw.acquireLabel(); - cfw.add(ByteCode.IF_ACMPEQ, isNumberLabel); - short stack = cfw.getStackTop(); - addDoubleWrap(); - cfw.addAStore(reg); - cfw.add(ByteCode.GOTO, beyond); - cfw.markLabel(isNumberLabel, stack); - cfw.addDStore(reg + 1); - cfw.markLabel(beyond); - } - else { - if (needValue) cfw.add(ByteCode.DUP); - cfw.addAStore(reg); - } - } else { - boolean isNumberVar = fnCurrent.isNumberVar(varIndex); - if (isNumber) { - if (isNumberVar) { - cfw.addDStore(reg); - if (needValue) cfw.addDLoad(reg); - } else { - if (needValue) cfw.add(ByteCode.DUP2); - // Cannot save number in variable since !isNumberVar, - // so convert to object - addDoubleWrap(); - cfw.addAStore(reg); - } - } else { - if (isNumberVar) Kit.codeBug(); - cfw.addAStore(reg); - if (needValue) cfw.addALoad(reg); - } - } - } - - private void visitSetConstVar(Node node, Node child, boolean needValue) - { - if (!hasVarsInRegs) Kit.codeBug(); - int varIndex = fnCurrent.getVarIndex(node); - generateExpression(child.getNext(), node); - boolean isNumber = (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1); - short reg = varRegisters[varIndex]; - int beyond = cfw.acquireLabel(); - int noAssign = cfw.acquireLabel(); - if (isNumber) { - cfw.addILoad(reg + 2); - cfw.add(ByteCode.IFNE, noAssign); - short stack = cfw.getStackTop(); - cfw.addPush(1); - cfw.addIStore(reg + 2); - cfw.addDStore(reg); - if (needValue) { - cfw.addDLoad(reg); - cfw.markLabel(noAssign, stack); - } else { - cfw.add(ByteCode.GOTO, beyond); - cfw.markLabel(noAssign, stack); - cfw.add(ByteCode.POP2); - } - } - else { - cfw.addILoad(reg + 1); - cfw.add(ByteCode.IFNE, noAssign); - short stack = cfw.getStackTop(); - cfw.addPush(1); - cfw.addIStore(reg + 1); - cfw.addAStore(reg); - if (needValue) { - cfw.addALoad(reg); - cfw.markLabel(noAssign, stack); - } else { - cfw.add(ByteCode.GOTO, beyond); - cfw.markLabel(noAssign, stack); - cfw.add(ByteCode.POP); - } - } - cfw.markLabel(beyond); - } - - private void visitGetProp(Node node, Node child) - { - generateExpression(child, node); // object - Node nameChild = child.getNext(); - generateExpression(nameChild, node); // the name - if (node.getType() == Token.GETPROPNOWARN) { - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "getObjectPropNoWarn", - "(Ljava/lang/Object;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - return; - } - /* - for 'this.foo' we call getObjectProp(Scriptable...) which can - skip some casting overhead. - */ - int childType = child.getType(); - if (childType == Token.THIS && nameChild.getType() == Token.STRING) { - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "getObjectProp", - "(Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } else { - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "getObjectProp", - "(Ljava/lang/Object;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - } - - private void visitSetProp(int type, Node node, Node child) - { - Node objectChild = child; - generateExpression(child, node); - child = child.getNext(); - if (type == Token.SETPROP_OP) { - cfw.add(ByteCode.DUP); - } - Node nameChild = child; - generateExpression(child, node); - child = child.getNext(); - if (type == Token.SETPROP_OP) { - // stack: ... object object name -> ... object name object name - cfw.add(ByteCode.DUP_X1); - //for 'this.foo += ...' we call thisGet which can skip some - //casting overhead. - if (objectChild.getType() == Token.THIS - && nameChild.getType() == Token.STRING) - { - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "getObjectProp", - "(Lorg/mozilla/javascript/Scriptable;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } else { - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "getObjectProp", - "(Ljava/lang/Object;" - +"Ljava/lang/String;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - } - generateExpression(child, node); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "setObjectProp", - "(Ljava/lang/Object;" - +"Ljava/lang/String;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - - private void visitSetElem(int type, Node node, Node child) - { - generateExpression(child, node); - child = child.getNext(); - if (type == Token.SETELEM_OP) { - cfw.add(ByteCode.DUP); - } - generateExpression(child, node); - child = child.getNext(); - boolean indexIsNumber = (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1); - if (type == Token.SETELEM_OP) { - if (indexIsNumber) { - // stack: ... object object number - // -> ... object number object number - cfw.add(ByteCode.DUP2_X1); - cfw.addALoad(contextLocal); - addOptRuntimeInvoke( - "getObjectIndex", - "(Ljava/lang/Object;D" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } else { - // stack: ... object object indexObject - // -> ... object indexObject object indexObject - cfw.add(ByteCode.DUP_X1); - cfw.addALoad(contextLocal); - addScriptRuntimeInvoke( - "getObjectElem", - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - } - generateExpression(child, node); - cfw.addALoad(contextLocal); - if (indexIsNumber) { - addScriptRuntimeInvoke( - "setObjectIndex", - "(Ljava/lang/Object;" - +"D" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } else { - addScriptRuntimeInvoke( - "setObjectElem", - "(Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Context;" - +")Ljava/lang/Object;"); - } - } - - private void visitDotQuery(Node node, Node child) - { - updateLineNumber(node); - generateExpression(child, node); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke("enterDotQuery", - "(Ljava/lang/Object;" - +"Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(variableObjectLocal); - - // add push null/pop with label in between to simplify code for loop - // continue when it is necessary to pop the null result from - // updateDotQuery - cfw.add(ByteCode.ACONST_NULL); - int queryLoopStart = cfw.acquireLabel(); - cfw.markLabel(queryLoopStart); // loop continue jumps here - cfw.add(ByteCode.POP); - - generateExpression(child.getNext(), node); - addScriptRuntimeInvoke("toBoolean", "(Ljava/lang/Object;)Z"); - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke("updateDotQuery", - "(Z" - +"Lorg/mozilla/javascript/Scriptable;" - +")Ljava/lang/Object;"); - cfw.add(ByteCode.DUP); - cfw.add(ByteCode.IFNULL, queryLoopStart); - // stack: ... non_null_result_of_updateDotQuery - cfw.addALoad(variableObjectLocal); - addScriptRuntimeInvoke("leaveDotQuery", - "(Lorg/mozilla/javascript/Scriptable;" - +")Lorg/mozilla/javascript/Scriptable;"); - cfw.addAStore(variableObjectLocal); - } - - private int getLocalBlockRegister(Node node) - { - Node localBlock = (Node)node.getProp(Node.LOCAL_BLOCK_PROP); - int localSlot = localBlock.getExistingIntProp(Node.LOCAL_PROP); - return localSlot; - } - - private void dcpLoadAsNumber(int dcp_register) - { - cfw.addALoad(dcp_register); - cfw.add(ByteCode.GETSTATIC, - "java/lang/Void", - "TYPE", - "Ljava/lang/Class;"); - int isNumberLabel = cfw.acquireLabel(); - cfw.add(ByteCode.IF_ACMPEQ, isNumberLabel); - short stack = cfw.getStackTop(); - cfw.addALoad(dcp_register); - addObjectToDouble(); - int beyond = cfw.acquireLabel(); - cfw.add(ByteCode.GOTO, beyond); - cfw.markLabel(isNumberLabel, stack); - cfw.addDLoad(dcp_register + 1); - cfw.markLabel(beyond); - } - - private void dcpLoadAsObject(int dcp_register) - { - cfw.addALoad(dcp_register); - cfw.add(ByteCode.GETSTATIC, - "java/lang/Void", - "TYPE", - "Ljava/lang/Class;"); - int isNumberLabel = cfw.acquireLabel(); - cfw.add(ByteCode.IF_ACMPEQ, isNumberLabel); - short stack = cfw.getStackTop(); - cfw.addALoad(dcp_register); - int beyond = cfw.acquireLabel(); - cfw.add(ByteCode.GOTO, beyond); - cfw.markLabel(isNumberLabel, stack); - cfw.addDLoad(dcp_register + 1); - addDoubleWrap(); - cfw.markLabel(beyond); - } - - private void addGoto(Node target, int jumpcode) - { - int targetLabel = getTargetLabel(target); - cfw.add(jumpcode, targetLabel); - } - - private void addObjectToDouble() - { - addScriptRuntimeInvoke("toNumber", "(Ljava/lang/Object;)D"); - } - - private void addNewObjectArray(int size) - { - if (size == 0) { - if (itsZeroArgArray >= 0) { - cfw.addALoad(itsZeroArgArray); - } else { - cfw.add(ByteCode.GETSTATIC, - "org/mozilla/javascript/ScriptRuntime", - "emptyArgs", "[Ljava/lang/Object;"); - } - } else { - cfw.addPush(size); - cfw.add(ByteCode.ANEWARRAY, "java/lang/Object"); - } - } - - private void addScriptRuntimeInvoke(String methodName, - String methodSignature) - { - cfw.addInvoke(ByteCode.INVOKESTATIC, - "org.mozilla.javascript.ScriptRuntime", - methodName, - methodSignature); - } - - private void addOptRuntimeInvoke(String methodName, - String methodSignature) - { - cfw.addInvoke(ByteCode.INVOKESTATIC, - "org/mozilla/javascript/optimizer/OptRuntime", - methodName, - methodSignature); - } - - private void addJumpedBooleanWrap(int trueLabel, int falseLabel) - { - cfw.markLabel(falseLabel); - int skip = cfw.acquireLabel(); - cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", - "FALSE", "Ljava/lang/Boolean;"); - cfw.add(ByteCode.GOTO, skip); - cfw.markLabel(trueLabel); - cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", - "TRUE", "Ljava/lang/Boolean;"); - cfw.markLabel(skip); - cfw.adjustStackTop(-1); // only have 1 of true/false - } - - private void addDoubleWrap() - { - addOptRuntimeInvoke("wrapDouble", "(D)Ljava/lang/Double;"); - } - - /** - * Const locals use an extra slot to hold the has-been-assigned-once flag at - * runtime. - * @param isConst true iff the variable is const - * @return the register for the word pair (double/long) - */ - private short getNewWordPairLocal(boolean isConst) - { - short result = getConsecutiveSlots(2, isConst); - if (result < (MAX_LOCALS - 1)) { - locals[result] = 1; - locals[result + 1] = 1; - if (isConst) - locals[result + 2] = 1; - if (result == firstFreeLocal) { - for (int i = firstFreeLocal + 2; i < MAX_LOCALS; i++) { - if (locals[i] == 0) { - firstFreeLocal = (short) i; - if (localsMax < firstFreeLocal) - localsMax = firstFreeLocal; - return result; - } - } - } - else { - return result; - } - } - throw Context.reportRuntimeError("Program too complex " + - "(out of locals)"); - } - - private short getNewWordLocal(boolean isConst) - { - short result = getConsecutiveSlots(1, isConst); - if (result < (MAX_LOCALS - 1)) { - locals[result] = 1; - if (isConst) - locals[result + 1] = 1; - if (result == firstFreeLocal) { - for (int i = firstFreeLocal + 2; i < MAX_LOCALS; i++) { - if (locals[i] == 0) { - firstFreeLocal = (short) i; - if (localsMax < firstFreeLocal) - localsMax = firstFreeLocal; - return result; - } - } - } - else { - return result; - } - } - throw Context.reportRuntimeError("Program too complex " + - "(out of locals)"); - } - - private short getNewWordLocal() - { - short result = firstFreeLocal; - locals[result] = 1; - for (int i = firstFreeLocal + 1; i < MAX_LOCALS; i++) { - if (locals[i] == 0) { - firstFreeLocal = (short) i; - if (localsMax < firstFreeLocal) - localsMax = firstFreeLocal; - return result; - } - } - throw Context.reportRuntimeError("Program too complex " + - "(out of locals)"); - } - - private short getConsecutiveSlots(int count, boolean isConst) { - if (isConst) - count++; - short result = firstFreeLocal; - while (true) { - if (result >= (MAX_LOCALS - 1)) - break; - int i; - for (i = 0; i < count; i++) - if (locals[result + i] != 0) - break; - if (i >= count) - break; - result++; - } - return result; - } - - // This is a valid call only for a local that is allocated by default. - private void incReferenceWordLocal(short local) - { - locals[local]++; - } - - // This is a valid call only for a local that is allocated by default. - private void decReferenceWordLocal(short local) - { - locals[local]--; - } - - private void releaseWordLocal(short local) - { - if (local < firstFreeLocal) - firstFreeLocal = local; - locals[local] = 0; - } - - - static final int GENERATOR_TERMINATE = -1; - static final int GENERATOR_START = 0; - static final int GENERATOR_YIELD_START = 1; - - ClassFileWriter cfw; - Codegen codegen; - CompilerEnvirons compilerEnv; - ScriptOrFnNode scriptOrFn; - public int scriptOrFnIndex; - private int savedCodeOffset; - - private OptFunctionNode fnCurrent; - private boolean isTopLevel; - - private static final int MAX_LOCALS = 256; - private int[] locals; - private short firstFreeLocal; - private short localsMax; - - private int itsLineNumber; - - private boolean hasVarsInRegs; - private short[] varRegisters; - private boolean inDirectCallFunction; - private boolean itsForcedObjectParameters; - private int enterAreaStartLabel; - private int epilogueLabel; - - // special known locals. If you add a new local here, be sure - // to initialize it to -1 in initBodyGeneration - private short variableObjectLocal; - private short popvLocal; - private short contextLocal; - private short argsLocal; - private short operationLocal; - private short thisObjLocal; - private short funObjLocal; - private short itsZeroArgArray; - private short itsOneArgArray; - private short scriptRegexpLocal; - private short generatorStateLocal; - - private boolean isGenerator; - private int generatorSwitch; - private int maxLocals = 0; - private int maxStack = 0; - - private Hashtable finallys; - - class FinallyReturnPoint { - public ArrayList jsrPoints = new ArrayList(); - public int tableLabel = 0; - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/DataFlowBitSet.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/DataFlowBitSet.java deleted file mode 100644 index 607e649..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/DataFlowBitSet.java +++ /dev/null @@ -1,134 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - - - -package org.mozilla.javascript.optimizer; - -class DataFlowBitSet { - - private int itsBits[]; - private int itsSize; - - DataFlowBitSet(int size) - { - itsSize = size; - itsBits = new int[(size + 31) >> 5]; - } - - void set(int n) - { - if (!(0 <= n && n < itsSize)) badIndex(n); - itsBits[n >> 5] |= 1 << (n & 31); - } - - boolean test(int n) - { - if (!(0 <= n && n < itsSize)) badIndex(n); - return ((itsBits[n >> 5] & (1 << (n & 31))) != 0); - } - - void not() - { - int bitsLength = itsBits.length; - for (int i = 0; i < bitsLength; i++) - itsBits[i] = ~itsBits[i]; - } - - void clear(int n) - { - if (!(0 <= n && n < itsSize)) badIndex(n); - itsBits[n >> 5] &= ~(1 << (n & 31)); - } - - void clear() - { - int bitsLength = itsBits.length; - for (int i = 0; i < bitsLength; i++) - itsBits[i] = 0; - } - - void or(DataFlowBitSet b) - { - int bitsLength = itsBits.length; - for (int i = 0; i < bitsLength; i++) - itsBits[i] |= b.itsBits[i]; - } - - public String toString() - { - StringBuffer sb = new StringBuffer(); - sb.append("DataFlowBitSet, size = "); - sb.append(itsSize); - sb.append('\n'); - int bitsLength = itsBits.length; - for (int i = 0; i < bitsLength; i++) { - sb.append(Integer.toHexString(itsBits[i])); - sb.append(' '); - } - return sb.toString(); - } - - boolean df(DataFlowBitSet in, DataFlowBitSet gen, DataFlowBitSet notKill) - { - int bitsLength = itsBits.length; - boolean changed = false; - for (int i = 0; i < bitsLength; i++) { - int oldBits = itsBits[i]; - itsBits[i] = (in.itsBits[i] | gen.itsBits[i]) & notKill.itsBits[i]; - changed |= (oldBits != itsBits[i]); - } - return changed; - } - - boolean df2(DataFlowBitSet in, DataFlowBitSet gen, DataFlowBitSet notKill) - { - int bitsLength = itsBits.length; - boolean changed = false; - for (int i = 0; i < bitsLength; i++) { - int oldBits = itsBits[i]; - itsBits[i] = (in.itsBits[i] & notKill.itsBits[i]) | gen.itsBits[i]; - changed |= (oldBits != itsBits[i]); - } - return changed; - } - - private void badIndex(int n) - { - throw new RuntimeException("DataFlowBitSet bad index " + n); - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/OptFunctionNode.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/OptFunctionNode.java deleted file mode 100644 index e043165..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/OptFunctionNode.java +++ /dev/null @@ -1,149 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Bob Jervis - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - - -package org.mozilla.javascript.optimizer; - -import org.mozilla.javascript.*; - -final class OptFunctionNode -{ - OptFunctionNode(FunctionNode fnode) - { - this.fnode = fnode; - fnode.setCompilerData(this); - } - - static OptFunctionNode get(ScriptOrFnNode scriptOrFn, int i) - { - FunctionNode fnode = scriptOrFn.getFunctionNode(i); - return (OptFunctionNode)fnode.getCompilerData(); - } - - static OptFunctionNode get(ScriptOrFnNode scriptOrFn) - { - return (OptFunctionNode)scriptOrFn.getCompilerData(); - } - - boolean isTargetOfDirectCall() - { - return directTargetIndex >= 0; - } - - int getDirectTargetIndex() - { - return directTargetIndex; - } - - void setDirectTargetIndex(int directTargetIndex) - { - // One time action - if (directTargetIndex < 0 || this.directTargetIndex >= 0) - Kit.codeBug(); - this.directTargetIndex = directTargetIndex; - } - - void setParameterNumberContext(boolean b) - { - itsParameterNumberContext = b; - } - - boolean getParameterNumberContext() - { - return itsParameterNumberContext; - } - - int getVarCount() - { - return fnode.getParamAndVarCount(); - } - - boolean isParameter(int varIndex) - { - return varIndex < fnode.getParamCount(); - } - - boolean isNumberVar(int varIndex) - { - varIndex -= fnode.getParamCount(); - if (varIndex >= 0 && numberVarFlags != null) { - return numberVarFlags[varIndex]; - } - return false; - } - - void setIsNumberVar(int varIndex) - { - varIndex -= fnode.getParamCount(); - // Can only be used with non-parameters - if (varIndex < 0) Kit.codeBug(); - if (numberVarFlags == null) { - int size = fnode.getParamAndVarCount() - fnode.getParamCount(); - numberVarFlags = new boolean[size]; - } - numberVarFlags[varIndex] = true; - } - - int getVarIndex(Node n) - { - int index = n.getIntProp(Node.VARIABLE_PROP, -1); - if (index == -1) { - Node node; - int type = n.getType(); - if (type == Token.GETVAR) { - node = n; - } else if (type == Token.SETVAR || - type == Token.SETCONSTVAR) { - node = n.getFirstChild(); - } else { - throw Kit.codeBug(); - } - index = fnode.getIndexForNameNode(node); - if (index < 0) throw Kit.codeBug(); - n.putIntProp(Node.VARIABLE_PROP, index); - } - return index; - } - - FunctionNode fnode; - private boolean[] numberVarFlags; - private int directTargetIndex = -1; - private boolean itsParameterNumberContext; - boolean itsContainsCalls0; - boolean itsContainsCalls1; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/OptRuntime.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/OptRuntime.java deleted file mode 100644 index ba8ca03..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/OptRuntime.java +++ /dev/null @@ -1,311 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Roger Lawrence - * Hannes Wallnoefer - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - - -package org.mozilla.javascript.optimizer; - -import org.mozilla.javascript.*; - -public final class OptRuntime extends ScriptRuntime -{ - - public static final Double zeroObj = new Double(0.0); - public static final Double oneObj = new Double(1.0); - public static final Double minusOneObj = new Double(-1.0); - - /** - * Implement ....() call shrinking optimizer code. - */ - public static Object call0(Callable fun, Scriptable thisObj, - Context cx, Scriptable scope) - { - return fun.call(cx, scope, thisObj, ScriptRuntime.emptyArgs); - } - - /** - * Implement ....(arg) call shrinking optimizer code. - */ - public static Object call1(Callable fun, Scriptable thisObj, Object arg0, - Context cx, Scriptable scope) - { - return fun.call(cx, scope, thisObj, new Object[] { arg0 } ); - } - - /** - * Implement ....(arg0, arg1) call shrinking optimizer code. - */ - public static Object call2(Callable fun, Scriptable thisObj, - Object arg0, Object arg1, - Context cx, Scriptable scope) - { - return fun.call(cx, scope, thisObj, new Object[] { arg0, arg1 }); - } - - /** - * Implement ....(arg0, arg1, ...) call shrinking optimizer code. - */ - public static Object callN(Callable fun, Scriptable thisObj, - Object[] args, - Context cx, Scriptable scope) - { - return fun.call(cx, scope, thisObj, args); - } - - /** - * Implement name(args) call shrinking optimizer code. - */ - public static Object callName(Object[] args, String name, - Context cx, Scriptable scope) - { - Callable f = getNameFunctionAndThis(name, cx, scope); - Scriptable thisObj = lastStoredScriptable(cx); - return f.call(cx, scope, thisObj, args); - } - - /** - * Implement name() call shrinking optimizer code. - */ - public static Object callName0(String name, - Context cx, Scriptable scope) - { - Callable f = getNameFunctionAndThis(name, cx, scope); - Scriptable thisObj = lastStoredScriptable(cx); - return f.call(cx, scope, thisObj, ScriptRuntime.emptyArgs); - } - - /** - * Implement x.property() call shrinking optimizer code. - */ - public static Object callProp0(Object value, String property, - Context cx, Scriptable scope) - { - Callable f = getPropFunctionAndThis(value, property, cx); - Scriptable thisObj = lastStoredScriptable(cx); - return f.call(cx, scope, thisObj, ScriptRuntime.emptyArgs); - } - - public static Object add(Object val1, double val2) - { - if (val1 instanceof Scriptable) - val1 = ((Scriptable) val1).getDefaultValue(null); - if (!(val1 instanceof String)) - return wrapDouble(toNumber(val1) + val2); - return ((String)val1).concat(toString(val2)); - } - - public static Object add(double val1, Object val2) - { - if (val2 instanceof Scriptable) - val2 = ((Scriptable) val2).getDefaultValue(null); - if (!(val2 instanceof String)) - return wrapDouble(toNumber(val2) + val1); - return toString(val1).concat((String)val2); - } - - public static Object elemIncrDecr(Object obj, double index, - Context cx, int incrDecrMask) - { - return ScriptRuntime.elemIncrDecr(obj, new Double(index), cx, - incrDecrMask); - } - - public static Object[] padStart(Object[] currentArgs, int count) { - Object[] result = new Object[currentArgs.length + count]; - System.arraycopy(currentArgs, 0, result, count, currentArgs.length); - return result; - } - - public static void initFunction(NativeFunction fn, int functionType, - Scriptable scope, Context cx) - { - ScriptRuntime.initFunction(cx, scope, fn, functionType, false); - } - - public static Object callSpecial(Context cx, Callable fun, - Scriptable thisObj, Object[] args, - Scriptable scope, - Scriptable callerThis, int callType, - String fileName, int lineNumber) - { - return ScriptRuntime.callSpecial(cx, fun, thisObj, args, scope, - callerThis, callType, - fileName, lineNumber); - } - - public static Object newObjectSpecial(Context cx, Object fun, - Object[] args, Scriptable scope, - Scriptable callerThis, int callType) - { - return ScriptRuntime.newSpecial(cx, fun, args, scope, callType); - } - - public static Double wrapDouble(double num) - { - if (num == 0.0) { - if (1 / num > 0) { - // +0.0 - return zeroObj; - } - } else if (num == 1.0) { - return oneObj; - } else if (num == -1.0) { - return minusOneObj; - } else if (num != num) { - return NaNobj; - } - return new Double(num); - } - - static String encodeIntArray(int[] array) - { - // XXX: this extremely inefficient for small integers - if (array == null) { return null; } - int n = array.length; - char[] buffer = new char[1 + n * 2]; - buffer[0] = 1; - for (int i = 0; i != n; ++i) { - int value = array[i]; - int shift = 1 + i * 2; - buffer[shift] = (char)(value >>> 16); - buffer[shift + 1] = (char)value; - } - return new String(buffer); - } - - private static int[] decodeIntArray(String str, int arraySize) - { - // XXX: this extremely inefficient for small integers - if (arraySize == 0) { - if (str != null) throw new IllegalArgumentException(); - return null; - } - if (str.length() != 1 + arraySize * 2 && str.charAt(0) != 1) { - throw new IllegalArgumentException(); - } - int[] array = new int[arraySize]; - for (int i = 0; i != arraySize; ++i) { - int shift = 1 + i * 2; - array[i] = (str.charAt(shift) << 16) | str.charAt(shift + 1); - } - return array; - } - - public static Scriptable newArrayLiteral(Object[] objects, - String encodedInts, - int skipCount, - Context cx, - Scriptable scope) - { - int[] skipIndexces = decodeIntArray(encodedInts, skipCount); - return newArrayLiteral(objects, skipIndexces, cx, scope); - } - - public static void main(final Script script, final String[] args) - { - Context.call(new ContextAction() { - public Object run(Context cx) - { - ScriptableObject global = getGlobal(cx); - - // get the command line arguments and define "arguments" - // array in the top-level object - Object[] argsCopy = new Object[args.length]; - System.arraycopy(args, 0, argsCopy, 0, args.length); - Scriptable argsObj = cx.newArray(global, argsCopy); - global.defineProperty("arguments", argsObj, - ScriptableObject.DONTENUM); - script.exec(cx, global); - return null; - } - }); - } - - public static void throwStopIteration(Object obj) { - throw new JavaScriptException( - NativeIterator.getStopIterationObject((Scriptable)obj), "", 0); - } - - public static Scriptable createNativeGenerator(NativeFunction funObj, - Scriptable scope, - Scriptable thisObj, - int maxLocals, - int maxStack) - { - return new NativeGenerator(scope, funObj, - new GeneratorState(thisObj, maxLocals, maxStack)); - } - - public static Object[] getGeneratorStackState(Object obj) { - GeneratorState rgs = (GeneratorState) obj; - if (rgs.stackState == null) - rgs.stackState = new Object[rgs.maxStack]; - return rgs.stackState; - } - - public static Object[] getGeneratorLocalsState(Object obj) { - GeneratorState rgs = (GeneratorState) obj; - if (rgs.localsState == null) - rgs.localsState = new Object[rgs.maxLocals]; - return rgs.localsState; - } - - public static class GeneratorState { - static final String CLASS_NAME = - "org/mozilla/javascript/optimizer/OptRuntime$GeneratorState"; - - public int resumptionPoint; - static final String resumptionPoint_NAME = "resumptionPoint"; - static final String resumptionPoint_TYPE = "I"; - - public Scriptable thisObj; - static final String thisObj_NAME = "thisObj"; - static final String thisObj_TYPE = - "Lorg/mozilla/javascript/Scriptable;"; - - Object[] stackState; - Object[] localsState; - int maxLocals; - int maxStack; - - GeneratorState(Scriptable thisObj, int maxLocals, int maxStack) { - this.thisObj = thisObj; - this.maxLocals = maxLocals; - this.maxStack = maxStack; - } - } -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/OptTransformer.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/OptTransformer.java deleted file mode 100644 index 7cf679f..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/OptTransformer.java +++ /dev/null @@ -1,133 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - - -package org.mozilla.javascript.optimizer; - -import org.mozilla.javascript.*; -import java.util.Hashtable; - -/** - * This class performs node transforms to prepare for optimization. - * - * @see NodeTransformer - * @author Norris Boyd - */ - -class OptTransformer extends NodeTransformer { - - OptTransformer(Hashtable possibleDirectCalls, ObjArray directCallTargets) - { - this.possibleDirectCalls = possibleDirectCalls; - this.directCallTargets = directCallTargets; - } - - protected void visitNew(Node node, ScriptOrFnNode tree) { - detectDirectCall(node, tree); - super.visitNew(node, tree); - } - - protected void visitCall(Node node, ScriptOrFnNode tree) { - detectDirectCall(node, tree); - super.visitCall(node, tree); - } - - private void detectDirectCall(Node node, ScriptOrFnNode tree) - { - if (tree.getType() == Token.FUNCTION) { - Node left = node.getFirstChild(); - - // count the arguments - int argCount = 0; - Node arg = left.getNext(); - while (arg != null) { - arg = arg.getNext(); - argCount++; - } - - if (argCount == 0) { - OptFunctionNode.get(tree).itsContainsCalls0 = true; - } - - /* - * Optimize a call site by converting call("a", b, c) into : - * - * FunctionObjectFor"a" <-- instance variable init'd by constructor - * - * // this is a DIRECTCALL node - * fn = GetProp(tmp = GetBase("a"), "a"); - * if (fn == FunctionObjectFor"a") - * fn.call(tmp, b, c) - * else - * ScriptRuntime.Call(fn, tmp, b, c) - */ - if (possibleDirectCalls != null) { - String targetName = null; - if (left.getType() == Token.NAME) { - targetName = left.getString(); - } else if (left.getType() == Token.GETPROP) { - targetName = left.getFirstChild().getNext().getString(); - } else if (left.getType() == Token.GETPROPNOWARN) { - throw Kit.codeBug(); - } - if (targetName != null) { - OptFunctionNode ofn; - ofn = (OptFunctionNode)possibleDirectCalls.get(targetName); - if (ofn != null - && argCount == ofn.fnode.getParamCount() - && !ofn.fnode.requiresActivation()) - { - // Refuse to directCall any function with more - // than 32 parameters - prevent code explosion - // for wacky test cases - if (argCount <= 32) { - node.putProp(Node.DIRECTCALL_PROP, ofn); - if (!ofn.isTargetOfDirectCall()) { - int index = directCallTargets.size(); - directCallTargets.add(ofn); - ofn.setDirectTargetIndex(index); - } - } - } - } - } - } - } - - private Hashtable possibleDirectCalls; - private ObjArray directCallTargets; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/Optimizer.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/Optimizer.java deleted file mode 100644 index 575c7e7..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/Optimizer.java +++ /dev/null @@ -1,510 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Roger Lawrence - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - - - -package org.mozilla.javascript.optimizer; - -import org.mozilla.javascript.*; - -class Optimizer -{ - - static final int NoType = 0; - static final int NumberType = 1; - static final int AnyType = 3; - - // It is assumed that (NumberType | AnyType) == AnyType - - void optimize(ScriptOrFnNode scriptOrFn) - { - // run on one function at a time for now - int functionCount = scriptOrFn.getFunctionCount(); - for (int i = 0; i != functionCount; ++i) { - OptFunctionNode f = OptFunctionNode.get(scriptOrFn, i); - optimizeFunction(f); - } - } - - private void optimizeFunction(OptFunctionNode theFunction) - { - if (theFunction.fnode.requiresActivation()) return; - - inDirectCallFunction = theFunction.isTargetOfDirectCall(); - this.theFunction = theFunction; - - ObjArray statementsArray = new ObjArray(); - buildStatementList_r(theFunction.fnode, statementsArray); - Node[] theStatementNodes = new Node[statementsArray.size()]; - statementsArray.toArray(theStatementNodes); - - Block.runFlowAnalyzes(theFunction, theStatementNodes); - - if (!theFunction.fnode.requiresActivation()) { - /* - * Now that we know which local vars are in fact always - * Numbers, we re-write the tree to take advantage of - * that. Any arithmetic or assignment op involving just - * Number typed vars is marked so that the codegen will - * generate non-object code. - */ - parameterUsedInNumberContext = false; - for (int i = 0; i < theStatementNodes.length; i++) { - rewriteForNumberVariables(theStatementNodes[i]); - } - theFunction.setParameterNumberContext(parameterUsedInNumberContext); - } - - } - - -/* - Each directCall parameter is passed as a pair of values - an object - and a double. The value passed depends on the type of value available at - the call site. If a double is available, the object in java/lang/Void.TYPE - is passed as the object value, and if an object value is available, then - 0.0 is passed as the double value. - - The receiving routine always tests the object value before proceeding. - If the parameter is being accessed in a 'Number Context' then the code - sequence is : - if ("parameter_objectValue" == java/lang/Void.TYPE) - ...fine..., use the parameter_doubleValue - else - toNumber(parameter_objectValue) - - and if the parameter is being referenced in an Object context, the code is - if ("parameter_objectValue" == java/lang/Void.TYPE) - new Double(parameter_doubleValue) - else - ...fine..., use the parameter_objectValue - - If the receiving code never uses the doubleValue, it is converted on - entry to a Double instead. -*/ - - -/* - We're referencing a node in a Number context (i.e. we'd prefer it - was a double value). If the node is a parameter in a directCall - function, mark it as being referenced in this context. -*/ - private void markDCPNumberContext(Node n) - { - if (inDirectCallFunction && n.getType() == Token.GETVAR) { - int varIndex = theFunction.getVarIndex(n); - if (theFunction.isParameter(varIndex)) { - parameterUsedInNumberContext = true; - } - } - } - - private boolean convertParameter(Node n) - { - if (inDirectCallFunction && n.getType() == Token.GETVAR) { - int varIndex = theFunction.getVarIndex(n); - if (theFunction.isParameter(varIndex)) { - n.removeProp(Node.ISNUMBER_PROP); - return true; - } - } - return false; - } - - private int rewriteForNumberVariables(Node n) - { - switch (n.getType()) { - case Token.EXPR_VOID : { - Node child = n.getFirstChild(); - int type = rewriteForNumberVariables(child); - if (type == NumberType) - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - return NoType; - } - case Token.NUMBER : - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - return NumberType; - - case Token.GETVAR : - { - int varIndex = theFunction.getVarIndex(n); - if (inDirectCallFunction - && theFunction.isParameter(varIndex)) - { - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - return NumberType; - } - else if (theFunction.isNumberVar(varIndex)) { - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - return NumberType; - } - return NoType; - } - - case Token.INC : - case Token.DEC : { - Node child = n.getFirstChild(); - // "child" will be GETVAR or GETPROP or GETELEM - if (child.getType() == Token.GETVAR) { - if (rewriteForNumberVariables(child) == NumberType) { - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - markDCPNumberContext(child); - return NumberType; - } - return NoType; - } - else if (child.getType() == Token.GETELEM) { - return rewriteForNumberVariables(child); - } - return NoType; - } - case Token.SETVAR : { - Node lChild = n.getFirstChild(); - Node rChild = lChild.getNext(); - int rType = rewriteForNumberVariables(rChild); - int varIndex = theFunction.getVarIndex(n); - if (inDirectCallFunction - && theFunction.isParameter(varIndex)) - { - if (rType == NumberType) { - if (!convertParameter(rChild)) { - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - return NumberType; - } - markDCPNumberContext(rChild); - return NoType; - } - else - return rType; - } - else if (theFunction.isNumberVar(varIndex)) { - if (rType != NumberType) { - n.removeChild(rChild); - n.addChildToBack( - new Node(Token.TO_DOUBLE, rChild)); - } - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - markDCPNumberContext(rChild); - return NumberType; - } - else { - if (rType == NumberType) { - if (!convertParameter(rChild)) { - n.removeChild(rChild); - n.addChildToBack( - new Node(Token.TO_OBJECT, rChild)); - } - } - return NoType; - } - } - case Token.LE : - case Token.LT : - case Token.GE : - case Token.GT : { - Node lChild = n.getFirstChild(); - Node rChild = lChild.getNext(); - int lType = rewriteForNumberVariables(lChild); - int rType = rewriteForNumberVariables(rChild); - markDCPNumberContext(lChild); - markDCPNumberContext(rChild); - - if (convertParameter(lChild)) { - if (convertParameter(rChild)) { - return NoType; - } else if (rType == NumberType) { - n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT); - } - } - else if (convertParameter(rChild)) { - if (lType == NumberType) { - n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT); - } - } - else { - if (lType == NumberType) { - if (rType == NumberType) { - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - } - else { - n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT); - } - } - else { - if (rType == NumberType) { - n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT); - } - } - } - // we actually build a boolean value - return NoType; - } - - case Token.ADD : { - Node lChild = n.getFirstChild(); - Node rChild = lChild.getNext(); - int lType = rewriteForNumberVariables(lChild); - int rType = rewriteForNumberVariables(rChild); - - - if (convertParameter(lChild)) { - if (convertParameter(rChild)) { - return NoType; - } - else { - if (rType == NumberType) { - n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT); - } - } - } - else { - if (convertParameter(rChild)) { - if (lType == NumberType) { - n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT); - } - } - else { - if (lType == NumberType) { - if (rType == NumberType) { - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - return NumberType; - } - else { - n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT); - } - } - else { - if (rType == NumberType) { - n.putIntProp(Node.ISNUMBER_PROP, - Node.RIGHT); - } - } - } - } - return NoType; - } - - case Token.BITXOR : - case Token.BITOR : - case Token.BITAND : - case Token.RSH : - case Token.LSH : - case Token.SUB : - case Token.MUL : - case Token.DIV : - case Token.MOD : { - Node lChild = n.getFirstChild(); - Node rChild = lChild.getNext(); - int lType = rewriteForNumberVariables(lChild); - int rType = rewriteForNumberVariables(rChild); - markDCPNumberContext(lChild); - markDCPNumberContext(rChild); - if (lType == NumberType) { - if (rType == NumberType) { - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - return NumberType; - } - else { - if (!convertParameter(rChild)) { - n.removeChild(rChild); - n.addChildToBack( - new Node(Token.TO_DOUBLE, rChild)); - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - } - return NumberType; - } - } - else { - if (rType == NumberType) { - if (!convertParameter(lChild)) { - n.removeChild(lChild); - n.addChildToFront( - new Node(Token.TO_DOUBLE, lChild)); - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - } - return NumberType; - } - else { - if (!convertParameter(lChild)) { - n.removeChild(lChild); - n.addChildToFront( - new Node(Token.TO_DOUBLE, lChild)); - } - if (!convertParameter(rChild)) { - n.removeChild(rChild); - n.addChildToBack( - new Node(Token.TO_DOUBLE, rChild)); - } - n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); - return NumberType; - } - } - } - case Token.SETELEM : - case Token.SETELEM_OP : { - Node arrayBase = n.getFirstChild(); - Node arrayIndex = arrayBase.getNext(); - Node rValue = arrayIndex.getNext(); - int baseType = rewriteForNumberVariables(arrayBase); - if (baseType == NumberType) {// can never happen ??? - if (!convertParameter(arrayBase)) { - n.removeChild(arrayBase); - n.addChildToFront( - new Node(Token.TO_OBJECT, arrayBase)); - } - } - int indexType = rewriteForNumberVariables(arrayIndex); - if (indexType == NumberType) { - // setting the ISNUMBER_PROP signals the codegen - // to use the OptRuntime.setObjectIndex that takes - // a double index - n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT); - markDCPNumberContext(arrayIndex); - } - int rValueType = rewriteForNumberVariables(rValue); - if (rValueType == NumberType) { - if (!convertParameter(rValue)) { - n.removeChild(rValue); - n.addChildToBack( - new Node(Token.TO_OBJECT, rValue)); - } - } - return NoType; - } - case Token.GETELEM : { - Node arrayBase = n.getFirstChild(); - Node arrayIndex = arrayBase.getNext(); - int baseType = rewriteForNumberVariables(arrayBase); - if (baseType == NumberType) {// can never happen ??? - if (!convertParameter(arrayBase)) { - n.removeChild(arrayBase); - n.addChildToFront( - new Node(Token.TO_OBJECT, arrayBase)); - } - } - int indexType = rewriteForNumberVariables(arrayIndex); - if (indexType == NumberType) { - if (!convertParameter(arrayIndex)) { - // setting the ISNUMBER_PROP signals the codegen - // to use the OptRuntime.getObjectIndex that takes - // a double index - n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT); - } - } - return NoType; - } - case Token.CALL : - { - Node child = n.getFirstChild(); // the function node - if (child.getType() == Token.GETELEM) { - // Optimization of x[0]() is not supported - // so bypass GETELEM optimization that - // rewriteForNumberVariables would trigger - rewriteAsObjectChildren(child, child.getFirstChild()); - } else { - rewriteForNumberVariables(child); - } - child = child.getNext(); // the first arg - - OptFunctionNode target - = (OptFunctionNode)n.getProp(Node.DIRECTCALL_PROP); - if (target != null) { -/* - we leave each child as a Number if it can be. The codegen will - handle moving the pairs of parameters. -*/ - while (child != null) { - int type = rewriteForNumberVariables(child); - if (type == NumberType) { - markDCPNumberContext(child); - } - child = child.getNext(); - } - } else { - rewriteAsObjectChildren(n, child); - } - return NoType; - } - default : { - rewriteAsObjectChildren(n, n.getFirstChild()); - return NoType; - } - } - } - - private void rewriteAsObjectChildren(Node n, Node child) - { - // Force optimized children to be objects - while (child != null) { - Node nextChild = child.getNext(); - int type = rewriteForNumberVariables(child); - if (type == NumberType) { - if (!convertParameter(child)) { - n.removeChild(child); - Node nuChild = new Node(Token.TO_OBJECT, child); - if (nextChild == null) - n.addChildToBack(nuChild); - else - n.addChildBefore(nuChild, nextChild); - } - } - child = nextChild; - } - } - - private static void buildStatementList_r(Node node, ObjArray statements) - { - int type = node.getType(); - if (type == Token.BLOCK - || type == Token.LOCAL_BLOCK - || type == Token.LOOP - || type == Token.FUNCTION) - { - Node child = node.getFirstChild(); - while (child != null) { - buildStatementList_r(child, statements); - child = child.getNext(); - } - } else { - statements.add(node); - } - } - - private boolean inDirectCallFunction; - OptFunctionNode theFunction; - private boolean parameterUsedInNumberContext; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/NativeRegExp.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/NativeRegExp.java deleted file mode 100644 index a893841..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/NativeRegExp.java +++ /dev/null @@ -1,2782 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Brendan Eich - * Matthias Radestock - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.regexp; - -import java.io.Serializable; - -import org.mozilla.javascript.Context; -import org.mozilla.javascript.Function; -import org.mozilla.javascript.IdFunctionObject; -import org.mozilla.javascript.IdScriptableObject; -import org.mozilla.javascript.Kit; -import org.mozilla.javascript.ScriptRuntime; -import org.mozilla.javascript.Scriptable; -import org.mozilla.javascript.ScriptableObject; -import org.mozilla.javascript.Undefined; - -/** - * This class implements the RegExp native object. - * - * Revision History: - * Implementation in C by Brendan Eich - * Initial port to Java by Norris Boyd from jsregexp.c version 1.36 - * Merged up to version 1.38, which included Unicode support. - * Merged bug fixes in version 1.39. - * Merged JSFUN13_BRANCH changes up to 1.32.2.13 - * - * @author Brendan Eich - * @author Norris Boyd - */ - - - -public class NativeRegExp extends IdScriptableObject implements Function -{ - static final long serialVersionUID = 4965263491464903264L; - - private static final Object REGEXP_TAG = new Object(); - - public static final int JSREG_GLOB = 0x1; // 'g' flag: global - public static final int JSREG_FOLD = 0x2; // 'i' flag: fold - public static final int JSREG_MULTILINE = 0x4; // 'm' flag: multiline - - //type of match to perform - public static final int TEST = 0; - public static final int MATCH = 1; - public static final int PREFIX = 2; - - private static final boolean debug = false; - - private static final byte REOP_EMPTY = 0; /* match rest of input against rest of r.e. */ - private static final byte REOP_ALT = 1; /* alternative subexpressions in kid and next */ - private static final byte REOP_BOL = 2; /* beginning of input (or line if multiline) */ - private static final byte REOP_EOL = 3; /* end of input (or line if multiline) */ - private static final byte REOP_WBDRY = 4; /* match "" at word boundary */ - private static final byte REOP_WNONBDRY = 5; /* match "" at word non-boundary */ - private static final byte REOP_QUANT = 6; /* quantified atom: atom{1,2} */ - private static final byte REOP_STAR = 7; /* zero or more occurrences of kid */ - private static final byte REOP_PLUS = 8; /* one or more occurrences of kid */ - private static final byte REOP_OPT = 9; /* optional subexpression in kid */ - private static final byte REOP_LPAREN = 10; /* left paren bytecode: kid is u.num'th sub-regexp */ - private static final byte REOP_RPAREN = 11; /* right paren bytecode */ - private static final byte REOP_DOT = 12; /* stands for any character */ -// private static final byte REOP_CCLASS = 13; /* character class: [a-f] */ - private static final byte REOP_DIGIT = 14; /* match a digit char: [0-9] */ - private static final byte REOP_NONDIGIT = 15; /* match a non-digit char: [^0-9] */ - private static final byte REOP_ALNUM = 16; /* match an alphanumeric char: [0-9a-z_A-Z] */ - private static final byte REOP_NONALNUM = 17; /* match a non-alphanumeric char: [^0-9a-z_A-Z] */ - private static final byte REOP_SPACE = 18; /* match a whitespace char */ - private static final byte REOP_NONSPACE = 19; /* match a non-whitespace char */ - private static final byte REOP_BACKREF = 20; /* back-reference (e.g., \1) to a parenthetical */ - private static final byte REOP_FLAT = 21; /* match a flat string */ - private static final byte REOP_FLAT1 = 22; /* match a single char */ - private static final byte REOP_JUMP = 23; /* for deoptimized closure loops */ -// private static final byte REOP_DOTSTAR = 24; /* optimize .* to use a single opcode */ -// private static final byte REOP_ANCHOR = 25; /* like .* but skips left context to unanchored r.e. */ -// private static final byte REOP_EOLONLY = 26; /* $ not preceded by any pattern */ -// private static final byte REOP_UCFLAT = 27; /* flat Unicode string; len immediate counts chars */ - private static final byte REOP_UCFLAT1 = 28; /* single Unicode char */ -// private static final byte REOP_UCCLASS = 29; /* Unicode character class, vector of chars to match */ -// private static final byte REOP_NUCCLASS = 30; /* negated Unicode character class */ -// private static final byte REOP_BACKREFi = 31; /* case-independent REOP_BACKREF */ - private static final byte REOP_FLATi = 32; /* case-independent REOP_FLAT */ - private static final byte REOP_FLAT1i = 33; /* case-independent REOP_FLAT1 */ -// private static final byte REOP_UCFLATi = 34; /* case-independent REOP_UCFLAT */ - private static final byte REOP_UCFLAT1i = 35; /* case-independent REOP_UCFLAT1 */ -// private static final byte REOP_ANCHOR1 = 36; /* first-char discriminating REOP_ANCHOR */ -// private static final byte REOP_NCCLASS = 37; /* negated 8-bit character class */ -// private static final byte REOP_DOTSTARMIN = 38; /* ungreedy version of REOP_DOTSTAR */ -// private static final byte REOP_LPARENNON = 39; /* non-capturing version of REOP_LPAREN */ -// private static final byte REOP_RPARENNON = 40; /* non-capturing version of REOP_RPAREN */ - private static final byte REOP_ASSERT = 41; /* zero width positive lookahead assertion */ - private static final byte REOP_ASSERT_NOT = 42; /* zero width negative lookahead assertion */ - private static final byte REOP_ASSERTTEST = 43; /* sentinel at end of assertion child */ - private static final byte REOP_ASSERTNOTTEST = 44; /* sentinel at end of !assertion child */ - private static final byte REOP_MINIMALSTAR = 45; /* non-greedy version of * */ - private static final byte REOP_MINIMALPLUS = 46; /* non-greedy version of + */ - private static final byte REOP_MINIMALOPT = 47; /* non-greedy version of ? */ - private static final byte REOP_MINIMALQUANT = 48; /* non-greedy version of {} */ - private static final byte REOP_ENDCHILD = 49; /* sentinel at end of quantifier child */ - private static final byte REOP_CLASS = 50; /* character class with index */ - private static final byte REOP_REPEAT = 51; /* directs execution of greedy quantifier */ - private static final byte REOP_MINIMALREPEAT = 52; /* directs execution of non-greedy quantifier */ - private static final byte REOP_END = 53; - - - - public static void init(Context cx, Scriptable scope, boolean sealed) - { - - NativeRegExp proto = new NativeRegExp(); - proto.re = (RECompiled)compileRE(cx, "", null, false); - proto.activatePrototypeMap(MAX_PROTOTYPE_ID); - proto.setParentScope(scope); - proto.setPrototype(getObjectPrototype(scope)); - - NativeRegExpCtor ctor = new NativeRegExpCtor(); - // Bug #324006: ECMA-262 15.10.6.1 says "The initial value of - // RegExp.prototype.constructor is the builtin RegExp constructor." - proto.put("constructor", proto, ctor); - - ScriptRuntime.setFunctionProtoAndParent(ctor, scope); - - ctor.setImmunePrototypeProperty(proto); - - if (sealed) { - proto.sealObject(); - ctor.sealObject(); - } - - defineProperty(scope, "RegExp", ctor, ScriptableObject.DONTENUM); - } - - NativeRegExp(Scriptable scope, Object regexpCompiled) - { - this.re = (RECompiled)regexpCompiled; - this.lastIndex = 0; - ScriptRuntime.setObjectProtoAndParent(this, scope); - } - - public String getClassName() - { - return "RegExp"; - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - return execSub(cx, scope, args, MATCH); - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) - { - return (Scriptable)execSub(cx, scope, args, MATCH); - } - - Scriptable compile(Context cx, Scriptable scope, Object[] args) - { - if (args.length > 0 && args[0] instanceof NativeRegExp) { - if (args.length > 1 && args[1] != Undefined.instance) { - // report error - throw ScriptRuntime.typeError0("msg.bad.regexp.compile"); - } - NativeRegExp thatObj = (NativeRegExp) args[0]; - this.re = thatObj.re; - this.lastIndex = thatObj.lastIndex; - return this; - } - String s = args.length == 0 ? "" : ScriptRuntime.toString(args[0]); - String global = args.length > 1 && args[1] != Undefined.instance - ? ScriptRuntime.toString(args[1]) - : null; - this.re = (RECompiled)compileRE(cx, s, global, false); - this.lastIndex = 0; - return this; - } - - public String toString() - { - StringBuffer buf = new StringBuffer(); - buf.append('/'); - if (re.source.length != 0) { - buf.append(re.source); - } else { - // See bugzilla 226045 - buf.append("(?:)"); - } - buf.append('/'); - if ((re.flags & JSREG_GLOB) != 0) - buf.append('g'); - if ((re.flags & JSREG_FOLD) != 0) - buf.append('i'); - if ((re.flags & JSREG_MULTILINE) != 0) - buf.append('m'); - return buf.toString(); - } - - NativeRegExp() { } - - private static RegExpImpl getImpl(Context cx) - { - return (RegExpImpl) ScriptRuntime.getRegExpProxy(cx); - } - - private Object execSub(Context cx, Scriptable scopeObj, - Object[] args, int matchType) - { - RegExpImpl reImpl = getImpl(cx); - String str; - if (args.length == 0) { - str = reImpl.input; - if (str == null) { - reportError("msg.no.re.input.for", toString()); - } - } else { - str = ScriptRuntime.toString(args[0]); - } - double d = ((re.flags & JSREG_GLOB) != 0) ? lastIndex : 0; - - Object rval; - if (d < 0 || str.length() < d) { - lastIndex = 0; - rval = null; - } - else { - int indexp[] = { (int)d }; - rval = executeRegExp(cx, scopeObj, reImpl, str, indexp, matchType); - if ((re.flags & JSREG_GLOB) != 0) { - lastIndex = (rval == null || rval == Undefined.instance) - ? 0 : indexp[0]; - } - } - return rval; - } - - static Object compileRE(Context cx, String str, String global, boolean flat) - { - RECompiled regexp = new RECompiled(); - regexp.source = str.toCharArray(); - int length = str.length(); - - int flags = 0; - if (global != null) { - for (int i = 0; i < global.length(); i++) { - char c = global.charAt(i); - if (c == 'g') { - flags |= JSREG_GLOB; - } else if (c == 'i') { - flags |= JSREG_FOLD; - } else if (c == 'm') { - flags |= JSREG_MULTILINE; - } else { - reportError("msg.invalid.re.flag", String.valueOf(c)); - } - } - } - regexp.flags = flags; - - CompilerState state = new CompilerState(cx, regexp.source, length, flags); - if (flat && length > 0) { -if (debug) { -System.out.println("flat = \"" + str + "\""); -} - state.result = new RENode(REOP_FLAT); - state.result.chr = state.cpbegin[0]; - state.result.length = length; - state.result.flatIndex = 0; - state.progLength += 5; - } - else - if (!parseDisjunction(state)) - return null; - - regexp.program = new byte[state.progLength + 1]; - if (state.classCount != 0) { - regexp.classList = new RECharSet[state.classCount]; - regexp.classCount = state.classCount; - } - int endPC = emitREBytecode(state, regexp, 0, state.result); - regexp.program[endPC++] = REOP_END; - -if (debug) { -System.out.println("Prog. length = " + endPC); -for (int i = 0; i < endPC; i++) { - System.out.print(regexp.program[i]); - if (i < (endPC - 1)) System.out.print(", "); -} -System.out.println(); -} - regexp.parenCount = state.parenCount; - - // If re starts with literal, init anchorCh accordingly - switch (regexp.program[0]) { - case REOP_UCFLAT1: - case REOP_UCFLAT1i: - regexp.anchorCh = (char)getIndex(regexp.program, 1); - break; - case REOP_FLAT1: - case REOP_FLAT1i: - regexp.anchorCh = (char)(regexp.program[1] & 0xFF); - break; - case REOP_FLAT: - case REOP_FLATi: - int k = getIndex(regexp.program, 1); - regexp.anchorCh = regexp.source[k]; - break; - } - -if (debug) { -if (regexp.anchorCh >= 0) { - System.out.println("Anchor ch = '" + (char)regexp.anchorCh + "'"); -} -} - return regexp; - } - - static boolean isDigit(char c) - { - return '0' <= c && c <= '9'; - } - - private static boolean isWord(char c) - { - return Character.isLetter(c) || isDigit(c) || c == '_'; - } - - private static boolean isLineTerm(char c) - { - return ScriptRuntime.isJSLineTerminator(c); - } - - private static boolean isREWhiteSpace(int c) - { - return (c == '\u0020' || c == '\u0009' - || c == '\n' || c == '\r' - || c == 0x2028 || c == 0x2029 - || c == '\u000C' || c == '\u000B' - || c == '\u00A0' - || Character.getType((char)c) == Character.SPACE_SEPARATOR); - } - - /* - * - * 1. If IgnoreCase is false, return ch. - * 2. Let u be ch converted to upper case as if by calling - * String.prototype.toUpperCase on the one-character string ch. - * 3. If u does not consist of a single character, return ch. - * 4. Let cu be u's character. - * 5. If ch's code point value is greater than or equal to decimal 128 and cu's - * code point value is less than decimal 128, then return ch. - * 6. Return cu. - */ - private static char upcase(char ch) - { - if (ch < 128) { - if ('a' <= ch && ch <= 'z') { - return (char)(ch + ('A' - 'a')); - } - return ch; - } - char cu = Character.toUpperCase(ch); - if ((ch >= 128) && (cu < 128)) return ch; - return cu; - } - - private static char downcase(char ch) - { - if (ch < 128) { - if ('A' <= ch && ch <= 'Z') { - return (char)(ch + ('a' - 'A')); - } - return ch; - } - char cl = Character.toLowerCase(ch); - if ((ch >= 128) && (cl < 128)) return ch; - return cl; - } - -/* - * Validates and converts hex ascii value. - */ - private static int toASCIIHexDigit(int c) - { - if (c < '0') - return -1; - if (c <= '9') { - return c - '0'; - } - c |= 0x20; - if ('a' <= c && c <= 'f') { - return c - 'a' + 10; - } - return -1; - } - -/* - * Top-down regular expression grammar, based closely on Perl4. - * - * regexp: altern A regular expression is one or more - * altern '|' regexp alternatives separated by vertical bar. - */ - private static boolean parseDisjunction(CompilerState state) - { - if (!parseAlternative(state)) - return false; - char[] source = state.cpbegin; - int index = state.cp; - if (index != source.length && source[index] == '|') { - RENode altResult; - ++state.cp; - altResult = new RENode(REOP_ALT); - altResult.kid = state.result; - if (!parseDisjunction(state)) - return false; - altResult.kid2 = state.result; - state.result = altResult; - /* ALT, <next>, ..., JUMP, <end> ... JUMP <end> */ - state.progLength += 9; - } - return true; - } - -/* - * altern: item An alternative is one or more items, - * item altern concatenated together. - */ - private static boolean parseAlternative(CompilerState state) - { - RENode headTerm = null; - RENode tailTerm = null; - char[] source = state.cpbegin; - while (true) { - if (state.cp == state.cpend || source[state.cp] == '|' - || (state.parenNesting != 0 && source[state.cp] == ')')) - { - if (headTerm == null) { - state.result = new RENode(REOP_EMPTY); - } - else - state.result = headTerm; - return true; - } - if (!parseTerm(state)) - return false; - if (headTerm == null) - headTerm = state.result; - else { - if (tailTerm == null) { - headTerm.next = state.result; - tailTerm = state.result; - while (tailTerm.next != null) tailTerm = tailTerm.next; - } - else { - tailTerm.next = state.result; - tailTerm = tailTerm.next; - while (tailTerm.next != null) tailTerm = tailTerm.next; - } - } - } - } - - /* calculate the total size of the bitmap required for a class expression */ - private static boolean - calculateBitmapSize(CompilerState state, RENode target, char[] src, - int index, int end) - { - char rangeStart = 0; - char c; - int n; - int nDigits; - int i; - int max = 0; - boolean inRange = false; - - target.bmsize = 0; - - if (index == end) - return true; - - if (src[index] == '^') - ++index; - - while (index != end) { - int localMax = 0; - nDigits = 2; - switch (src[index]) { - case '\\': - ++index; - c = src[index++]; - switch (c) { - case 'b': - localMax = 0x8; - break; - case 'f': - localMax = 0xC; - break; - case 'n': - localMax = 0xA; - break; - case 'r': - localMax = 0xD; - break; - case 't': - localMax = 0x9; - break; - case 'v': - localMax = 0xB; - break; - case 'c': - if (((index + 1) < end) && Character.isLetter(src[index + 1])) - localMax = (char)(src[index++] & 0x1F); - else - localMax = '\\'; - break; - case 'u': - nDigits += 2; - // fall thru... - case 'x': - n = 0; - for (i = 0; (i < nDigits) && (index < end); i++) { - c = src[index++]; - n = Kit.xDigitToInt(c, n); - if (n < 0) { - // Back off to accepting the original - // '\' as a literal - index -= (i + 1); - n = '\\'; - break; - } - } - localMax = n; - break; - case 'd': - if (inRange) { - reportError("msg.bad.range", ""); - return false; - } - localMax = '9'; - break; - case 'D': - case 's': - case 'S': - case 'w': - case 'W': - if (inRange) { - reportError("msg.bad.range", ""); - return false; - } - target.bmsize = 65535; - return true; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - /* - * This is a non-ECMA extension - decimal escapes (in this - * case, octal!) are supposed to be an error inside class - * ranges, but supported here for backwards compatibility. - * - */ - n = (c - '0'); - c = src[index]; - if ('0' <= c && c <= '7') { - index++; - n = 8 * n + (c - '0'); - c = src[index]; - if ('0' <= c && c <= '7') { - index++; - i = 8 * n + (c - '0'); - if (i <= 0377) - n = i; - else - index--; - } - } - localMax = n; - break; - - default: - localMax = c; - break; - } - break; - default: - localMax = src[index++]; - break; - } - if (inRange) { - if (rangeStart > localMax) { - reportError("msg.bad.range", ""); - return false; - } - inRange = false; - } - else { - if (index < (end - 1)) { - if (src[index] == '-') { - ++index; - inRange = true; - rangeStart = (char)localMax; - continue; - } - } - } - if ((state.flags & JSREG_FOLD) != 0){ - char cu = upcase((char)localMax); - char cd = downcase((char)localMax); - localMax = (cu >= cd) ? cu : cd; - } - if (localMax > max) - max = localMax; - } - target.bmsize = max; - return true; - } - - /* - * item: assertion An item is either an assertion or - * quantatom a quantified atom. - * - * assertion: '^' Assertions match beginning of string - * (or line if the class static property - * RegExp.multiline is true). - * '$' End of string (or line if the class - * static property RegExp.multiline is - * true). - * '\b' Word boundary (between \w and \W). - * '\B' Word non-boundary. - * - * quantatom: atom An unquantified atom. - * quantatom '{' n ',' m '}' - * Atom must occur between n and m times. - * quantatom '{' n ',' '}' Atom must occur at least n times. - * quantatom '{' n '}' Atom must occur exactly n times. - * quantatom '*' Zero or more times (same as {0,}). - * quantatom '+' One or more times (same as {1,}). - * quantatom '?' Zero or one time (same as {0,1}). - * - * any of which can be optionally followed by '?' for ungreedy - * - * atom: '(' regexp ')' A parenthesized regexp (what matched - * can be addressed using a backreference, - * see '\' n below). - * '.' Matches any char except '\n'. - * '[' classlist ']' A character class. - * '[' '^' classlist ']' A negated character class. - * '\f' Form Feed. - * '\n' Newline (Line Feed). - * '\r' Carriage Return. - * '\t' Horizontal Tab. - * '\v' Vertical Tab. - * '\d' A digit (same as [0-9]). - * '\D' A non-digit. - * '\w' A word character, [0-9a-z_A-Z]. - * '\W' A non-word character. - * '\s' A whitespace character, [ \b\f\n\r\t\v]. - * '\S' A non-whitespace character. - * '\' n A backreference to the nth (n decimal - * and positive) parenthesized expression. - * '\' octal An octal escape sequence (octal must be - * two or three digits long, unless it is - * 0 for the null character). - * '\x' hex A hex escape (hex must be two digits). - * '\c' ctrl A control character, ctrl is a letter. - * '\' literalatomchar Any character except one of the above - * that follow '\' in an atom. - * otheratomchar Any character not first among the other - * atom right-hand sides. - */ - - private static void doFlat(CompilerState state, char c) - { - state.result = new RENode(REOP_FLAT); - state.result.chr = c; - state.result.length = 1; - state.result.flatIndex = -1; - state.progLength += 3; - } - - private static int - getDecimalValue(char c, CompilerState state, int maxValue, - String overflowMessageId) - { - boolean overflow = false; - int start = state.cp; - char[] src = state.cpbegin; - int value = c - '0'; - for (; state.cp != state.cpend; ++state.cp) { - c = src[state.cp]; - if (!isDigit(c)) { - break; - } - if (!overflow) { - int digit = c - '0'; - if (value < (maxValue - digit) / 10) { - value = value * 10 + digit; - } else { - overflow = true; - value = maxValue; - } - } - } - if (overflow) { - reportError(overflowMessageId, - String.valueOf(src, start, state.cp - start)); - } - return value; - } - - private static boolean - parseTerm(CompilerState state) - { - char[] src = state.cpbegin; - char c = src[state.cp++]; - int nDigits = 2; - int parenBaseCount = state.parenCount; - int num, tmp; - RENode term; - int termStart; - - switch (c) { - /* assertions and atoms */ - case '^': - state.result = new RENode(REOP_BOL); - state.progLength++; - return true; - case '$': - state.result = new RENode(REOP_EOL); - state.progLength++; - return true; - case '\\': - if (state.cp < state.cpend) { - c = src[state.cp++]; - switch (c) { - /* assertion escapes */ - case 'b' : - state.result = new RENode(REOP_WBDRY); - state.progLength++; - return true; - case 'B': - state.result = new RENode(REOP_WNONBDRY); - state.progLength++; - return true; - /* Decimal escape */ - case '0': -/* - * Under 'strict' ECMA 3, we interpret \0 as NUL and don't accept octal. - * However, (XXX and since Rhino doesn't have a 'strict' mode) we'll just - * behave the old way for compatibility reasons. - * (see http://bugzilla.mozilla.org/show_bug.cgi?id=141078) - * - */ - reportWarning(state.cx, "msg.bad.backref", ""); - /* octal escape */ - num = 0; - while (state.cp < state.cpend) { - c = src[state.cp]; - if ((c >= '0') && (c <= '7')) { - state.cp++; - tmp = 8 * num + (c - '0'); - if (tmp > 0377) - break; - num = tmp; - } - else - break; - } - c = (char)(num); - doFlat(state, c); - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - termStart = state.cp - 1; - num = getDecimalValue(c, state, 0xFFFF, - "msg.overlarge.backref"); - if (num > state.parenCount) - reportWarning(state.cx, "msg.bad.backref", ""); - /* - * n > 9 or > count of parentheses, - * then treat as octal instead. - */ - if ((num > 9) && (num > state.parenCount)) { - state.cp = termStart; - num = 0; - while (state.cp < state.cpend) { - c = src[state.cp]; - if ((c >= '0') && (c <= '7')) { - state.cp++; - tmp = 8 * num + (c - '0'); - if (tmp > 0377) - break; - num = tmp; - } - else - break; - } - c = (char)(num); - doFlat(state, c); - break; - } - /* otherwise, it's a back-reference */ - state.result = new RENode(REOP_BACKREF); - state.result.parenIndex = num - 1; - state.progLength += 3; - break; - /* Control escape */ - case 'f': - c = 0xC; - doFlat(state, c); - break; - case 'n': - c = 0xA; - doFlat(state, c); - break; - case 'r': - c = 0xD; - doFlat(state, c); - break; - case 't': - c = 0x9; - doFlat(state, c); - break; - case 'v': - c = 0xB; - doFlat(state, c); - break; - /* Control letter */ - case 'c': - if (((state.cp + 1) < state.cpend) && - Character.isLetter(src[state.cp + 1])) - c = (char)(src[state.cp++] & 0x1F); - else { - /* back off to accepting the original '\' as a literal */ - --state.cp; - c = '\\'; - } - doFlat(state, c); - break; - /* UnicodeEscapeSequence */ - case 'u': - nDigits += 2; - // fall thru... - /* HexEscapeSequence */ - case 'x': - { - int n = 0; - int i; - for (i = 0; (i < nDigits) - && (state.cp < state.cpend); i++) { - c = src[state.cp++]; - n = Kit.xDigitToInt(c, n); - if (n < 0) { - // Back off to accepting the original - // 'u' or 'x' as a literal - state.cp -= (i + 2); - n = src[state.cp++]; - break; - } - } - c = (char)(n); - } - doFlat(state, c); - break; - /* Character class escapes */ - case 'd': - state.result = new RENode(REOP_DIGIT); - state.progLength++; - break; - case 'D': - state.result = new RENode(REOP_NONDIGIT); - state.progLength++; - break; - case 's': - state.result = new RENode(REOP_SPACE); - state.progLength++; - break; - case 'S': - state.result = new RENode(REOP_NONSPACE); - state.progLength++; - break; - case 'w': - state.result = new RENode(REOP_ALNUM); - state.progLength++; - break; - case 'W': - state.result = new RENode(REOP_NONALNUM); - state.progLength++; - break; - /* IdentityEscape */ - default: - state.result = new RENode(REOP_FLAT); - state.result.chr = c; - state.result.length = 1; - state.result.flatIndex = state.cp - 1; - state.progLength += 3; - break; - } - break; - } - else { - /* a trailing '\' is an error */ - reportError("msg.trail.backslash", ""); - return false; - } - case '(': { - RENode result = null; - termStart = state.cp; - if (state.cp + 1 < state.cpend && src[state.cp] == '?' - && ((c = src[state.cp + 1]) == '=' || c == '!' || c == ':')) - { - state.cp += 2; - if (c == '=') { - result = new RENode(REOP_ASSERT); - /* ASSERT, <next>, ... ASSERTTEST */ - state.progLength += 4; - } else if (c == '!') { - result = new RENode(REOP_ASSERT_NOT); - /* ASSERTNOT, <next>, ... ASSERTNOTTEST */ - state.progLength += 4; - } - } else { - result = new RENode(REOP_LPAREN); - /* LPAREN, <index>, ... RPAREN, <index> */ - state.progLength += 6; - result.parenIndex = state.parenCount++; - } - ++state.parenNesting; - if (!parseDisjunction(state)) - return false; - if (state.cp == state.cpend || src[state.cp] != ')') { - reportError("msg.unterm.paren", "in regular expression"/*APPJET*/); - return false; - } - ++state.cp; - --state.parenNesting; - if (result != null) { - result.kid = state.result; - state.result = result; - } - break; - } - case ')': - reportError("msg.re.unmatched.right.paren", ""); - return false; - case '[': - state.result = new RENode(REOP_CLASS); - termStart = state.cp; - state.result.startIndex = termStart; - while (true) { - if (state.cp == state.cpend) { - reportError("msg.unterm.class", ""); - return false; - } - if (src[state.cp] == '\\') - state.cp++; - else { - if (src[state.cp] == ']') { - state.result.kidlen = state.cp - termStart; - break; - } - } - state.cp++; - } - state.result.index = state.classCount++; - /* - * Call calculateBitmapSize now as we want any errors it finds - * to be reported during the parse phase, not at execution. - */ - if (!calculateBitmapSize(state, state.result, src, termStart, state.cp++)) - return false; - state.progLength += 3; /* CLASS, <index> */ - break; - - case '.': - state.result = new RENode(REOP_DOT); - state.progLength++; - break; - case '*': - case '+': - case '?': - reportError("msg.bad.quant", String.valueOf(src[state.cp - 1])); - return false; - default: - state.result = new RENode(REOP_FLAT); - state.result.chr = c; - state.result.length = 1; - state.result.flatIndex = state.cp - 1; - state.progLength += 3; - break; - } - - term = state.result; - if (state.cp == state.cpend) { - return true; - } - boolean hasQ = false; - switch (src[state.cp]) { - case '+': - state.result = new RENode(REOP_QUANT); - state.result.min = 1; - state.result.max = -1; - /* <PLUS>, <parencount>, <parenindex>, <next> ... <ENDCHILD> */ - state.progLength += 8; - hasQ = true; - break; - case '*': - state.result = new RENode(REOP_QUANT); - state.result.min = 0; - state.result.max = -1; - /* <STAR>, <parencount>, <parenindex>, <next> ... <ENDCHILD> */ - state.progLength += 8; - hasQ = true; - break; - case '?': - state.result = new RENode(REOP_QUANT); - state.result.min = 0; - state.result.max = 1; - /* <OPT>, <parencount>, <parenindex>, <next> ... <ENDCHILD> */ - state.progLength += 8; - hasQ = true; - break; - case '{': /* balance '}' */ - { - int min = 0; - int max = -1; - int leftCurl = state.cp; - - /* For Perl etc. compatibility, if quntifier does not match - * \{\d+(,\d*)?\} exactly back off from it - * being a quantifier, and chew it up as a literal - * atom next time instead. - */ - - c = src[++state.cp]; - if (isDigit(c)) { - ++state.cp; - min = getDecimalValue(c, state, 0xFFFF, - "msg.overlarge.min"); - c = src[state.cp]; - if (c == ',') { - c = src[++state.cp]; - if (isDigit(c)) { - ++state.cp; - max = getDecimalValue(c, state, 0xFFFF, - "msg.overlarge.max"); - c = src[state.cp]; - if (min > max) { - reportError("msg.max.lt.min", - String.valueOf(src[state.cp])); - return false; - } - } - } else { - max = min; - } - /* balance '{' */ - if (c == '}') { - state.result = new RENode(REOP_QUANT); - state.result.min = min; - state.result.max = max; - // QUANT, <min>, <max>, <parencount>, - // <parenindex>, <next> ... <ENDCHILD> - state.progLength += 12; - hasQ = true; - } - } - if (!hasQ) { - state.cp = leftCurl; - } - break; - } - } - if (!hasQ) - return true; - - ++state.cp; - state.result.kid = term; - state.result.parenIndex = parenBaseCount; - state.result.parenCount = state.parenCount - parenBaseCount; - if ((state.cp < state.cpend) && (src[state.cp] == '?')) { - ++state.cp; - state.result.greedy = false; - } - else - state.result.greedy = true; - return true; - } - - private static void resolveForwardJump(byte[] array, int from, int pc) - { - if (from > pc) throw Kit.codeBug(); - addIndex(array, from, pc - from); - } - - private static int getOffset(byte[] array, int pc) - { - return getIndex(array, pc); - } - - private static int addIndex(byte[] array, int pc, int index) - { - if (index < 0) throw Kit.codeBug(); - if (index > 0xFFFF) - throw Context.reportRuntimeError("Too complex regexp"); - array[pc] = (byte)(index >> 8); - array[pc + 1] = (byte)(index); - return pc + 2; - } - - private static int getIndex(byte[] array, int pc) - { - return ((array[pc] & 0xFF) << 8) | (array[pc + 1] & 0xFF); - } - - private static final int OFFSET_LEN = 2; - private static final int INDEX_LEN = 2; - - private static int - emitREBytecode(CompilerState state, RECompiled re, int pc, RENode t) - { - RENode nextAlt; - int nextAltFixup, nextTermFixup; - byte[] program = re.program; - - while (t != null) { - program[pc++] = t.op; - switch (t.op) { - case REOP_EMPTY: - --pc; - break; - case REOP_ALT: - nextAlt = t.kid2; - nextAltFixup = pc; /* address of next alternate */ - pc += OFFSET_LEN; - pc = emitREBytecode(state, re, pc, t.kid); - program[pc++] = REOP_JUMP; - nextTermFixup = pc; /* address of following term */ - pc += OFFSET_LEN; - resolveForwardJump(program, nextAltFixup, pc); - pc = emitREBytecode(state, re, pc, nextAlt); - - program[pc++] = REOP_JUMP; - nextAltFixup = pc; - pc += OFFSET_LEN; - - resolveForwardJump(program, nextTermFixup, pc); - resolveForwardJump(program, nextAltFixup, pc); - break; - case REOP_FLAT: - /* - * Consecutize FLAT's if possible. - */ - if (t.flatIndex != -1) { - while ((t.next != null) && (t.next.op == REOP_FLAT) - && ((t.flatIndex + t.length) - == t.next.flatIndex)) { - t.length += t.next.length; - t.next = t.next.next; - } - } - if ((t.flatIndex != -1) && (t.length > 1)) { - if ((state.flags & JSREG_FOLD) != 0) - program[pc - 1] = REOP_FLATi; - else - program[pc - 1] = REOP_FLAT; - pc = addIndex(program, pc, t.flatIndex); - pc = addIndex(program, pc, t.length); - } - else { - if (t.chr < 256) { - if ((state.flags & JSREG_FOLD) != 0) - program[pc - 1] = REOP_FLAT1i; - else - program[pc - 1] = REOP_FLAT1; - program[pc++] = (byte)(t.chr); - } - else { - if ((state.flags & JSREG_FOLD) != 0) - program[pc - 1] = REOP_UCFLAT1i; - else - program[pc - 1] = REOP_UCFLAT1; - pc = addIndex(program, pc, t.chr); - } - } - break; - case REOP_LPAREN: - pc = addIndex(program, pc, t.parenIndex); - pc = emitREBytecode(state, re, pc, t.kid); - program[pc++] = REOP_RPAREN; - pc = addIndex(program, pc, t.parenIndex); - break; - case REOP_BACKREF: - pc = addIndex(program, pc, t.parenIndex); - break; - case REOP_ASSERT: - nextTermFixup = pc; - pc += OFFSET_LEN; - pc = emitREBytecode(state, re, pc, t.kid); - program[pc++] = REOP_ASSERTTEST; - resolveForwardJump(program, nextTermFixup, pc); - break; - case REOP_ASSERT_NOT: - nextTermFixup = pc; - pc += OFFSET_LEN; - pc = emitREBytecode(state, re, pc, t.kid); - program[pc++] = REOP_ASSERTNOTTEST; - resolveForwardJump(program, nextTermFixup, pc); - break; - case REOP_QUANT: - if ((t.min == 0) && (t.max == -1)) - program[pc - 1] = (t.greedy) ? REOP_STAR : REOP_MINIMALSTAR; - else - if ((t.min == 0) && (t.max == 1)) - program[pc - 1] = (t.greedy) ? REOP_OPT : REOP_MINIMALOPT; - else - if ((t.min == 1) && (t.max == -1)) - program[pc - 1] = (t.greedy) ? REOP_PLUS : REOP_MINIMALPLUS; - else { - if (!t.greedy) program[pc - 1] = REOP_MINIMALQUANT; - pc = addIndex(program, pc, t.min); - // max can be -1 which addIndex does not accept - pc = addIndex(program, pc, t.max + 1); - } - pc = addIndex(program, pc, t.parenCount); - pc = addIndex(program, pc, t.parenIndex); - nextTermFixup = pc; - pc += OFFSET_LEN; - pc = emitREBytecode(state, re, pc, t.kid); - program[pc++] = REOP_ENDCHILD; - resolveForwardJump(program, nextTermFixup, pc); - break; - case REOP_CLASS: - pc = addIndex(program, pc, t.index); - re.classList[t.index] = new RECharSet(t.bmsize, t.startIndex, - t.kidlen); - break; - default: - break; - } - t = t.next; - } - return pc; - } - - private static void - pushProgState(REGlobalData gData, int min, int max, - REBackTrackData backTrackLastToSave, - int continuation_pc, int continuation_op) - { - gData.stateStackTop = new REProgState(gData.stateStackTop, min, max, - gData.cp, backTrackLastToSave, - continuation_pc, - continuation_op); - } - - private static REProgState - popProgState(REGlobalData gData) - { - REProgState state = gData.stateStackTop; - gData.stateStackTop = state.previous; - return state; - } - - private static void - pushBackTrackState(REGlobalData gData, byte op, int target) - { - gData.backTrackStackTop = new REBackTrackData(gData, op, target); - } - - /* - * Consecutive literal characters. - */ - private static boolean - flatNMatcher(REGlobalData gData, int matchChars, - int length, char[] chars, int end) - { - if ((gData.cp + length) > end) - return false; - for (int i = 0; i < length; i++) { - if (gData.regexp.source[matchChars + i] != chars[gData.cp + i]) { - return false; - } - } - gData.cp += length; - return true; - } - - private static boolean - flatNIMatcher(REGlobalData gData, int matchChars, - int length, char[] chars, int end) - { - if ((gData.cp + length) > end) - return false; - for (int i = 0; i < length; i++) { - if (upcase(gData.regexp.source[matchChars + i]) - != upcase(chars[gData.cp + i])) - { - return false; - } - } - gData.cp += length; - return true; - } - - /* - 1. Evaluate DecimalEscape to obtain an EscapeValue E. - 2. If E is not a character then go to step 6. - 3. Let ch be E's character. - 4. Let A be a one-element RECharSet containing the character ch. - 5. Call CharacterSetMatcher(A, false) and return its Matcher result. - 6. E must be an integer. Let n be that integer. - 7. If n=0 or n>NCapturingParens then throw a SyntaxError exception. - 8. Return an internal Matcher closure that takes two arguments, a State x - and a Continuation c, and performs the following: - 1. Let cap be x's captures internal array. - 2. Let s be cap[n]. - 3. If s is undefined, then call c(x) and return its result. - 4. Let e be x's endIndex. - 5. Let len be s's length. - 6. Let f be e+len. - 7. If f>InputLength, return failure. - 8. If there exists an integer i between 0 (inclusive) and len (exclusive) - such that Canonicalize(s[i]) is not the same character as - Canonicalize(Input [e+i]), then return failure. - 9. Let y be the State (f, cap). - 10. Call c(y) and return its result. - */ - private static boolean - backrefMatcher(REGlobalData gData, int parenIndex, - char[] chars, int end) - { - int len; - int i; - int parenContent = gData.parens_index(parenIndex); - if (parenContent == -1) - return true; - - len = gData.parens_length(parenIndex); - if ((gData.cp + len) > end) - return false; - - if ((gData.regexp.flags & JSREG_FOLD) != 0) { - for (i = 0; i < len; i++) { - if (upcase(chars[parenContent + i]) != upcase(chars[gData.cp + i])) - return false; - } - } - else { - for (i = 0; i < len; i++) { - if (chars[parenContent + i] != chars[gData.cp + i]) - return false; - } - } - gData.cp += len; - return true; - } - - - /* Add a single character to the RECharSet */ - private static void - addCharacterToCharSet(RECharSet cs, char c) - { - int byteIndex = (c / 8); - if (c > cs.length) - throw new RuntimeException(); - cs.bits[byteIndex] |= 1 << (c & 0x7); - } - - - /* Add a character range, c1 to c2 (inclusive) to the RECharSet */ - private static void - addCharacterRangeToCharSet(RECharSet cs, char c1, char c2) - { - int i; - - int byteIndex1 = (c1 / 8); - int byteIndex2 = (c2 / 8); - - if ((c2 > cs.length) || (c1 > c2)) - throw new RuntimeException(); - - c1 &= 0x7; - c2 &= 0x7; - - if (byteIndex1 == byteIndex2) { - cs.bits[byteIndex1] |= ((0xFF) >> (7 - (c2 - c1))) << c1; - } - else { - cs.bits[byteIndex1] |= 0xFF << c1; - for (i = byteIndex1 + 1; i < byteIndex2; i++) - cs.bits[i] = (byte)0xFF; - cs.bits[byteIndex2] |= (0xFF) >> (7 - c2); - } - } - - /* Compile the source of the class into a RECharSet */ - private static void - processCharSet(REGlobalData gData, RECharSet charSet) - { - synchronized (charSet) { - if (!charSet.converted) { - processCharSetImpl(gData, charSet); - charSet.converted = true; - } - } - } - - - private static void - processCharSetImpl(REGlobalData gData, RECharSet charSet) - { - int src = charSet.startIndex; - int end = src + charSet.strlength; - - char rangeStart = 0, thisCh; - int byteLength; - char c; - int n; - int nDigits; - int i; - boolean inRange = false; - - charSet.sense = true; - byteLength = (charSet.length / 8) + 1; - charSet.bits = new byte[byteLength]; - - if (src == end) - return; - - if (gData.regexp.source[src] == '^') { - charSet.sense = false; - ++src; - } - - while (src != end) { - nDigits = 2; - switch (gData.regexp.source[src]) { - case '\\': - ++src; - c = gData.regexp.source[src++]; - switch (c) { - case 'b': - thisCh = 0x8; - break; - case 'f': - thisCh = 0xC; - break; - case 'n': - thisCh = 0xA; - break; - case 'r': - thisCh = 0xD; - break; - case 't': - thisCh = 0x9; - break; - case 'v': - thisCh = 0xB; - break; - case 'c': - if (((src + 1) < end) && isWord(gData.regexp.source[src + 1])) - thisCh = (char)(gData.regexp.source[src++] & 0x1F); - else { - --src; - thisCh = '\\'; - } - break; - case 'u': - nDigits += 2; - // fall thru - case 'x': - n = 0; - for (i = 0; (i < nDigits) && (src < end); i++) { - c = gData.regexp.source[src++]; - int digit = toASCIIHexDigit(c); - if (digit < 0) { - /* back off to accepting the original '\' - * as a literal - */ - src -= (i + 1); - n = '\\'; - break; - } - n = (n << 4) | digit; - } - thisCh = (char)(n); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - /* - * This is a non-ECMA extension - decimal escapes (in this - * case, octal!) are supposed to be an error inside class - * ranges, but supported here for backwards compatibility. - * - */ - n = (c - '0'); - c = gData.regexp.source[src]; - if ('0' <= c && c <= '7') { - src++; - n = 8 * n + (c - '0'); - c = gData.regexp.source[src]; - if ('0' <= c && c <= '7') { - src++; - i = 8 * n + (c - '0'); - if (i <= 0377) - n = i; - else - src--; - } - } - thisCh = (char)(n); - break; - - case 'd': - addCharacterRangeToCharSet(charSet, '0', '9'); - continue; /* don't need range processing */ - case 'D': - addCharacterRangeToCharSet(charSet, (char)0, (char)('0' - 1)); - addCharacterRangeToCharSet(charSet, (char)('9' + 1), - (char)(charSet.length)); - continue; - case 's': - for (i = charSet.length; i >= 0; i--) - if (isREWhiteSpace(i)) - addCharacterToCharSet(charSet, (char)(i)); - continue; - case 'S': - for (i = charSet.length; i >= 0; i--) - if (!isREWhiteSpace(i)) - addCharacterToCharSet(charSet, (char)(i)); - continue; - case 'w': - for (i = charSet.length; i >= 0; i--) - if (isWord((char)i)) - addCharacterToCharSet(charSet, (char)(i)); - continue; - case 'W': - for (i = charSet.length; i >= 0; i--) - if (!isWord((char)i)) - addCharacterToCharSet(charSet, (char)(i)); - continue; - default: - thisCh = c; - break; - - } - break; - - default: - thisCh = gData.regexp.source[src++]; - break; - - } - if (inRange) { - if ((gData.regexp.flags & JSREG_FOLD) != 0) { - addCharacterRangeToCharSet(charSet, - upcase(rangeStart), - upcase(thisCh)); - addCharacterRangeToCharSet(charSet, - downcase(rangeStart), - downcase(thisCh)); - } else { - addCharacterRangeToCharSet(charSet, rangeStart, thisCh); - } - inRange = false; - } - else { - if ((gData.regexp.flags & JSREG_FOLD) != 0) { - addCharacterToCharSet(charSet, upcase(thisCh)); - addCharacterToCharSet(charSet, downcase(thisCh)); - } else { - addCharacterToCharSet(charSet, thisCh); - } - if (src < (end - 1)) { - if (gData.regexp.source[src] == '-') { - ++src; - inRange = true; - rangeStart = thisCh; - } - } - } - } - } - - - /* - * Initialize the character set if it this is the first call. - * Test the bit - if the ^ flag was specified, non-inclusion is a success - */ - private static boolean - classMatcher(REGlobalData gData, RECharSet charSet, char ch) - { - if (!charSet.converted) { - processCharSet(gData, charSet); - } - - int byteIndex = ch / 8; - if (charSet.sense) { - if ((charSet.length == 0) || - ( (ch > charSet.length) - || ((charSet.bits[byteIndex] & (1 << (ch & 0x7))) == 0) )) - return false; - } else { - if (! ((charSet.length == 0) || - ( (ch > charSet.length) - || ((charSet.bits[byteIndex] & (1 << (ch & 0x7))) == 0) ))) - return false; - } - return true; - } - - private static boolean - executeREBytecode(REGlobalData gData, char[] chars, int end) - { - int pc = 0; - byte program[] = gData.regexp.program; - int currentContinuation_op; - int currentContinuation_pc; - boolean result = false; - - currentContinuation_pc = 0; - currentContinuation_op = REOP_END; -if (debug) { -System.out.println("Input = \"" + new String(chars) + "\", start at " + gData.cp); -} - int op = program[pc++]; - for (;;) { -if (debug) { -System.out.println("Testing at " + gData.cp + ", op = " + op); -} - switch (op) { - case REOP_EMPTY: - result = true; - break; - case REOP_BOL: - if (gData.cp != 0) { - if (gData.multiline || - ((gData.regexp.flags & JSREG_MULTILINE) != 0)) { - if (!isLineTerm(chars[gData.cp - 1])) { - result = false; - break; - } - } - else { - result = false; - break; - } - } - result = true; - break; - case REOP_EOL: - if (gData.cp != end) { - if (gData.multiline || - ((gData.regexp.flags & JSREG_MULTILINE) != 0)) { - if (!isLineTerm(chars[gData.cp])) { - result = false; - break; - } - } - else { - result = false; - break; - } - } - result = true; - break; - case REOP_WBDRY: - result = ((gData.cp == 0 || !isWord(chars[gData.cp - 1])) - ^ !((gData.cp < end) && isWord(chars[gData.cp]))); - break; - case REOP_WNONBDRY: - result = ((gData.cp == 0 || !isWord(chars[gData.cp - 1])) - ^ ((gData.cp < end) && isWord(chars[gData.cp]))); - break; - case REOP_DOT: - result = (gData.cp != end && !isLineTerm(chars[gData.cp])); - if (result) { - gData.cp++; - } - break; - case REOP_DIGIT: - result = (gData.cp != end && isDigit(chars[gData.cp])); - if (result) { - gData.cp++; - } - break; - case REOP_NONDIGIT: - result = (gData.cp != end && !isDigit(chars[gData.cp])); - if (result) { - gData.cp++; - } - break; - case REOP_SPACE: - result = (gData.cp != end && isREWhiteSpace(chars[gData.cp])); - if (result) { - gData.cp++; - } - break; - case REOP_NONSPACE: - result = (gData.cp != end && !isREWhiteSpace(chars[gData.cp])); - if (result) { - gData.cp++; - } - break; - case REOP_ALNUM: - result = (gData.cp != end && isWord(chars[gData.cp])); - if (result) { - gData.cp++; - } - break; - case REOP_NONALNUM: - result = (gData.cp != end && !isWord(chars[gData.cp])); - if (result) { - gData.cp++; - } - break; - case REOP_FLAT: - { - int offset = getIndex(program, pc); - pc += INDEX_LEN; - int length = getIndex(program, pc); - pc += INDEX_LEN; - result = flatNMatcher(gData, offset, length, chars, end); - } - break; - case REOP_FLATi: - { - int offset = getIndex(program, pc); - pc += INDEX_LEN; - int length = getIndex(program, pc); - pc += INDEX_LEN; - result = flatNIMatcher(gData, offset, length, chars, end); - } - break; - case REOP_FLAT1: - { - char matchCh = (char)(program[pc++] & 0xFF); - result = (gData.cp != end && chars[gData.cp] == matchCh); - if (result) { - gData.cp++; - } - } - break; - case REOP_FLAT1i: - { - char matchCh = (char)(program[pc++] & 0xFF); - result = (gData.cp != end - && upcase(chars[gData.cp]) == upcase(matchCh)); - if (result) { - gData.cp++; - } - } - break; - case REOP_UCFLAT1: - { - char matchCh = (char)getIndex(program, pc); - pc += INDEX_LEN; - result = (gData.cp != end && chars[gData.cp] == matchCh); - if (result) { - gData.cp++; - } - } - break; - case REOP_UCFLAT1i: - { - char matchCh = (char)getIndex(program, pc); - pc += INDEX_LEN; - result = (gData.cp != end - && upcase(chars[gData.cp]) == upcase(matchCh)); - if (result) { - gData.cp++; - } - } - break; - case REOP_ALT: - { - int nextpc; - byte nextop; - pushProgState(gData, 0, 0, null, - currentContinuation_pc, - currentContinuation_op); - nextpc = pc + getOffset(program, pc); - nextop = program[nextpc++]; - pushBackTrackState(gData, nextop, nextpc); - pc += INDEX_LEN; - op = program[pc++]; - } - continue; - - case REOP_JUMP: - { - int offset; - REProgState state = popProgState(gData); - currentContinuation_pc = state.continuation_pc; - currentContinuation_op = state.continuation_op; - offset = getOffset(program, pc); - pc += offset; - op = program[pc++]; - } - continue; - - - case REOP_LPAREN: - { - int parenIndex = getIndex(program, pc); - pc += INDEX_LEN; - gData.set_parens(parenIndex, gData.cp, 0); - op = program[pc++]; - } - continue; - case REOP_RPAREN: - { - int cap_index; - int parenIndex = getIndex(program, pc); - pc += INDEX_LEN; - cap_index = gData.parens_index(parenIndex); - gData.set_parens(parenIndex, cap_index, - gData.cp - cap_index); - if (parenIndex > gData.lastParen) - gData.lastParen = parenIndex; - op = program[pc++]; - } - continue; - case REOP_BACKREF: - { - int parenIndex = getIndex(program, pc); - pc += INDEX_LEN; - result = backrefMatcher(gData, parenIndex, chars, end); - } - break; - - case REOP_CLASS: - { - int index = getIndex(program, pc); - pc += INDEX_LEN; - if (gData.cp != end) { - if (classMatcher(gData, gData.regexp.classList[index], - chars[gData.cp])) - { - gData.cp++; - result = true; - break; - } - } - result = false; - } - break; - - case REOP_ASSERT: - case REOP_ASSERT_NOT: - { - byte testOp; - pushProgState(gData, 0, 0, gData.backTrackStackTop, - currentContinuation_pc, - currentContinuation_op); - if (op == REOP_ASSERT) { - testOp = REOP_ASSERTTEST; - } else { - testOp = REOP_ASSERTNOTTEST; - } - pushBackTrackState(gData, testOp, - pc + getOffset(program, pc)); - pc += INDEX_LEN; - op = program[pc++]; - } - continue; - - case REOP_ASSERTTEST: - case REOP_ASSERTNOTTEST: - { - REProgState state = popProgState(gData); - gData.cp = state.index; - gData.backTrackStackTop = state.backTrack; - currentContinuation_pc = state.continuation_pc; - currentContinuation_op = state.continuation_op; - if (result) { - if (op == REOP_ASSERTTEST) { - result = true; - } else { - result = false; - } - } else { - if (op == REOP_ASSERTTEST) { - // Do nothing - } else { - result = true; - } - } - } - break; - - case REOP_STAR: - case REOP_PLUS: - case REOP_OPT: - case REOP_QUANT: - case REOP_MINIMALSTAR: - case REOP_MINIMALPLUS: - case REOP_MINIMALOPT: - case REOP_MINIMALQUANT: - { - int min, max; - boolean greedy = false; - switch (op) { - case REOP_STAR: - greedy = true; - // fallthrough - case REOP_MINIMALSTAR: - min = 0; - max = -1; - break; - case REOP_PLUS: - greedy = true; - // fallthrough - case REOP_MINIMALPLUS: - min = 1; - max = -1; - break; - case REOP_OPT: - greedy = true; - // fallthrough - case REOP_MINIMALOPT: - min = 0; - max = 1; - break; - case REOP_QUANT: - greedy = true; - // fallthrough - case REOP_MINIMALQUANT: - min = getOffset(program, pc); - pc += INDEX_LEN; - // See comments in emitREBytecode for " - 1" reason - max = getOffset(program, pc) - 1; - pc += INDEX_LEN; - break; - default: - throw Kit.codeBug(); - } - pushProgState(gData, min, max, null, - currentContinuation_pc, - currentContinuation_op); - if (greedy) { - currentContinuation_op = REOP_REPEAT; - currentContinuation_pc = pc; - pushBackTrackState(gData, REOP_REPEAT, pc); - /* Step over <parencount>, <parenindex> & <next> */ - pc += 3 * INDEX_LEN; - op = program[pc++]; - } else { - if (min != 0) { - currentContinuation_op = REOP_MINIMALREPEAT; - currentContinuation_pc = pc; - /* <parencount> <parenindex> & <next> */ - pc += 3 * INDEX_LEN; - op = program[pc++]; - } else { - pushBackTrackState(gData, REOP_MINIMALREPEAT, pc); - popProgState(gData); - pc += 2 * INDEX_LEN; // <parencount> & <parenindex> - pc = pc + getOffset(program, pc); - op = program[pc++]; - } - } - } - continue; - - case REOP_ENDCHILD: - // Use the current continuation. - pc = currentContinuation_pc; - op = currentContinuation_op; - continue; - - case REOP_REPEAT: - { - REProgState state = popProgState(gData); - if (!result) { - // - // There's been a failure, see if we have enough - // children. - // - if (state.min == 0) - result = true; - currentContinuation_pc = state.continuation_pc; - currentContinuation_op = state.continuation_op; - pc += 2 * INDEX_LEN; /* <parencount> & <parenindex> */ - pc = pc + getOffset(program, pc); - break; - } - else { - if (state.min == 0 && gData.cp == state.index) { - // matched an empty string, that'll get us nowhere - result = false; - currentContinuation_pc = state.continuation_pc; - currentContinuation_op = state.continuation_op; - pc += 2 * INDEX_LEN; - pc = pc + getOffset(program, pc); - break; - } - int new_min = state.min, new_max = state.max; - if (new_min != 0) new_min--; - if (new_max != -1) new_max--; - if (new_max == 0) { - result = true; - currentContinuation_pc = state.continuation_pc; - currentContinuation_op = state.continuation_op; - pc += 2 * INDEX_LEN; - pc = pc + getOffset(program, pc); - break; - } - pushProgState(gData, new_min, new_max, null, - state.continuation_pc, - state.continuation_op); - currentContinuation_op = REOP_REPEAT; - currentContinuation_pc = pc; - pushBackTrackState(gData, REOP_REPEAT, pc); - int parenCount = getIndex(program, pc); - pc += INDEX_LEN; - int parenIndex = getIndex(program, pc); - pc += 2 * INDEX_LEN; - op = program[pc++]; - for (int k = 0; k < parenCount; k++) { - gData.set_parens(parenIndex + k, -1, 0); - } - } - } - continue; - - case REOP_MINIMALREPEAT: - { - REProgState state = popProgState(gData); - if (!result) { - // - // Non-greedy failure - try to consume another child. - // - if (state.max == -1 || state.max > 0) { - pushProgState(gData, state.min, state.max, null, - state.continuation_pc, - state.continuation_op); - currentContinuation_op = REOP_MINIMALREPEAT; - currentContinuation_pc = pc; - int parenCount = getIndex(program, pc); - pc += INDEX_LEN; - int parenIndex = getIndex(program, pc); - pc += 2 * INDEX_LEN; - for (int k = 0; k < parenCount; k++) { - gData.set_parens(parenIndex + k, -1, 0); - } - op = program[pc++]; - continue; - } else { - // Don't need to adjust pc since we're going to pop. - currentContinuation_pc = state.continuation_pc; - currentContinuation_op = state.continuation_op; - break; - } - } else { - if (state.min == 0 && gData.cp == state.index) { - // Matched an empty string, that'll get us nowhere. - result = false; - currentContinuation_pc = state.continuation_pc; - currentContinuation_op = state.continuation_op; - break; - } - int new_min = state.min, new_max = state.max; - if (new_min != 0) new_min--; - if (new_max != -1) new_max--; - pushProgState(gData, new_min, new_max, null, - state.continuation_pc, - state.continuation_op); - if (new_min != 0) { - currentContinuation_op = REOP_MINIMALREPEAT; - currentContinuation_pc = pc; - int parenCount = getIndex(program, pc); - pc += INDEX_LEN; - int parenIndex = getIndex(program, pc); - pc += 2 * INDEX_LEN; - for (int k = 0; k < parenCount; k++) { - gData.set_parens(parenIndex + k, -1, 0); - } - op = program[pc++]; - } else { - currentContinuation_pc = state.continuation_pc; - currentContinuation_op = state.continuation_op; - pushBackTrackState(gData, REOP_MINIMALREPEAT, pc); - popProgState(gData); - pc += 2 * INDEX_LEN; - pc = pc + getOffset(program, pc); - op = program[pc++]; - } - continue; - } - } - - case REOP_END: - return true; - - default: - throw Kit.codeBug(); - - } - /* - * If the match failed and there's a backtrack option, take it. - * Otherwise this is a complete and utter failure. - */ - if (!result) { - REBackTrackData backTrackData = gData.backTrackStackTop; - if (backTrackData != null) { - gData.backTrackStackTop = backTrackData.previous; - - gData.lastParen = backTrackData.lastParen; - - // XXX: If backTrackData will no longer be used, then - // there is no need to clone backTrackData.parens - if (backTrackData.parens != null) { - gData.parens = backTrackData.parens.clone(); - } - - gData.cp = backTrackData.cp; - - gData.stateStackTop = backTrackData.stateStackTop; - - currentContinuation_op - = gData.stateStackTop.continuation_op; - currentContinuation_pc - = gData.stateStackTop.continuation_pc; - pc = backTrackData.continuation_pc; - op = backTrackData.continuation_op; - continue; - } - else - return false; - } - - op = program[pc++]; - } - - } - - private static boolean - matchRegExp(REGlobalData gData, RECompiled re, - char[] chars, int start, int end, boolean multiline) - { - if (re.parenCount != 0) { - gData.parens = new long[re.parenCount]; - } else { - gData.parens = null; - } - - gData.backTrackStackTop = null; - - gData.stateStackTop = null; - - gData.multiline = multiline; - gData.regexp = re; - gData.lastParen = 0; - - int anchorCh = gData.regexp.anchorCh; - // - // have to include the position beyond the last character - // in order to detect end-of-input/line condition - // - for (int i = start; i <= end; ++i) { - // - // If the first node is a literal match, step the index into - // the string until that match is made, or fail if it can't be - // found at all. - // - if (anchorCh >= 0) { - for (;;) { - if (i == end) { - return false; - } - char matchCh = chars[i]; - if (matchCh == anchorCh || - ((gData.regexp.flags & JSREG_FOLD) != 0 - && upcase(matchCh) == upcase((char)anchorCh))) - { - break; - } - ++i; - } - } - gData.cp = i; - for (int j = 0; j < re.parenCount; j++) { - gData.set_parens(j, -1, 0); - } - boolean result = executeREBytecode(gData, chars, end); - - gData.backTrackStackTop = null; - gData.stateStackTop = null; - if (result) { - gData.skipped = i - start; - return true; - } - } - return false; - } - - /* - * indexp is assumed to be an array of length 1 - */ - Object executeRegExp(Context cx, Scriptable scopeObj, RegExpImpl res, - String str, int indexp[], int matchType) - { - REGlobalData gData = new REGlobalData(); - - int start = indexp[0]; - char[] charArray = str.toCharArray(); - int end = charArray.length; - if (start > end) - start = end; - // - // Call the recursive matcher to do the real work. - // - boolean matches = matchRegExp(gData, re, charArray, start, end, - res.multiline); - if (!matches) { - if (matchType != PREFIX) return null; - return Undefined.instance; - } - int index = gData.cp; - int i = index; - indexp[0] = i; - int matchlen = i - (start + gData.skipped); - int ep = index; - index -= matchlen; - Object result; - Scriptable obj; - - if (matchType == TEST) { - /* - * Testing for a match and updating cx.regExpImpl: don't allocate - * an array object, do return true. - */ - result = Boolean.TRUE; - obj = null; - } - else { - /* - * The array returned on match has element 0 bound to the matched - * string, elements 1 through re.parenCount bound to the paren - * matches, an index property telling the length of the left context, - * and an input property referring to the input string. - */ - Scriptable scope = getTopLevelScope(scopeObj); - result = ScriptRuntime.newObject(cx, scope, "Array", null); - obj = (Scriptable) result; - - String matchstr = new String(charArray, index, matchlen); - obj.put(0, obj, matchstr); - } - - if (re.parenCount == 0) { - res.parens = null; - res.lastParen = SubString.emptySubString; - } else { - SubString parsub = null; - int num; - res.parens = new SubString[re.parenCount]; - for (num = 0; num < re.parenCount; num++) { - int cap_index = gData.parens_index(num); - String parstr; - if (cap_index != -1) { - int cap_length = gData.parens_length(num); - parsub = new SubString(charArray, cap_index, cap_length); - res.parens[num] = parsub; - if (matchType == TEST) continue; - parstr = parsub.toString(); - obj.put(num+1, obj, parstr); - } - else { - if (matchType != TEST) - obj.put(num+1, obj, Undefined.instance); - } - } - res.lastParen = parsub; - } - - if (! (matchType == TEST)) { - /* - * Define the index and input properties last for better for/in loop - * order (so they come after the elements). - */ - obj.put("index", obj, new Integer(start + gData.skipped)); - obj.put("input", obj, str); - } - - if (res.lastMatch == null) { - res.lastMatch = new SubString(); - res.leftContext = new SubString(); - res.rightContext = new SubString(); - } - res.lastMatch.charArray = charArray; - res.lastMatch.index = index; - res.lastMatch.length = matchlen; - - res.leftContext.charArray = charArray; - if (cx.getLanguageVersion() == Context.VERSION_1_2) { - /* - * JS1.2 emulated Perl4.0.1.8 (patch level 36) for global regexps used - * in scalar contexts, and unintentionally for the string.match "list" - * psuedo-context. On "hi there bye", the following would result: - * - * Language while(/ /g){print("$`");} s/ /$`/g - * perl4.036 "hi", "there" "hihitherehi therebye" - * perl5 "hi", "hi there" "hihitherehi therebye" - * js1.2 "hi", "there" "hihitheretherebye" - * - * Insofar as JS1.2 always defined $` as "left context from the last - * match" for global regexps, it was more consistent than perl4. - */ - res.leftContext.index = start; - res.leftContext.length = gData.skipped; - } else { - /* - * For JS1.3 and ECMAv2, emulate Perl5 exactly: - * - * js1.3 "hi", "hi there" "hihitherehi therebye" - */ - res.leftContext.index = 0; - res.leftContext.length = start + gData.skipped; - } - - res.rightContext.charArray = charArray; - res.rightContext.index = ep; - res.rightContext.length = end - ep; - - return result; - } - - int getFlags() - { - return re.flags; - } - - private static void reportWarning(Context cx, String messageId, String arg) - { - if (cx.hasFeature(Context.FEATURE_STRICT_MODE)) { - String msg = ScriptRuntime.getMessage1(messageId, arg); - Context.reportWarning(msg); - } - } - - private static void reportError(String messageId, String arg) - { - String msg = ScriptRuntime.getMessage1(messageId, arg); - throw ScriptRuntime.constructError("SyntaxError", msg); - } - -// #string_id_map# - - private static final int - Id_lastIndex = 1, - Id_source = 2, - Id_global = 3, - Id_ignoreCase = 4, - Id_multiline = 5, - - MAX_INSTANCE_ID = 5; - - protected int getMaxInstanceId() - { - return MAX_INSTANCE_ID; - } - - protected int findInstanceIdInfo(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:16:24 EDT - L0: { id = 0; String X = null; int c; - int s_length = s.length(); - if (s_length==6) { - c=s.charAt(0); - if (c=='g') { X="global";id=Id_global; } - else if (c=='s') { X="source";id=Id_source; } - } - else if (s_length==9) { - c=s.charAt(0); - if (c=='l') { X="lastIndex";id=Id_lastIndex; } - else if (c=='m') { X="multiline";id=Id_multiline; } - } - else if (s_length==10) { X="ignoreCase";id=Id_ignoreCase; } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# -// #/string_id_map# - - if (id == 0) return super.findInstanceIdInfo(s); - - int attr; - switch (id) { - case Id_lastIndex: - attr = PERMANENT | DONTENUM; - break; - case Id_source: - case Id_global: - case Id_ignoreCase: - case Id_multiline: - attr = PERMANENT | READONLY | DONTENUM; - break; - default: - throw new IllegalStateException(); - } - return instanceIdInfo(attr, id); - } - - protected String getInstanceIdName(int id) - { - switch (id) { - case Id_lastIndex: return "lastIndex"; - case Id_source: return "source"; - case Id_global: return "global"; - case Id_ignoreCase: return "ignoreCase"; - case Id_multiline: return "multiline"; - } - return super.getInstanceIdName(id); - } - - protected Object getInstanceIdValue(int id) - { - switch (id) { - case Id_lastIndex: - return ScriptRuntime.wrapNumber(lastIndex); - case Id_source: - return new String(re.source); - case Id_global: - return ScriptRuntime.wrapBoolean((re.flags & JSREG_GLOB) != 0); - case Id_ignoreCase: - return ScriptRuntime.wrapBoolean((re.flags & JSREG_FOLD) != 0); - case Id_multiline: - return ScriptRuntime.wrapBoolean((re.flags & JSREG_MULTILINE) != 0); - } - return super.getInstanceIdValue(id); - } - - protected void setInstanceIdValue(int id, Object value) - { - if (id == Id_lastIndex) { - lastIndex = ScriptRuntime.toNumber(value); - return; - } - super.setInstanceIdValue(id, value); - } - - protected void initPrototypeId(int id) - { - String s; - int arity; - switch (id) { - case Id_compile: arity=1; s="compile"; break; - case Id_toString: arity=0; s="toString"; break; - case Id_toSource: arity=0; s="toSource"; break; - case Id_exec: arity=1; s="exec"; break; - case Id_test: arity=1; s="test"; break; - case Id_prefix: arity=1; s="prefix"; break; - default: throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(REGEXP_TAG, id, s, arity); - } - - public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - { - if (!f.hasTag(REGEXP_TAG)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case Id_compile: - return realThis(thisObj, f).compile(cx, scope, args); - - case Id_toString: - case Id_toSource: - return realThis(thisObj, f).toString(); - - case Id_exec: - return realThis(thisObj, f).execSub(cx, scope, args, MATCH); - - case Id_test: { - Object x = realThis(thisObj, f).execSub(cx, scope, args, TEST); - return Boolean.TRUE.equals(x) ? Boolean.TRUE : Boolean.FALSE; - } - - case Id_prefix: - return realThis(thisObj, f).execSub(cx, scope, args, PREFIX); - } - throw new IllegalArgumentException(String.valueOf(id)); - } - - private static NativeRegExp realThis(Scriptable thisObj, IdFunctionObject f) - { - if (!(thisObj instanceof NativeRegExp)) - throw incompatibleCallError(f); - return (NativeRegExp)thisObj; - } - -// #string_id_map# - protected int findPrototypeId(String s) - { - int id; -// #generated# Last update: 2007-05-09 08:16:24 EDT - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 4: c=s.charAt(0); - if (c=='e') { X="exec";id=Id_exec; } - else if (c=='t') { X="test";id=Id_test; } - break L; - case 6: X="prefix";id=Id_prefix; break L; - case 7: X="compile";id=Id_compile; break L; - case 8: c=s.charAt(3); - if (c=='o') { X="toSource";id=Id_toSource; } - else if (c=='t') { X="toString";id=Id_toString; } - break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - break L0; - } -// #/generated# - return id; - } - - private static final int - Id_compile = 1, - Id_toString = 2, - Id_toSource = 3, - Id_exec = 4, - Id_test = 5, - Id_prefix = 6, - - MAX_PROTOTYPE_ID = 6; - -// #/string_id_map# - - private RECompiled re; - double lastIndex; /* index after last match, for //g iterator */ - -} // class NativeRegExp - -class RECompiled implements Serializable -{ - static final long serialVersionUID = -6144956577595844213L; - - char []source; /* locked source string, sans // */ - int parenCount; /* number of parenthesized submatches */ - int flags; /* flags */ - byte[] program; /* regular expression bytecode */ - int classCount; /* count [...] bitmaps */ - RECharSet[] classList; /* list of [...] bitmaps */ - int anchorCh = -1; /* if >= 0, then re starts with this literal char */ -} - -class RENode { - - RENode(byte op) - { - this.op = op; - } - - byte op; /* r.e. op bytecode */ - RENode next; /* next in concatenation order */ - RENode kid; /* first operand */ - - RENode kid2; /* second operand */ - int num; /* could be a number */ - int parenIndex; /* or a parenthesis index */ - - /* or a range */ - int min; - int max; - int parenCount; - boolean greedy; - - /* or a character class */ - int startIndex; - int kidlen; /* length of string at kid, in chars */ - int bmsize; /* bitmap size, based on max char code */ - int index; /* index into class list */ - - /* or a literal sequence */ - char chr; /* of one character */ - int length; /* or many (via the index) */ - int flatIndex; /* which is -1 if not sourced */ - -} - -class CompilerState { - - CompilerState(Context cx, char[] source, int length, int flags) - { - this.cx = cx; - this.cpbegin = source; - this.cp = 0; - this.cpend = length; - this.flags = flags; - this.parenCount = 0; - this.classCount = 0; - this.progLength = 0; - } - - Context cx; - char cpbegin[]; - int cpend; - int cp; - int flags; - int parenCount; - int parenNesting; - int classCount; /* number of [] encountered */ - int progLength; /* estimated bytecode length */ - RENode result; -} - -class REProgState -{ - REProgState(REProgState previous, int min, int max, int index, - REBackTrackData backTrack, - int continuation_pc, int continuation_op) - { - this.previous = previous; - this.min = min; - this.max = max; - this.index = index; - this.continuation_op = continuation_op; - this.continuation_pc = continuation_pc; - this.backTrack = backTrack; - } - - REProgState previous; // previous state in stack - - int min; /* current quantifier min */ - int max; /* current quantifier max */ - int index; /* progress in text */ - int continuation_op; - int continuation_pc; - REBackTrackData backTrack; // used by ASSERT_ to recover state -} - -class REBackTrackData { - - REBackTrackData(REGlobalData gData, int op, int pc) - { - previous = gData.backTrackStackTop; - continuation_op = op; - continuation_pc = pc; - lastParen = gData.lastParen; - if (gData.parens != null) { - parens = gData.parens.clone(); - } - cp = gData.cp; - stateStackTop = gData.stateStackTop; - } - - REBackTrackData previous; - - int continuation_op; /* where to backtrack to */ - int continuation_pc; - int lastParen; - long[] parens; /* parenthesis captures */ - int cp; /* char buffer index */ - REProgState stateStackTop; /* state of op that backtracked */ -} - -class REGlobalData { - boolean multiline; - RECompiled regexp; /* the RE in execution */ - int lastParen; /* highest paren set so far */ - int skipped; /* chars skipped anchoring this r.e. */ - - int cp; /* char buffer index */ - long[] parens; /* parens captures */ - - REProgState stateStackTop; /* stack of state of current ancestors */ - - REBackTrackData backTrackStackTop; /* last matched-so-far position */ - - - /** - * Get start of parenthesis capture contents, -1 for empty. - */ - int parens_index(int i) - { - return (int)(parens[i]); - } - - /** - * Get length of parenthesis capture contents. - */ - int parens_length(int i) - { - return (int)(parens[i] >>> 32); - } - - void set_parens(int i, int index, int length) - { - parens[i] = (index & 0xffffffffL) | ((long)length << 32); - } - -} - -/* - * This struct holds a bitmap representation of a class from a regexp. - * There's a list of these referenced by the classList field in the NativeRegExp - * struct below. The initial state has startIndex set to the offset in the - * original regexp source of the beginning of the class contents. The first - * use of the class converts the source representation into a bitmap. - * - */ -final class RECharSet implements Serializable -{ - static final long serialVersionUID = 7931787979395898394L; - - RECharSet(int length, int startIndex, int strlength) - { - this.length = length; - this.startIndex = startIndex; - this.strlength = strlength; - } - - int length; - int startIndex; - int strlength; - - volatile transient boolean converted; - volatile transient boolean sense; - volatile transient byte[] bits; -} - - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/NativeRegExpCtor.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/NativeRegExpCtor.java deleted file mode 100644 index 808d62d..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/NativeRegExpCtor.java +++ /dev/null @@ -1,289 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Brendan Eich - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.regexp; - -import org.mozilla.javascript.*; - -/** - * This class implements the RegExp constructor native object. - * - * Revision History: - * Implementation in C by Brendan Eich - * Initial port to Java by Norris Boyd from jsregexp.c version 1.36 - * Merged up to version 1.38, which included Unicode support. - * Merged bug fixes in version 1.39. - * Merged JSFUN13_BRANCH changes up to 1.32.2.11 - * - * @author Brendan Eich - * @author Norris Boyd - */ -class NativeRegExpCtor extends BaseFunction -{ - static final long serialVersionUID = -5733330028285400526L; - - NativeRegExpCtor() - { - } - - public String getFunctionName() - { - return "RegExp"; - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - if (args.length > 0 && args[0] instanceof NativeRegExp && - (args.length == 1 || args[1] == Undefined.instance)) - { - return args[0]; - } - return construct(cx, scope, args); - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) - { - NativeRegExp re = new NativeRegExp(); - re.compile(cx, scope, args); - ScriptRuntime.setObjectProtoAndParent(re, scope); - return re; - } - - private static RegExpImpl getImpl() - { - Context cx = Context.getCurrentContext(); - return (RegExpImpl) ScriptRuntime.getRegExpProxy(cx); - } - -// #string_id_map# - - private static final int - Id_multiline = 1, - Id_STAR = 2, // #string=$*# - - Id_input = 3, - Id_UNDERSCORE = 4, // #string=$_# - - Id_lastMatch = 5, - Id_AMPERSAND = 6, // #string=$&# - - Id_lastParen = 7, - Id_PLUS = 8, // #string=$+# - - Id_leftContext = 9, - Id_BACK_QUOTE = 10, // #string=$`# - - Id_rightContext = 11, - Id_QUOTE = 12, // #string=$'# - - DOLLAR_ID_BASE = 12; - - private static final int - Id_DOLLAR_1 = DOLLAR_ID_BASE + 1, // #string=$1# - Id_DOLLAR_2 = DOLLAR_ID_BASE + 2, // #string=$2# - Id_DOLLAR_3 = DOLLAR_ID_BASE + 3, // #string=$3# - Id_DOLLAR_4 = DOLLAR_ID_BASE + 4, // #string=$4# - Id_DOLLAR_5 = DOLLAR_ID_BASE + 5, // #string=$5# - Id_DOLLAR_6 = DOLLAR_ID_BASE + 6, // #string=$6# - Id_DOLLAR_7 = DOLLAR_ID_BASE + 7, // #string=$7# - Id_DOLLAR_8 = DOLLAR_ID_BASE + 8, // #string=$8# - Id_DOLLAR_9 = DOLLAR_ID_BASE + 9, // #string=$9# - - MAX_INSTANCE_ID = DOLLAR_ID_BASE + 9; - - protected int getMaxInstanceId() - { - return super.getMaxInstanceId() + MAX_INSTANCE_ID; - } - - protected int findInstanceIdInfo(String s) { - int id; -// #generated# Last update: 2001-05-24 16:09:31 GMT+02:00 - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 2: switch (s.charAt(1)) { - case '&': if (s.charAt(0)=='$') {id=Id_AMPERSAND; break L0;} break L; - case '\'': if (s.charAt(0)=='$') {id=Id_QUOTE; break L0;} break L; - case '*': if (s.charAt(0)=='$') {id=Id_STAR; break L0;} break L; - case '+': if (s.charAt(0)=='$') {id=Id_PLUS; break L0;} break L; - case '1': if (s.charAt(0)=='$') {id=Id_DOLLAR_1; break L0;} break L; - case '2': if (s.charAt(0)=='$') {id=Id_DOLLAR_2; break L0;} break L; - case '3': if (s.charAt(0)=='$') {id=Id_DOLLAR_3; break L0;} break L; - case '4': if (s.charAt(0)=='$') {id=Id_DOLLAR_4; break L0;} break L; - case '5': if (s.charAt(0)=='$') {id=Id_DOLLAR_5; break L0;} break L; - case '6': if (s.charAt(0)=='$') {id=Id_DOLLAR_6; break L0;} break L; - case '7': if (s.charAt(0)=='$') {id=Id_DOLLAR_7; break L0;} break L; - case '8': if (s.charAt(0)=='$') {id=Id_DOLLAR_8; break L0;} break L; - case '9': if (s.charAt(0)=='$') {id=Id_DOLLAR_9; break L0;} break L; - case '_': if (s.charAt(0)=='$') {id=Id_UNDERSCORE; break L0;} break L; - case '`': if (s.charAt(0)=='$') {id=Id_BACK_QUOTE; break L0;} break L; - } break L; - case 5: X="input";id=Id_input; break L; - case 9: c=s.charAt(4); - if (c=='M') { X="lastMatch";id=Id_lastMatch; } - else if (c=='P') { X="lastParen";id=Id_lastParen; } - else if (c=='i') { X="multiline";id=Id_multiline; } - break L; - case 11: X="leftContext";id=Id_leftContext; break L; - case 12: X="rightContext";id=Id_rightContext; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - } -// #/generated# - - if (id == 0) return super.findInstanceIdInfo(s); - - int attr; - switch (id) { - case Id_multiline: - case Id_STAR: - case Id_input: - case Id_UNDERSCORE: - attr = PERMANENT; - break; - default: - attr = PERMANENT | READONLY; - break; - } - - return instanceIdInfo(attr, super.getMaxInstanceId() + id); - } - -// #/string_id_map# - - protected String getInstanceIdName(int id) - { - int shifted = id - super.getMaxInstanceId(); - if (1 <= shifted && shifted <= MAX_INSTANCE_ID) { - switch (shifted) { - case Id_multiline: return "multiline"; - case Id_STAR: return "$*"; - - case Id_input: return "input"; - case Id_UNDERSCORE: return "$_"; - - case Id_lastMatch: return "lastMatch"; - case Id_AMPERSAND: return "$&"; - - case Id_lastParen: return "lastParen"; - case Id_PLUS: return "$+"; - - case Id_leftContext: return "leftContext"; - case Id_BACK_QUOTE: return "$`"; - - case Id_rightContext: return "rightContext"; - case Id_QUOTE: return "$'"; - } - // Must be one of $1..$9, convert to 0..8 - int substring_number = shifted - DOLLAR_ID_BASE - 1; - char[] buf = { '$', (char)('1' + substring_number) }; - return new String(buf); - } - return super.getInstanceIdName(id); - } - - protected Object getInstanceIdValue(int id) - { - int shifted = id - super.getMaxInstanceId(); - if (1 <= shifted && shifted <= MAX_INSTANCE_ID) { - RegExpImpl impl = getImpl(); - Object stringResult; - switch (shifted) { - case Id_multiline: - case Id_STAR: - return ScriptRuntime.wrapBoolean(impl.multiline); - - case Id_input: - case Id_UNDERSCORE: - stringResult = impl.input; - break; - - case Id_lastMatch: - case Id_AMPERSAND: - stringResult = impl.lastMatch; - break; - - case Id_lastParen: - case Id_PLUS: - stringResult = impl.lastParen; - break; - - case Id_leftContext: - case Id_BACK_QUOTE: - stringResult = impl.leftContext; - break; - - case Id_rightContext: - case Id_QUOTE: - stringResult = impl.rightContext; - break; - - default: - { - // Must be one of $1..$9, convert to 0..8 - int substring_number = shifted - DOLLAR_ID_BASE - 1; - stringResult = impl.getParenSubString(substring_number); - break; - } - } - return (stringResult == null) ? "" : stringResult.toString(); - } - return super.getInstanceIdValue(id); - } - - protected void setInstanceIdValue(int id, Object value) - { - int shifted = id - super.getMaxInstanceId(); - switch (shifted) { - case Id_multiline: - case Id_STAR: - getImpl().multiline = ScriptRuntime.toBoolean(value); - return; - - case Id_input: - case Id_UNDERSCORE: - getImpl().input = ScriptRuntime.toString(value); - return; - } - super.setInstanceIdValue(id, value); - } - -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/RegExpImpl.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/RegExpImpl.java deleted file mode 100644 index 4b0a303..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/RegExpImpl.java +++ /dev/null @@ -1,541 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.regexp; - -import org.mozilla.javascript.*; - -/** - * - */ -public class RegExpImpl implements RegExpProxy { - - public boolean isRegExp(Scriptable obj) { - return obj instanceof NativeRegExp; - } - - public Object compileRegExp(Context cx, String source, String flags) - { - return NativeRegExp.compileRE(cx, source, flags, false); - } - - public Scriptable wrapRegExp(Context cx, Scriptable scope, - Object compiled) - { - return new NativeRegExp(scope, compiled); - } - - public Object action(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args, - int actionType) - { - GlobData data = new GlobData(); - data.mode = actionType; - - switch (actionType) { - case RA_MATCH: - { - Object rval; - data.optarg = 1; - rval = matchOrReplace(cx, scope, thisObj, args, - this, data, false); - return data.arrayobj == null ? rval : data.arrayobj; - } - - case RA_SEARCH: - data.optarg = 1; - return matchOrReplace(cx, scope, thisObj, args, - this, data, false); - - case RA_REPLACE: - { - Object arg1 = args.length < 2 ? Undefined.instance : args[1]; - String repstr = null; - Function lambda = null; - if (arg1 instanceof Function) { - lambda = (Function) arg1; - } else { - repstr = ScriptRuntime.toString(arg1); - } - - data.optarg = 2; - data.lambda = lambda; - data.repstr = repstr; - data.dollar = repstr == null ? -1 : repstr.indexOf('$'); - data.charBuf = null; - data.leftIndex = 0; - Object val = matchOrReplace(cx, scope, thisObj, args, - this, data, true); - SubString rc = this.rightContext; - - if (data.charBuf == null) { - if (data.global || val == null - || !val.equals(Boolean.TRUE)) - { - /* Didn't match even once. */ - return data.str; - } - SubString lc = this.leftContext; - replace_glob(data, cx, scope, this, lc.index, lc.length); - } - data.charBuf.append(rc.charArray, rc.index, rc.length); - return data.charBuf.toString(); - } - - default: - throw Kit.codeBug(); - } - } - - /** - * Analog of C match_or_replace. - */ - private static Object matchOrReplace(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args, - RegExpImpl reImpl, - GlobData data, boolean forceFlat) - { - NativeRegExp re; - - String str = ScriptRuntime.toString(thisObj); - data.str = str; - Scriptable topScope = ScriptableObject.getTopLevelScope(scope); - - if (args.length == 0) { - Object compiled = NativeRegExp.compileRE(cx, "", "", false); - re = new NativeRegExp(topScope, compiled); - } else if (args[0] instanceof NativeRegExp) { - re = (NativeRegExp) args[0]; - } else { - String src = ScriptRuntime.toString(args[0]); - String opt; - if (data.optarg < args.length) { - args[0] = src; - opt = ScriptRuntime.toString(args[data.optarg]); - } else { - opt = null; - } - Object compiled = NativeRegExp.compileRE(cx, src, opt, forceFlat); - re = new NativeRegExp(topScope, compiled); - } - data.regexp = re; - - data.global = (re.getFlags() & NativeRegExp.JSREG_GLOB) != 0; - int[] indexp = { 0 }; - Object result = null; - if (data.mode == RA_SEARCH) { - result = re.executeRegExp(cx, scope, reImpl, - str, indexp, NativeRegExp.TEST); - if (result != null && result.equals(Boolean.TRUE)) - result = new Integer(reImpl.leftContext.length); - else - result = new Integer(-1); - } else if (data.global) { - re.lastIndex = 0; - for (int count = 0; indexp[0] <= str.length(); count++) { - result = re.executeRegExp(cx, scope, reImpl, - str, indexp, NativeRegExp.TEST); - if (result == null || !result.equals(Boolean.TRUE)) - break; - if (data.mode == RA_MATCH) { - match_glob(data, cx, scope, count, reImpl); - } else { - if (data.mode != RA_REPLACE) Kit.codeBug(); - SubString lastMatch = reImpl.lastMatch; - int leftIndex = data.leftIndex; - int leftlen = lastMatch.index - leftIndex; - data.leftIndex = lastMatch.index + lastMatch.length; - replace_glob(data, cx, scope, reImpl, leftIndex, leftlen); - } - if (reImpl.lastMatch.length == 0) { - if (indexp[0] == str.length()) - break; - indexp[0]++; - } - } - } else { - result = re.executeRegExp(cx, scope, reImpl, str, indexp, - ((data.mode == RA_REPLACE) - ? NativeRegExp.TEST - : NativeRegExp.MATCH)); - } - - return result; - } - - - - public int find_split(Context cx, Scriptable scope, String target, - String separator, Scriptable reObj, - int[] ip, int[] matchlen, - boolean[] matched, String[][] parensp) - { - int i = ip[0]; - int length = target.length(); - int result; - - int version = cx.getLanguageVersion(); - NativeRegExp re = (NativeRegExp) reObj; - again: - while (true) { // imitating C label - /* JS1.2 deviated from Perl by never matching at end of string. */ - int ipsave = ip[0]; // reuse ip to save object creation - ip[0] = i; - Object ret = re.executeRegExp(cx, scope, this, target, ip, - NativeRegExp.TEST); - if (ret != Boolean.TRUE) { - // Mismatch: ensure our caller advances i past end of string. - ip[0] = ipsave; - matchlen[0] = 1; - matched[0] = false; - return length; - } - i = ip[0]; - ip[0] = ipsave; - matched[0] = true; - - SubString sep = this.lastMatch; - matchlen[0] = sep.length; - if (matchlen[0] == 0) { - /* - * Empty string match: never split on an empty - * match at the start of a find_split cycle. Same - * rule as for an empty global match in - * match_or_replace. - */ - if (i == ip[0]) { - /* - * "Bump-along" to avoid sticking at an empty - * match, but don't bump past end of string -- - * our caller must do that by adding - * sep->length to our return value. - */ - if (i == length) { - if (version == Context.VERSION_1_2) { - matchlen[0] = 1; - result = i; - } - else - result = -1; - break; - } - i++; - continue again; // imitating C goto - } - } - // PR_ASSERT((size_t)i >= sep->length); - result = i - matchlen[0]; - break; - } - int size = (parens == null) ? 0 : parens.length; - parensp[0] = new String[size]; - for (int num = 0; num < size; num++) { - SubString parsub = getParenSubString(num); - parensp[0][num] = parsub.toString(); - } - return result; - } - - /** - * Analog of REGEXP_PAREN_SUBSTRING in C jsregexp.h. - * Assumes zero-based; i.e., for $3, i==2 - */ - SubString getParenSubString(int i) - { - if (parens != null && i < parens.length) { - SubString parsub = parens[i]; - if (parsub != null) { - return parsub; - } - } - return SubString.emptySubString; - } - - /* - * Analog of match_glob() in jsstr.c - */ - private static void match_glob(GlobData mdata, Context cx, - Scriptable scope, int count, - RegExpImpl reImpl) - { - if (mdata.arrayobj == null) { - Scriptable s = ScriptableObject.getTopLevelScope(scope); - mdata.arrayobj = ScriptRuntime.newObject(cx, s, "Array", null); - } - SubString matchsub = reImpl.lastMatch; - String matchstr = matchsub.toString(); - mdata.arrayobj.put(count, mdata.arrayobj, matchstr); - } - - /* - * Analog of replace_glob() in jsstr.c - */ - private static void replace_glob(GlobData rdata, Context cx, - Scriptable scope, RegExpImpl reImpl, - int leftIndex, int leftlen) - { - int replen; - String lambdaStr; - if (rdata.lambda != null) { - // invoke lambda function with args lastMatch, $1, $2, ... $n, - // leftContext.length, whole string. - SubString[] parens = reImpl.parens; - int parenCount = (parens == null) ? 0 : parens.length; - Object[] args = new Object[parenCount + 3]; - args[0] = reImpl.lastMatch.toString(); - for (int i=0; i < parenCount; i++) { - SubString sub = parens[i]; - if (sub != null) { - args[i+1] = sub.toString(); - } else { - args[i+1] = Undefined.instance; - } - } - args[parenCount+1] = new Integer(reImpl.leftContext.length); - args[parenCount+2] = rdata.str; - // This is a hack to prevent expose of reImpl data to - // JS function which can run new regexps modifing - // regexp that are used later by the engine. - // TODO: redesign is necessary - if (reImpl != ScriptRuntime.getRegExpProxy(cx)) Kit.codeBug(); - RegExpImpl re2 = new RegExpImpl(); - re2.multiline = reImpl.multiline; - re2.input = reImpl.input; - ScriptRuntime.setRegExpProxy(cx, re2); - try { - Scriptable parent = ScriptableObject.getTopLevelScope(scope); - Object result = rdata.lambda.call(cx, parent, parent, args); - lambdaStr = ScriptRuntime.toString(result); - } finally { - ScriptRuntime.setRegExpProxy(cx, reImpl); - } - replen = lambdaStr.length(); - } else { - lambdaStr = null; - replen = rdata.repstr.length(); - if (rdata.dollar >= 0) { - int[] skip = new int[1]; - int dp = rdata.dollar; - do { - SubString sub = interpretDollar(cx, reImpl, rdata.repstr, - dp, skip); - if (sub != null) { - replen += sub.length - skip[0]; - dp += skip[0]; - } else { - ++dp; - } - dp = rdata.repstr.indexOf('$', dp); - } while (dp >= 0); - } - } - - int growth = leftlen + replen + reImpl.rightContext.length; - StringBuffer charBuf = rdata.charBuf; - if (charBuf == null) { - charBuf = new StringBuffer(growth); - rdata.charBuf = charBuf; - } else { - charBuf.ensureCapacity(rdata.charBuf.length() + growth); - } - - charBuf.append(reImpl.leftContext.charArray, leftIndex, leftlen); - if (rdata.lambda != null) { - charBuf.append(lambdaStr); - } else { - do_replace(rdata, cx, reImpl); - } - } - - private static SubString interpretDollar(Context cx, RegExpImpl res, - String da, int dp, int[] skip) - { - char dc; - int num, tmp; - - if (da.charAt(dp) != '$') Kit.codeBug(); - - /* Allow a real backslash (literal "\\") to escape "$1" etc. */ - int version = cx.getLanguageVersion(); - if (version != Context.VERSION_DEFAULT - && version <= Context.VERSION_1_4) - { - if (dp > 0 && da.charAt(dp - 1) == '\\') - return null; - } - int daL = da.length(); - if (dp + 1 >= daL) - return null; - /* Interpret all Perl match-induced dollar variables. */ - dc = da.charAt(dp + 1); - if (NativeRegExp.isDigit(dc)) { - int cp; - if (version != Context.VERSION_DEFAULT - && version <= Context.VERSION_1_4) - { - if (dc == '0') - return null; - /* Check for overflow to avoid gobbling arbitrary decimal digits. */ - num = 0; - cp = dp; - while (++cp < daL && NativeRegExp.isDigit(dc = da.charAt(cp))) - { - tmp = 10 * num + (dc - '0'); - if (tmp < num) - break; - num = tmp; - } - } - else { /* ECMA 3, 1-9 or 01-99 */ - int parenCount = (res.parens == null) ? 0 : res.parens.length; - num = dc - '0'; - if (num > parenCount) - return null; - cp = dp + 2; - if ((dp + 2) < daL) { - dc = da.charAt(dp + 2); - if (NativeRegExp.isDigit(dc)) { - tmp = 10 * num + (dc - '0'); - if (tmp <= parenCount) { - cp++; - num = tmp; - } - } - } - if (num == 0) return null; /* $0 or $00 is not valid */ - } - /* Adjust num from 1 $n-origin to 0 array-index-origin. */ - num--; - skip[0] = cp - dp; - return res.getParenSubString(num); - } - - skip[0] = 2; - switch (dc) { - case '$': - return new SubString("$"); - case '&': - return res.lastMatch; - case '+': - return res.lastParen; - case '`': - if (version == Context.VERSION_1_2) { - /* - * JS1.2 imitated the Perl4 bug where left context at each step - * in an iterative use of a global regexp started from last match, - * not from the start of the target string. But Perl4 does start - * $` at the beginning of the target string when it is used in a - * substitution, so we emulate that special case here. - */ - res.leftContext.index = 0; - res.leftContext.length = res.lastMatch.index; - } - return res.leftContext; - case '\'': - return res.rightContext; - } - return null; - } - - /** - * Analog of do_replace in jsstr.c - */ - private static void do_replace(GlobData rdata, Context cx, - RegExpImpl regExpImpl) - { - StringBuffer charBuf = rdata.charBuf; - int cp = 0; - String da = rdata.repstr; - int dp = rdata.dollar; - if (dp != -1) { - int[] skip = new int[1]; - do { - int len = dp - cp; - charBuf.append(da.substring(cp, dp)); - cp = dp; - SubString sub = interpretDollar(cx, regExpImpl, da, - dp, skip); - if (sub != null) { - len = sub.length; - if (len > 0) { - charBuf.append(sub.charArray, sub.index, len); - } - cp += skip[0]; - dp += skip[0]; - } else { - ++dp; - } - dp = da.indexOf('$', dp); - } while (dp >= 0); - } - int daL = da.length(); - if (daL > cp) { - charBuf.append(da.substring(cp, daL)); - } - } - - String input; /* input string to match (perl $_, GC root) */ - boolean multiline; /* whether input contains newlines (perl $*) */ - SubString[] parens; /* Vector of SubString; last set of parens - matched (perl $1, $2) */ - SubString lastMatch; /* last string matched (perl $&) */ - SubString lastParen; /* last paren matched (perl $+) */ - SubString leftContext; /* input to left of last match (perl $`) */ - SubString rightContext; /* input to right of last match (perl $') */ -} - - -final class GlobData -{ - int mode; /* input: return index, match object, or void */ - int optarg; /* input: index of optional flags argument */ - boolean global; /* output: whether regexp was global */ - String str; /* output: 'this' parameter object as string */ - NativeRegExp regexp;/* output: regexp parameter object private data */ - - // match-specific data - - Scriptable arrayobj; - - // replace-specific data - - Function lambda; /* replacement function object or null */ - String repstr; /* replacement string */ - int dollar = -1; /* -1 or index of first $ in repstr */ - StringBuffer charBuf; /* result characters, null initially */ - int leftIndex; /* leftContext index, always 0 for JS1.2 */ -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/SubString.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/SubString.java deleted file mode 100644 index 00905ca..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/regexp/SubString.java +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.regexp; - -class SubString { - - public SubString() - { - } - - public SubString(String str) - { - index = 0; - charArray = str.toCharArray(); - length = str.length(); - } - - public SubString(char[] source, int start, int len) - { - // there must be a better way of doing this?? - index = 0; - length = len; - charArray = new char[len]; - for (int j = 0; j < len; j++) - charArray[j] = source[start + j]; - } - - public String toString() { - return charArray == null - ? "" - : new String(charArray, index, length); - } - - static final SubString emptySubString = new SubString(); - - char[] charArray; - int index; - int length; -} - diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/resources/Messages.properties b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/resources/Messages.properties deleted file mode 100644 index fd869c1..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/resources/Messages.properties +++ /dev/null @@ -1,778 +0,0 @@ -# -# Default JavaScript messages file. -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Rhino code, released -# May 6, 1999. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1997-1999 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Norris Boyd -# Bob Jervis -# -# Alternatively, the contents of this file may be used under the terms of -# the GNU General Public License Version 2 or later (the "GPL"), in which -# case the provisions of the GPL are applicable instead of those above. If -# you wish to allow use of your version of this file only under the terms of -# the GPL and not to allow others to use your version of this file under the -# MPL, indicate your decision by deleting the provisions above and replacing -# them with the notice and other provisions required by the GPL. If you do -# not delete the provisions above, a recipient may use your version of this -# file under either the MPL or the GPL. -# -# ***** END LICENSE BLOCK ***** - -# This is replaced during jar assembly from property string -# and should not be translated -implementation.version = @IMPLEMENTATION.VERSION@ - -# -# To add JavaScript error messages for a particular locale, create a -# new Messages_[locale].properties file, where [locale] is the Java -# string abbreviation for that locale. For example, JavaScript -# messages for the Polish locale should be located in -# Messages_pl.properties, and messages for the Italian Swiss locale -# should be located in Messages_it_CH.properties. Message properties -# files should be accessible through the classpath under -# org.mozilla.javascript.resources -# -# See: -# java.util.ResourceBundle -# java.text.MessageFormat -# - -# SomeJavaClassWhereUsed - -# Codegen -msg.dup.parms =\ - Duplicate parameter name "{0}". - -msg.too.big.jump =\ - Program too complex: too big jump offset. - -msg.too.big.index =\ - Program too complex: internal index exceeds 64K limit. - -msg.while.compiling.fn =\ - Encountered code generation error while compiling function "{0}": {1} - -msg.while.compiling.script =\ - Encountered code generation error while compiling script: {0} - -# Context -msg.ctor.not.found =\ - Constructor for "{0}" not found. - -msg.not.ctor =\ - "{0}" is not a constructor. - -# FunctionObject -msg.varargs.ctor =\ - Method or constructor "{0}" must be static with the signature \ - "(Context cx, Object[] args, Function ctorObj, boolean inNewExpr)" \ - to define a variable arguments constructor. - -msg.varargs.fun =\ - Method "{0}" must be static with the signature \ - "(Context cx, Scriptable thisObj, Object[] args, Function funObj)" \ - to define a variable arguments function. - -msg.incompat.call =\ - Method "{0}" called on incompatible object. - -msg.bad.parms =\ - Unsupported parameter type "{0}" in method "{1}". - -msg.bad.method.return =\ - Unsupported return type "{0}" in method "{1}". - -msg.bad.ctor.return =\ - Construction of objects of type "{0}" is not supported. - -msg.no.overload =\ - Method "{0}" occurs multiple times in class "{1}". - -msg.method.not.found =\ - Method "{0}" not found in "{1}". - -# IRFactory - -msg.bad.for.in.lhs =\ - Invalid left-hand side of for..in loop. - -msg.mult.index =\ - Only one variable allowed in for..in loop. - -msg.bad.for.in.destruct =\ - Left hand side of for..in loop must be an array of length 2 to accept \ - key/value pair. - -msg.cant.convert =\ - Can''t convert to type "{0}". - -msg.bad.assign.left =\ - Invalid assignment left-hand side. - -msg.bad.decr =\ - Invalid decerement operand. - -msg.bad.incr =\ - Invalid increment operand. - -msg.bad.yield =\ - yield must be in a function. - -msg.yield.parenthesized =\ - yield expression must be parenthesized. - -# NativeGlobal -msg.cant.call.indirect =\ - Function "{0}" must be called directly, and not by way of a \ - function of another name. - -msg.eval.nonstring =\ - Calling eval() with anything other than a primitive string value will \ - simply return the value. Is this what you intended? - -msg.eval.nonstring.strict =\ - Calling eval() with anything other than a primitive string value is not \ - allowed in strict mode. - -msg.bad.destruct.op =\ - Invalid destructuring assignment operator - -# NativeCall -msg.only.from.new =\ - "{0}" may only be invoked from a "new" expression. - -msg.deprec.ctor =\ - The "{0}" constructor is deprecated. - -# NativeFunction -msg.no.function.ref.found =\ - no source found to decompile function reference {0} - -msg.arg.isnt.array =\ - second argument to Function.prototype.apply must be an array - -# NativeGlobal -msg.bad.esc.mask =\ - invalid string escape mask - -# NativeJavaClass -msg.cant.instantiate =\ - error instantiating ({0}): class {1} is interface or abstract - -msg.bad.ctor.sig =\ - Found constructor with wrong signature: \ - {0} calling {1} with signature {2} - -msg.not.java.obj =\ - Expected argument to getClass() to be a Java object. - -msg.no.java.ctor =\ - Java constructor for "{0}" with arguments "{1}" not found. - -# NativeJavaMethod -msg.method.ambiguous =\ - The choice of Java method {0}.{1} matching JavaScript argument types ({2}) is ambiguous; \ - candidate methods are: {3} - -msg.constructor.ambiguous =\ - The choice of Java constructor {0} matching JavaScript argument types ({1}) is ambiguous; \ - candidate constructors are: {2} - -# NativeJavaObject -msg.conversion.not.allowed =\ - Cannot convert {0} to {1} - -msg.no.empty.interface.conversion =\ - Cannot convert {0} to interface {1} with no methods - -msg.no.function.interface.conversion =\ - Cannot convert function {0} to interface since it contains methods with \ - different signatures - -# NativeJavaPackage -msg.not.classloader =\ - Constructor for "Packages" expects argument of type java.lang.Classloader - -# NativeRegExp -msg.bad.quant =\ - Invalid quantifier {0} - -msg.overlarge.backref =\ - Overly large back reference {0} - -msg.overlarge.min =\ - Overly large minimum {0} - -msg.overlarge.max =\ - Overly large maximum {0} - -msg.zero.quant =\ - Zero quantifier {0} - -msg.max.lt.min =\ - Maximum {0} less than minimum - -msg.unterm.quant =\ - Unterminated quantifier {0} - -msg.unterm.paren =\ - Unterminated parenthetical {0} - -msg.unterm.class =\ - Unterminated character class {0} - -msg.bad.range =\ - Invalid range in character class. - -msg.trail.backslash =\ - Trailing \\ in regular expression. - -msg.re.unmatched.right.paren =\ - unmatched ) in regular expression. - -msg.no.regexp =\ - Regular expressions are not available. - -msg.bad.backref =\ - back-reference exceeds number of capturing parentheses. - -msg.bad.regexp.compile =\ - Only one argument may be specified if the first argument to \ - RegExp.prototype.compile is a RegExp object. - -# Parser -msg.got.syntax.errors = \ - Compilation produced {0} syntax errors. - -msg.var.redecl =\ - TypeError: redeclaration of var {0}. - -msg.const.redecl =\ - TypeError: redeclaration of const {0}. - -msg.let.redecl =\ - TypeError: redeclaration of variable {0}. - -msg.parm.redecl =\ - TypeError: redeclaration of formal parameter {0}. - -msg.fn.redecl =\ - TypeError: redeclaration of function {0}. - -# NodeTransformer -msg.dup.label =\ - duplicated label - -msg.undef.label =\ - undefined label - -msg.bad.break =\ - unlabelled break must be inside loop or switch - -msg.continue.outside =\ - continue must be inside loop - -msg.continue.nonloop =\ - continue can only use labeles of iteration statements - -msg.bad.throw.eol =\ - Line terminator is not allowed between the throw keyword and throw \ - expression. - -msg.no.paren.parms =\ - missing ( before function parameters. - -msg.no.parm =\ - missing formal parameter - -msg.no.paren.after.parms =\ - missing ) after formal parameters - -msg.no.brace.body =\ - missing '{' before function body - -msg.no.brace.after.body =\ - missing } after function body - -msg.no.paren.cond =\ - missing ( before condition - -msg.no.paren.after.cond =\ - missing ) after condition - -msg.no.semi.stmt =\ - missing ; before statement - -msg.no.name.after.dot =\ - missing name after . operator - -msg.no.name.after.coloncolon =\ - missing name after :: operator - -msg.no.name.after.dotdot =\ - missing name after .. operator - -msg.no.name.after.xmlAttr =\ - missing name after .@ - -msg.no.bracket.index =\ - missing ] in index expression - -msg.no.paren.switch =\ - missing ( before switch expression - -msg.no.paren.after.switch =\ - missing ) after switch expression - -msg.no.brace.switch =\ - missing '{' before switch body - -msg.bad.switch =\ - invalid switch statement - -msg.no.colon.case =\ - missing : after case expression - -msg.double.switch.default =\ - double default label in the switch statement - -msg.no.while.do =\ - missing while after do-loop body - -msg.no.paren.for =\ - missing ( after for - -msg.no.semi.for =\ - missing ; after for-loop initializer - -msg.no.semi.for.cond =\ - missing ; after for-loop condition - -msg.in.after.for.name =\ - missing in after for - -msg.no.paren.for.ctrl =\ - missing ) after for-loop control - -msg.no.paren.with =\ - missing ( before with-statement object - -msg.no.paren.after.with =\ - missing ) after with-statement object - -msg.no.paren.after.let =\ - missing ( after let - -msg.no.paren.let =\ - missing ) after variable list - -msg.no.curly.let =\ - missing } after let statement - -msg.bad.return =\ - invalid return - -msg.no.brace.block =\ - missing } in compound statement - -msg.bad.label =\ - invalid label - -msg.bad.var =\ - missing variable name - -msg.bad.var.init =\ - invalid variable initialization - -msg.no.colon.cond =\ - missing : in conditional expression - -msg.no.paren.arg =\ - missing ) after argument list - -msg.no.bracket.arg =\ - missing ] after element list - -msg.bad.prop =\ - invalid property id - -msg.no.colon.prop =\ - missing : after property id - -msg.no.brace.prop =\ - missing } after property list - -msg.no.paren =\ - missing ) in parenthetical - -msg.reserved.id =\ - identifier is a reserved word - -msg.no.paren.catch =\ - missing ( before catch-block condition - -msg.bad.catchcond =\ - invalid catch block condition - -msg.catch.unreachable =\ - any catch clauses following an unqualified catch are unreachable - -msg.no.brace.try =\ - missing '{' before try block - -msg.no.brace.catchblock =\ - missing '{' before catch-block body - -msg.try.no.catchfinally =\ - ''try'' without ''catch'' or ''finally'' - -msg.no.return.value =\ - function {0} does not always return a value - -msg.anon.no.return.value =\ - anonymous function does not always return a value - -msg.return.inconsistent =\ - return statement is inconsistent with previous usage - -msg.generator.returns =\ - TypeError: generator function {0} returns a value - -msg.anon.generator.returns =\ - TypeError: anonymous generator function returns a value - -msg.syntax =\ - syntax error - -msg.unexpected.eof =\ - Unexpected end of file - -msg.XML.bad.form =\ - illegally formed XML syntax - -msg.XML.not.available =\ - XML runtime not available - -msg.too.deep.parser.recursion =\ - Too deep recursion while parsing - -msg.no.side.effects =\ - Code has no side effects - -msg.extra.trailing.comma =\ - Trailing comma is not legal in an ECMA-262 object initializer - -msg.equal.as.assign =\ - Test for equality (==) mistyped as assignment (=)? - -msg.var.hides.arg =\ - Variable {0} hides argument - -msg.destruct.assign.no.init =\ - Missing = in destructuring declaration - -# ScriptRuntime -msg.no.properties =\ - {0} has no properties. - -msg.invalid.iterator =\ - Invalid iterator value - -msg.iterator.primitive =\ - __iterator__ returned a primitive value - -msg.assn.create.strict =\ - Assignment to undeclared variable {0} - -msg.ref.undefined.prop =\ - Reference to undefined property "{0}" - -msg.prop.not.found =\ - Property {0} not found. - -msg.invalid.type =\ - Invalid JavaScript value of type {0} - -msg.primitive.expected =\ - Primitive type expected (had {0} instead) - -msg.namespace.expected =\ - Namespace object expected to left of :: (found {0} instead) - -msg.null.to.object =\ - Cannot convert null to an object. - -msg.undef.to.object =\ - Cannot convert undefined to an object. - -msg.cyclic.value =\ - Cyclic {0} value not allowed. - -msg.is.not.defined =\ - "{0}" is not defined. - -msg.undef.prop.read =\ - Cannot read property "{1}" from {0} - -msg.undef.prop.write =\ - Cannot set property "{1}" of {0} to "{2}" - -msg.undef.prop.delete =\ - Cannot delete property "{1}" of {0} - -msg.undef.method.call =\ - Cannot call method "{1}" of {0} - -msg.undef.with =\ - Cannot apply "with" to {0} - -msg.isnt.function =\ - {0} is not a function, it is {1}. - -msg.isnt.function.in =\ - Cannot call property {0} in object {1}. It is not a function, it is "{2}". - -msg.function.not.found =\ - Cannot find function {0}. - -msg.function.not.found.in =\ - Cannot find function {0} in object {1}. - -msg.isnt.xml.object =\ - {0} is not an xml object. - -msg.no.ref.to.get =\ - {0} is not a reference to read reference value. - -msg.no.ref.to.set =\ - {0} is not a reference to set reference value to {1}. - -msg.no.ref.from.function =\ - Function {0} can not be used as the left-hand side of assignment \ - or as an operand of ++ or -- operator. - -msg.bad.default.value =\ - Object''s getDefaultValue() method returned an object. - -msg.instanceof.not.object = \ - Can''t use instanceof on a non-object. - -msg.instanceof.bad.prototype = \ - ''prototype'' property of {0} is not an object. - -msg.bad.radix = \ - illegal radix {0}. - -# ScriptableObject -msg.default.value =\ - Cannot find default value for object. - -msg.zero.arg.ctor =\ - Cannot load class "{0}" which has no zero-parameter constructor. - -msg.ctor.multiple.parms =\ - Can''t define constructor or class {0} since more than one \ - constructor has multiple parameters. - -msg.extend.scriptable =\ - {0} must extend ScriptableObject in order to define property {1}. - -msg.bad.getter.parms =\ - In order to define a property, getter {0} must have zero parameters \ - or a single ScriptableObject parameter. - -msg.obj.getter.parms =\ - Expected static or delegated getter {0} to take a ScriptableObject parameter. - -msg.getter.static =\ - Getter and setter must both be static or neither be static. - -msg.setter.return =\ - Setter must have void return type: {0} - -msg.setter2.parms =\ - Two-parameter setter must take a ScriptableObject as its first parameter. - -msg.setter1.parms =\ - Expected single parameter setter for {0} - -msg.setter2.expected =\ - Expected static or delegated setter {0} to take two parameters. - -msg.setter.parms =\ - Expected either one or two parameters for setter. - -msg.setter.bad.type =\ - Unsupported parameter type "{0}" in setter "{1}". - -msg.add.sealed =\ - Cannot add a property to a sealed object: {0}. - -msg.remove.sealed =\ - Cannot remove a property from a sealed object: {0}. - -msg.modify.sealed =\ - Cannot modify a property of a sealed object: {0}. - -msg.modify.readonly =\ - Cannot modify readonly property: {0}. - -# TokenStream -msg.missing.exponent =\ - missing exponent - -msg.caught.nfe =\ - number format error - -msg.unterminated.string.lit =\ - unterminated string literal - -msg.unterminated.mstring.appjet =\ - unterminated multi-line string literal - -msg.unterminated.comment =\ - unterminated comment - -msg.unterminated.re.lit =\ - unterminated regular expression literal - -msg.invalid.re.flag =\ - invalid flag after regular expression - -msg.no.re.input.for =\ - no input for {0} - -msg.illegal.character =\ - illegal character - -msg.illegal.character.appjet =\ - illegal character: {0} - -msg.invalid.escape =\ - invalid Unicode escape sequence - -msg.bad.namespace =\ - not a valid default namespace statement. \ - Syntax is: default xml namespace = EXPRESSION; - -# TokensStream warnings -msg.bad.octal.literal =\ - illegal octal literal digit {0}; interpreting it as a decimal digit - -msg.reserved.keyword =\ - illegal usage of future reserved keyword {0}; interpreting it as ordinary identifier - -# LiveConnect errors -msg.java.internal.field.type =\ - Internal error: type conversion of {0} to assign to {1} on {2} failed. - -msg.java.conversion.implicit_method =\ - Can''t find converter method "{0}" on class {1}. - -msg.java.method.assign =\ - Java method "{0}" cannot be assigned to. - -msg.java.internal.private =\ - Internal error: attempt to access private/protected field "{0}". - -msg.java.no_such_method =\ - Can''t find method {0}. - -msg.script.is.not.constructor =\ - Script objects are not constructors. - -msg.nonjava.method =\ - Java method "{0}" was invoked with {1} as "this" value that can not be converted to Java type {2}. - -msg.java.member.not.found =\ - Java class "{0}" has no public instance field or method named "{1}". - -msg.java.array.index.out.of.bounds =\ - Array index {0} is out of bounds [0..{1}]. - -msg.java.array.member.not.found =\ - Java arrays have no public instance fields or methods named "{0}". - -msg.pkg.int =\ - Java package names may not be numbers. - -msg.access.prohibited =\ - Access to Java class "{0}" is prohibited. - -# ImporterTopLevel -msg.ambig.import =\ - Ambiguous import: "{0}" and and "{1}". - -msg.not.pkg =\ - Function importPackage must be called with a package; had "{0}" instead. - -msg.not.class =\ - Function importClass must be called with a class; had "{0}" instead. - -msg.not.class.not.pkg =\ - "{0}" is neither a class nor a package. - -msg.prop.defined =\ - Cannot import "{0}" since a property by that name is already defined. - -#JavaAdapter -msg.adapter.zero.args =\ - JavaAdapter requires at least one argument. - -msg.not.java.class.arg = \ -Argument {0} is not Java class: {1}. - -#JavaAdapter -msg.only.one.super = \ -Only one class may be extended by a JavaAdapter. Had {0} and {1}. - - -# Arrays -msg.arraylength.bad =\ - Inappropriate array length. - -# Arrays -msg.arraylength.too.big =\ - Array length {0} exceeds supported capacity limit. - -# URI -msg.bad.uri =\ - Malformed URI sequence. - -# Number -msg.bad.precision =\ - Precision {0} out of range. - -# NativeGenerator -msg.send.newborn =\ - Attempt to send value to newborn generator - -msg.already.exec.gen =\ - Already executing generator - -msg.StopIteration.invalid =\ - StopIteration may not be changed to an arbitrary object. - -# Interpreter -msg.yield.closing =\ - Yield from closing generator diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/resources/Messages_fr.properties b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/resources/Messages_fr.properties deleted file mode 100644 index fc87c97..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/resources/Messages_fr.properties +++ /dev/null @@ -1,329 +0,0 @@ -# -# French JavaScript messages file. -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Aviva Inc. code, released -# March 5, 2004. -# -# The Initial Developer of the Original Code is -# Aviva Inc. -# Portions created by the Initial Developer are Copyright (C) 2004 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Eugene Aresteanu -# -# Alternatively, the contents of this file may be used under the terms of -# the GNU General Public License Version 2 or later (the "GPL"), in which -# case the provisions of the GPL are applicable instead of those above. If -# you wish to allow use of your version of this file only under the terms of -# the GPL and not to allow others to use your version of this file under the -# MPL, indicate your decision by deleting the provisions above and replacing -# them with the notice and other provisions required by the GPL. If you do -# not delete the provisions above, a recipient may use your version of this -# file under either the MPL or the GPL. -# -# ***** END LICENSE BLOCK ***** - -msg.dup.parms =\ - Le nom de param\u00E8tre "{0}" existe d\u00E9j\u00E0. -msg.too.big.jump =\ - Programme trop complexe : d\u00E9calage de saut trop important -msg.too.big.index =\ - Programme trop complexe : l''indice interne d\u00E9passe la limite de 64 ko -msg.ctor.not.found =\ - Le constructeur de "{0}" est introuvable -msg.not.ctor =\ - {0} n''est pas un constructeur -msg.varargs.ctor =\ - La m\u00E9thode ou le constructeur "{0}" doit \u00EAtre statique avec la signature "(Context cx, arguments Object[], Function ctorObj, boolean inNewExpr)" pour d\u00E9finir un constructeur d''arguments de variable. -msg.varargs.fun =\ - La m\u00E9thode "{0}" doit \u00EAtre statique avec la signature "(Context cx, Scriptable thisObj, arguments Object[], Function funObj)" pour d\u00E9finir une fonction d''arguments de variable -msg.incompat.call =\ - La m\u00E9thode "{0}" a \u00E9t\u00E9 appel\u00E9e dans un objet non compatible -msg.bad.parms =\ - Les param\u00E8tres de la m\u00E9thode sont incorrects pour "{0}" -msg.no.overload =\ - La m\u00E9thode "{0}" appara\u00EEt plusieurs fois dans la classe "{1}" -msg.method.not.found =\ - La m\u00E9thode "{0}" est introuvable dans "{1}" -msg.bad.for.in.lhs =\ - La partie gauche de la boucle for..in est incorrecte -msg.bad.lhs.assign =\ - La partie gauche de l''affectation est incorrecte -msg.mult.index =\ - Une seule variable est autoris\u00E9e dans la boucle for..in -msg.cant.convert =\ - La conversion en type "{0}" est impossible -msg.cant.call.indirect =\ - La fonction "{0}" doit \u00EAtre appel\u00E9e directement et non par l''interm\u00E9diaire d''une fonction portant un autre nom -msg.eval.nonstring =\ - Si vous appelez la fonction eval() avec une valeur qui n''appartient pas \u00E0 une cha\u00EEne primitive, c''est la valeur en question qui est renvoy\u00E9e. \u00E9tait-ce votre intention ? -msg.only.from.new =\ - {0} ne peut \u00EAtre appel\u00E9e qu''\u00E0 partir d''une "nouvelle" expression. -msg.deprec.ctor =\ - Le constructeur "{0}" est d\u00E9conseill\u00E9 -msg.no.function.ref.found =\ - aucune source n''a \u00E9t\u00E9 trouv\u00E9e pour d\u00E9compiler la r\u00E9f\u00E9rence de fonction {0} -msg.arg.isnt.array =\ - le second argument de la m\u00E9thode Function.prototype.apply doit \u00EAtre un tableau -msg.bad.esc.mask =\ - le masque d''\u00E9chappement de cha\u00EEne est incorrect -msg.cant.instantiate =\ - erreur lors de l''instanciation ({0}) : la classe {1} est une classe interface ou abstract -msg.bad.ctor.sig =\ - Un constructeur avec une signature incorrecte a \u00E9t\u00E9 d\u00E9tect\u00E9 : {0} qui appelle {1} avec la signature {2} -msg.not.java.obj =\ - L''argument attendu pour la fonction getClass() doit \u00EAtre un objet Java -msg.no.java.ctor =\ - Le constructeur Java de "{0}" avec les arguments "{1}" est introuvable -msg.method.ambiguous =\ - Le choix de la m\u00E9thode Java {0}.{1} correspondant aux types d''argument JavaScript ({2}) est ambigu. Les m\u00E9thodes propos\u00E9es sont les suivantes : {3} -msg.constructor.ambiguous =\ - Le choix du constructeur Java {0} correspondant aux types d''argument JavaScript ({1}) est ambigu. Les constructeurs propos\u00E9s sont les suivants : {2} -msg.conversion.not.allowed =\ - Impossible de convertir {0} en {1} -msg.not.classloader =\ - Le constructeur de "Packages" attend un argument de type java.lang.Classloader -msg.bad.quant =\ - Le quantificateur {0} est incorrect -msg.overlarge.max =\ - Le maximum {0} est trop important -msg.zero.quant =\ - Le quantificateur {0} est nul -msg.max.lt.min =\ - Le maximum {0} est inf\u00E9rieur au minimum -msg.unterm.quant =\ - Le quantificateur {0} n''a pas de limite -msg.unterm.paren =\ - Les parenth\u00E8ses {0} n''ont pas de limite -msg.unterm.class =\ - La classe de caract\u00E8res {0} n''a pas de limite -msg.bad.range =\ - La classe de caract\u00E8res contient une plage de valeurs incorrecte -msg.trail.backslash =\ - \\ au d\u00E9but d''une expression r\u00E9guli\u00E8re -msg.no.regexp =\ - Les expressions r\u00E9guli\u00E8res ne sont pas disponibles -msg.bad.backref =\ - la r\u00E9f\u00E9rence ant\u00E9rieure d\u00E9passe le nombre de parenth\u00E8ses de capture -msg.dup.label =\ - Le libell\u00E9 {0} existe d\u00E9j\u00E0 -msg.undef.label =\ - Le libell\u00E9 {0} n''est pas d\u00E9fini -msg.bad.break =\ - Le saut non libell\u00E9 doit se trouver dans la boucle ou dans l''aiguillage -msg.continue.outside =\ - continue doit se trouver dans la boucle -msg.continue.nonloop =\ - Il n''est possible de continuer que dans l''instruction d''it\u00E9ration libell\u00E9e -msg.fn.redecl =\ - La fonction "{0}" a \u00E9t\u00E9 de nouveau d\u00E9clar\u00E9e. La d\u00E9finition pr\u00E9c\u00E9dente sera ignor\u00E9e -msg.no.paren.parms =\ - il manque ''('' avant les param\u00E8tres de la fonction -msg.no.parm =\ - il manque un param\u00E8tre de forme -msg.no.paren.after.parms =\ - il manque '')'' apr\u00E8s les param\u00E8tres de forme -msg.no.brace.body =\ - il manque '{' avant le corps d''une fonction -msg.no.brace.after.body =\ - il manque ''}'' apr\u00E8s le corps d''une fonction -msg.no.paren.cond =\ - il manque ''('' avant une condition -msg.no.paren.after.cond =\ - il manque '')'' apr\u00E8s une condition -msg.no.semi.stmt =\ - il manque '';'' avant une instruction -msg.no.name.after.dot =\ - il manque un nom apr\u00E8s un op\u00E9rateur ''.'' -msg.no.bracket.index =\ - il manque '']'' dans l''expression de l''indice -msg.no.paren.switch =\ - il manque ''('' avant l''expression d''un aiguillage -msg.no.paren.after.switch =\ - il manque '')'' apr\u00E8s l''expression d''un aiguillage -msg.no.brace.switch =\ - il manque '{' avant le corps d''un aiguillage -msg.bad.switch =\ - l''instruction d''aiguillage est incorrecte -msg.no.colon.case =\ - il manque '':'' apr\u00E8s l''expression d''un cas -msg.no.while.do =\ - il manque ''while'' apr\u00E8s le corps d''une boucle do-loop -msg.no.paren.for =\ - il manque ''('' apr\u00E8s for -msg.no.semi.for =\ - Il manque '';'' apr\u00E8s l''initialiseur for-loop -msg.no.semi.for.cond =\ - il manque '';'' apr\u00E8s la condition for-loop -msg.no.paren.for.ctrl =\ - il manque '')'' apr\u00E8s le contrôle for-loop -msg.no.paren.with =\ - il manque ''('' avant un objet with-statement -msg.no.paren.after.with =\ - il manque '')'' apr\u00E8s un objet with-statement -msg.bad.return =\ - la valeur renvoy\u00E9e est incorrecte -msg.no.brace.block =\ - il manque ''}'' dans une instruction compos\u00E9e -msg.bad.label =\ - le libell\u00E9 est incorrect -msg.bad.var =\ - il manque un nom de variable -msg.bad.var.init =\ - l''initialisation de la variable est incorrecte -msg.no.colon.cond =\ - il manque '':'' dans une expression conditionnelle -msg.no.paren.arg =\ - il manque '')'' apr\u00E8s une liste d''arguments -msg.no.bracket.arg =\ - il manque '']'' apr\u00E8s une liste d''\u00E9l\u00E9ments -msg.bad.prop =\ - l''identifiant de propri\u00E9t\u00E9 est incorrect -msg.no.colon.prop =\ - il manque '':'' apr\u00E8s un identifiant de propri\u00E9t\u00E9 -msg.no.brace.prop =\ - il manque ''}'' apr\u00E8s une liste de propri\u00E9t\u00E9s -msg.no.paren =\ - il manque '')'' dans des parenth\u00E8ses -msg.reserved.id =\ - l''identifiant est un mot r\u00E9serv\u00E9 -msg.no.paren.catch =\ - il manque ''('' avant une condition catch-block -msg.bad.catchcond =\ - la condition catch-block est incorrecte -msg.catch.unreachable =\ - aucune clause catch suivant une interception non qualifi\u00E9e ne peut \u00EAtre atteinte -msg.no.brace.catchblock =\ - il manque '{' avant le corps catch-block -msg.try.no.catchfinally =\ - ''try'' a \u00E9t\u00E9 d\u00E9tect\u00E9 sans ''catch'' ni ''finally'' -msg.syntax =\ - erreur de syntaxe -msg.assn.create =\ - Une variable va \u00EAtre cr\u00E9\u00E9e en raison de l''affectation \u00E0 un ''{0}'' non d\u00E9fini. Ajoutez une instruction de variable \u00E0 la port\u00E9e sup\u00E9rieure pour que cet avertissement ne soit plus affich\u00E9 -msg.prop.not.found =\ - La propri\u00E9t\u00E9 est introuvable -msg.invalid.type =\ - Valeur JavaScript de type {0} incorrecte -msg.primitive.expected =\ - Un type primitif \u00E9tait attendu (et non {0}) -msg.null.to.object =\ - Il est impossible de convertir la valeur null en objet -msg.undef.to.object =\ - Il est impossible de convertir une valeur non d\u00E9finie en objet -msg.cyclic.value =\ - La valeur cyclique {0} n''est pas autoris\u00E9e -msg.is.not.defined =\ - "{0}" n''est pas d\u00E9fini -msg.isnt.function =\ - {0} n''est pas une fonction, est un {1} -msg.bad.default.value =\ - La m\u00E9thode getDefaultValue() de l''objet a renvoy\u00E9 un objet -msg.instanceof.not.object =\ - Il est impossible d''utiliser une instance d''un \u00E9l\u00E9ment autre qu''un objet -msg.instanceof.bad.prototype =\ - La propri\u00E9t\u00E9 ''prototype'' de {0} n''est pas un objet -msg.bad.radix =\ - la base {0} n''est pas autoris\u00E9e -msg.default.value =\ - La valeur par d\u00E9faut de l''objet est introuvable -msg.zero.arg.ctor =\ - Il est impossible de charger la classe "{0}", qui ne poss\u00E8de pas de constructeur de param\u00E8tre z\u00E9ro -msg.multiple.ctors =\ - Les m\u00E9thodes {0} et {1} ont \u00E9t\u00E9 d\u00E9tect\u00E9es alors qu''il est impossible d''utiliser plusieurs m\u00E9thodes constructor -msg.ctor.multiple.parms =\ - Il est impossible de d\u00E9finir le constructeur ou la classe {0} car plusieurs constructeurs poss\u00E8dent plusieurs param\u00E8tres -msg.extend.scriptable =\ - {0} doit \u00E9tendre ScriptableObject afin de d\u00E9finir la propri\u00E9t\u00E9 {1} -msg.bad.getter.parms =\ - Pour d\u00E9finir une propri\u00E9t\u00E9, la m\u00E9thode d''obtention {0} doit avoir des param\u00E8tres z\u00E9ro ou un seul param\u00E8tre ScriptableObject -msg.obj.getter.parms =\ - La m\u00E9thode d''obtention statique ou d\u00E9l\u00E9gu\u00E9e {0} doit utiliser un param\u00E8tre ScriptableObject -msg.getter.static =\ - La m\u00E9thode d''obtention et la m\u00E9thode de d\u00E9finition doivent toutes deux avoir le m\u00EAme \u00E9tat (statique ou non) -msg.setter2.parms =\ - La m\u00E9thode de d\u00E9finition \u00E0 deux param\u00E8tres doit utiliser un param\u00E8tre ScriptableObject comme premier param\u00E8tre -msg.setter1.parms =\ - Une m\u00E9thode d''obtention \u00E0 param\u00E8tre unique est attendue pour {0} -msg.setter2.expected =\ - La m\u00E9thode de d\u00E9finition statique ou d\u00E9l\u00E9gu\u00E9e {0} doit utiliser deux param\u00E8tres -msg.setter.parms =\ - Un ou deux param\u00E8tres sont attendus pour la m\u00E9thode de d\u00E9finition -msg.add.sealed =\ - Il est impossible d''ajouter une propri\u00E9t\u00E9 \u00E0 un objet ferm\u00E9 -msg.remove.sealed =\ - Il est impossible de supprimer une propri\u00E9t\u00E9 d''un objet ferm\u00E9 -msg.token.replaces.pushback =\ - le jeton de non-obtention {0} remplace le jeton de renvoi {1} -msg.missing.exponent =\ - il manque un exposant -msg.caught.nfe =\ - erreur de format de nombre : {0} -msg.unterminated.string.lit =\ - le litt\u00E9ral de la cha\u00EEne n''a pas de limite -msg.unterminated.comment =\ - le commentaire n''a pas de limite -msg.unterminated.re.lit =\ - le litt\u00E9ral de l''expression r\u00E9guli\u00E8re n''a pas de limite -msg.invalid.re.flag =\ - une expression r\u00E9guli\u00E8re est suivie d''un indicateur incorrect -msg.no.re.input.for =\ - il n''y a pas d''entr\u00E9e pour {0} -msg.illegal.character =\ - caract\u00E8re non autoris\u00E9 -msg.invalid.escape =\ - la s\u00E9quence d''\u00E9chappement Unicode est incorrecte -msg.bad.octal.literal =\ - le chiffre octal du litt\u00E9ral, {0}, n''est pas autoris\u00E9 et sera interpr\u00E9t\u00E9 comme un chiffre d\u00E9cimal -msg.reserved.keyword =\ - l''utilisation du futur mot-cl\u00E9 r\u00E9serv\u00E9 {0} n''est pas autoris\u00E9e et celui-ci sera interpr\u00E9t\u00E9 comme un identifiant ordinaire -msg.undefined =\ - La valeur non d\u00E9finie ne poss\u00E8de pas de propri\u00E9t\u00E9 -msg.java.internal.field.type =\ - Erreur interne : la conversion de type de {0} afin d''affecter {1} \u00E0 {2} a \u00E9chou\u00E9 -msg.java.conversion.implicit_method =\ - La m\u00E9thode de conversion "{0}" est introuvable dans la classe {1} -sg.java.method.assign =\ - La m\u00E9thode Java "{0}" ne peut pas \u00EAtre affect\u00E9e \u00E0 -msg.java.internal.private =\ - Erreur interne : une tentative d''acc\u00E9der \u00E0 un champ "{0}" priv\u00E9/prot\u00E9g\u00E9 a \u00E9t\u00E9 d\u00E9tect\u00E9e -msg.java.no_such_method =\ - La m\u00E9thode ''{0}'' est introuvable -msg.script.is.not.constructor =\ - Les objets Script ne sont pas des constructeurs -msg.nonjava.method =\ - La m\u00E9thode Java "{0}" a \u00E9t\u00E9 appel\u00E9e avec une valeur ''this'' qui n''est pas un objet Java -msg.java.member.not.found =\ - La classe Java "{0}" ne poss\u00E8de aucun champ ou aucune m\u00E9thode d''instance publique appel\u00E9 "{1}" -msg.java.array.index.out.of.bounds =\ - Array index {0} is out of bounds [0..{1}]. -msg.pkg.int =\ - Les noms de package Java ne peuvent pas \u00EAtre des nombres -msg.ambig.import =\ - Importation ambigu\u00EB : "{0}" et "{1}" -msg.not.pkg =\ - La fonction importPackage doit \u00EAtre appel\u00E9e avec un package et non avec "{0}" -msg.not.class =\ - La fonction importClass doit \u00EAtre appel\u00E9e avec une classe et non avec "{0}" -msg.prop.defined =\ - Il est impossible d''importer "{0}" car une propri\u00E9t\u00E9 portant le m\u00EAme nom a d\u00E9j\u00E0 \u00E9t\u00E9 d\u00E9finie -sg.arraylength.bad =\ - La longueur du tableau n''est pas appropri\u00E9e -msg.bad.uri =\ - La s\u00E9quence URI n''est pas form\u00E9e correctement -msg.bad.precision =\ - La pr\u00E9cision {0} ne se trouve pas dans la plage de valeurs diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/serialize/ScriptableInputStream.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/serialize/ScriptableInputStream.java deleted file mode 100644 index 476ff69..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/serialize/ScriptableInputStream.java +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino serialization code, released - * Sept. 25, 2001. - * - * The Initial Developer of the Original Code is - * Norris Boyd. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Igor Bukanov - * Attila Szegedi - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -// API class - -package org.mozilla.javascript.serialize; - -import java.io.*; - -import org.mozilla.javascript.*; - -/** - * Class ScriptableInputStream is used to read in a JavaScript - * object or function previously serialized with a ScriptableOutputStream. - * References to names in the exclusion list - * replaced with references to the top-level scope specified during - * creation of the ScriptableInputStream. - * - * @author Norris Boyd - */ - -public class ScriptableInputStream extends ObjectInputStream { - - /** - * Create a ScriptableInputStream. - * @param in the InputStream to read from. - * @param scope the top-level scope to create the object in. - */ - public ScriptableInputStream(InputStream in, Scriptable scope) - throws IOException - { - super(in); - this.scope = scope; - enableResolveObject(true); - Context cx = Context.getCurrentContext(); - if (cx != null) { - this.classLoader = cx.getApplicationClassLoader(); - } - } - - protected Class resolveClass(ObjectStreamClass desc) - throws IOException, ClassNotFoundException - { - String name = desc.getName(); - if (classLoader != null) { - try { - return classLoader.loadClass(name); - } catch (ClassNotFoundException ex) { - // fall through to default loading - } - } - return super.resolveClass(desc); - } - - protected Object resolveObject(Object obj) - throws IOException - { - if (obj instanceof ScriptableOutputStream.PendingLookup) { - String name = ((ScriptableOutputStream.PendingLookup)obj).getName(); - obj = ScriptableOutputStream.lookupQualifiedName(scope, name); - if (obj == Scriptable.NOT_FOUND) { - throw new IOException("Object " + name + " not found upon " + - "deserialization."); - } - }else if (obj instanceof UniqueTag) { - obj = ((UniqueTag)obj).readResolve(); - }else if (obj instanceof Undefined) { - obj = ((Undefined)obj).readResolve(); - } - return obj; - } - - private Scriptable scope; - private ClassLoader classLoader; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/serialize/ScriptableOutputStream.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/serialize/ScriptableOutputStream.java deleted file mode 100644 index 5ba0d74..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/serialize/ScriptableOutputStream.java +++ /dev/null @@ -1,207 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino serialization code, released - * Sept. 25, 2001. - * - * The Initial Developer of the Original Code is - * Norris Boyd. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * Attila Szegedi - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.serialize; - -import java.util.Hashtable; -import java.util.StringTokenizer; -import java.io.*; - -import org.mozilla.javascript.*; - -/** - * Class ScriptableOutputStream is an ObjectOutputStream used - * to serialize JavaScript objects and functions. Note that - * compiled functions currently cannot be serialized, only - * interpreted functions. The top-level scope containing the - * object is not written out, but is instead replaced with - * another top-level object when the ScriptableInputStream - * reads in this object. Also, object corresponding to names - * added to the exclude list are not written out but instead - * are looked up during deserialization. This approach avoids - * the creation of duplicate copies of standard objects - * during deserialization. - * - * @author Norris Boyd - */ - -// API class - -public class ScriptableOutputStream extends ObjectOutputStream { - - /** - * ScriptableOutputStream constructor. - * Creates a ScriptableOutputStream for use in serializing - * JavaScript objects. Calls excludeStandardObjectNames. - * - * @param out the OutputStream to write to. - * @param scope the scope containing the object. - */ - public ScriptableOutputStream(OutputStream out, Scriptable scope) - throws IOException - { - super(out); - this.scope = scope; - table = new Hashtable(31); - table.put(scope, ""); - enableReplaceObject(true); - excludeStandardObjectNames(); - } - - /** - * Adds a qualified name to the list of object to be excluded from - * serialization. Names excluded from serialization are looked up - * in the new scope and replaced upon deserialization. - * @param name a fully qualified name (of the form "a.b.c", where - * "a" must be a property of the top-level object). The object - * need not exist, in which case the name is ignored. - * @throws IllegalArgumentException if the object is not a - * {@link Scriptable}. - */ - public void addOptionalExcludedName(String name) { - Object obj = lookupQualifiedName(scope, name); - if(obj != null && obj != UniqueTag.NOT_FOUND) { - if (!(obj instanceof Scriptable)) { - throw new IllegalArgumentException( - "Object for excluded name " + name + - " is not a Scriptable, it is " + - obj.getClass().getName()); - } - table.put(obj, name); - } - } - - /** - * Adds a qualified name to the list of object to be excluded from - * serialization. Names excluded from serialization are looked up - * in the new scope and replaced upon deserialization. - * @param name a fully qualified name (of the form "a.b.c", where - * "a" must be a property of the top-level object) - * @throws IllegalArgumentException if the object is not found or is not - * a {@link Scriptable}. - */ - public void addExcludedName(String name) { - Object obj = lookupQualifiedName(scope, name); - if (!(obj instanceof Scriptable)) { - throw new IllegalArgumentException("Object for excluded name " + - name + " not found."); - } - table.put(obj, name); - } - - /** - * Returns true if the name is excluded from serialization. - */ - public boolean hasExcludedName(String name) { - return table.get(name) != null; - } - - /** - * Removes a name from the list of names to exclude. - */ - public void removeExcludedName(String name) { - table.remove(name); - } - - /** - * Adds the names of the standard objects and their - * prototypes to the list of excluded names. - */ - public void excludeStandardObjectNames() { - String[] names = { "Object", "Object.prototype", - "Function", "Function.prototype", - "String", "String.prototype", - "Math", // no Math.prototype - "Array", "Array.prototype", - "Error", "Error.prototype", - "Number", "Number.prototype", - "Date", "Date.prototype", - "RegExp", "RegExp.prototype", - "Script", "Script.prototype", - "Continuation", "Continuation.prototype", - }; - for (int i=0; i < names.length; i++) { - addExcludedName(names[i]); - } - - String[] optionalNames = { - "XML", "XML.prototype", - "XMLList", "XMLList.prototype", - }; - for (int i=0; i < optionalNames.length; i++) { - addOptionalExcludedName(optionalNames[i]); - } - } - - static Object lookupQualifiedName(Scriptable scope, - String qualifiedName) - { - StringTokenizer st = new StringTokenizer(qualifiedName, "."); - Object result = scope; - while (st.hasMoreTokens()) { - String s = st.nextToken(); - result = ScriptableObject.getProperty((Scriptable)result, s); - if (result == null || !(result instanceof Scriptable)) - break; - } - return result; - } - - static class PendingLookup implements Serializable - { - static final long serialVersionUID = -2692990309789917727L; - - PendingLookup(String name) { this.name = name; } - - String getName() { return name; } - - private String name; - } - - protected Object replaceObject(Object obj) throws IOException - { - String name = (String) table.get(obj); - if (name == null) - return obj; - return new PendingLookup(name); - } - - private Scriptable scope; - private Hashtable table; -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/xml/XMLLib.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/xml/XMLLib.java deleted file mode 100644 index da57ddf..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/xml/XMLLib.java +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.xml; - -import org.mozilla.javascript.*; - -public abstract class XMLLib -{ - private static final Object XML_LIB_KEY = new Object(); - - /** - An object which specifies an XMLLib implementation to be used at runtime. - - This interface should be considered experimental. It may be better - (and certainly more flexible) to write an interface that returns an - XMLLib object rather than a class name, for example. But that would - cause many more ripple effects in the code, all the way back to - {@link ScriptRuntime}. - */ - public static abstract class Factory { - public static Factory create(final String className) { - return new Factory() { - public String getImplementationClassName() { - return className; - } - }; - } - - public abstract String getImplementationClassName(); - } - - public static XMLLib extractFromScopeOrNull(Scriptable scope) - { - ScriptableObject so = ScriptRuntime.getLibraryScopeOrNull(scope); - if (so == null) { - // If library is not yet initialized, return null - return null; - } - - // Ensure lazily initialization of real XML library instance - // which is done on first access to XML property - ScriptableObject.getProperty(so, "XML"); - - return (XMLLib)so.getAssociatedValue(XML_LIB_KEY); - } - - public static XMLLib extractFromScope(Scriptable scope) - { - XMLLib lib = extractFromScopeOrNull(scope); - if (lib != null) { - return lib; - } - String msg = ScriptRuntime.getMessage0("msg.XML.not.available"); - throw Context.reportRuntimeError(msg); - } - - protected final XMLLib bindToScope(Scriptable scope) - { - ScriptableObject so = ScriptRuntime.getLibraryScopeOrNull(scope); - if (so == null) { - // standard library should be initialized at this point - throw new IllegalStateException(); - } - return (XMLLib)so.associateValue(XML_LIB_KEY, this); - } - - public abstract boolean isXMLName(Context cx, Object name); - - public abstract Ref nameRef(Context cx, Object name, - Scriptable scope, int memberTypeFlags); - - public abstract Ref nameRef(Context cx, Object namespace, Object name, - Scriptable scope, int memberTypeFlags); - - /** - * Escapes the reserved characters in a value of an attribute. - * - * @param value Unescaped text - * @return The escaped text - */ - public abstract String escapeAttributeValue(Object value); - - /** - * Escapes the reserved characters in a value of a text node. - * - * @param value Unescaped text - * @return The escaped text - */ - public abstract String escapeTextValue(Object value); - - - /** - * Construct namespace for default xml statement. - */ - public abstract Object toDefaultXmlNamespace(Context cx, Object uriValue); -} diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/xml/XMLObject.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/xml/XMLObject.java deleted file mode 100644 index 5033564..0000000 --- a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/xml/XMLObject.java +++ /dev/null @@ -1,128 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Igor Bukanov - * Ethan Hugg - * Terry Lucas - * Milen Nankov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript.xml; - -import org.mozilla.javascript.*; - -/** - * This Interface describes what all XML objects (XML, XMLList) should have in common. - * - */ -public abstract class XMLObject extends IdScriptableObject -{ - public XMLObject() - { - } - - public XMLObject(Scriptable scope, Scriptable prototype) - { - super(scope, prototype); - } - - /** - * Implementation of ECMAScript [[Has]]. - */ - public abstract boolean ecmaHas(Context cx, Object id); - - /** - * Implementation of ECMAScript [[Get]]. - */ - public abstract Object ecmaGet(Context cx, Object id); - - /** - * Implementation of ECMAScript [[Put]]. - */ - public abstract void ecmaPut(Context cx, Object id, Object value); - - /** - * Implementation of ECMAScript [[Delete]]. - */ - public abstract boolean ecmaDelete(Context cx, Object id); - - /** - * Return an additional object to look for methods that runtime should - * consider during method search. Return null if no such object available. - */ - public abstract Scriptable getExtraMethodSource(Context cx); - - /** - * Generic reference to implement x.@y, x..y etc. - */ - public abstract Ref memberRef(Context cx, Object elem, - int memberTypeFlags); - - /** - * Generic reference to implement x::ns, x.@ns::y, x..@ns::y etc. - */ - public abstract Ref memberRef(Context cx, Object namespace, Object elem, - int memberTypeFlags); - - /** - * Wrap this object into NativeWith to implement the with statement. - */ - public abstract NativeWith enterWith(Scriptable scope); - - /** - * Wrap this object into NativeWith to implement the .() query. - */ - public abstract NativeWith enterDotQuery(Scriptable scope); - - /** - * Custom <tt>+</tt> operator. - * Should return {@link Scriptable#NOT_FOUND} if this object does not have - * custom addition operator for the given value, - * or the result of the addition operation. - * <p> - * The default implementation returns {@link Scriptable#NOT_FOUND} - * to indicate no custom addition operation. - * - * @param cx the Context object associated with the current thread. - * @param thisIsLeft if true, the object should calculate this + value - * if false, the object should calculate value + this. - * @param value the second argument for addition operation. - */ - public Object addValues(Context cx, boolean thisIsLeft, Object value) - { - return Scriptable.NOT_FOUND; - } - -} |