root / trunk / buildscripts / lib / custom_rhino.diff

Revision 7908, 38.4 kB (checked in by jburke, 20 months ago)

(merge from 0.4 branch) Fixes #2407 and Refs #2386. dojo compressing now works over multiple files in the same process. Layer files are now compressed, and it is possible to compress all files in the src directory via the strip-resource-comments ant task. Specify that task and a -Dstrip_and_compress=true to ant.

  • src/org/mozilla/javascript/BaseFunction.java

    ### Eclipse Workspace Patch 1.0
    #P rhino
    RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/BaseFunction.java,v
    retrieving revision 1.57
    diff -u -r1.57 BaseFunction.java
     
    373373        return sb.toString(); 
    374374    } 
    375375 
     376        String compress(int indent, int flags) 
     377        { 
     378            StringBuffer sb = new StringBuffer(); 
     379                String FuncName = null; 
     380            boolean justbody = (0 != (flags & Decompiler.ONLY_BODY_FLAG)); 
     381            if (!justbody) { 
     382                sb.append("function"); 
     383                        FuncName = getFunctionName(); 
     384                        if(FuncName.length()>0){ 
     385                                sb.append(" "+FuncName); 
     386                        } 
     387                sb.append("(){"); 
     388            } 
     389           sb.append("[native code, arity="); 
     390            sb.append(getArity()); 
     391            sb.append("]"); 
     392            if (!justbody) { 
     393                sb.append("}"); 
     394            } 
     395            return sb.toString(); 
     396        } 
     397     
    376398    public int getArity() { return 0; } 
    377399 
    378400    public int getLength() { return 0; } 
  • src/org/mozilla/javascript/NativeFunction.java

    RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/NativeFunction.java,v
    retrieving revision 1.62
    diff -u -r1.62 NativeFunction.java
     
    7070        } 
    7171    } 
    7272 
     73    /** 
     74     * Compress the script. 
     75     * <p> 
     76     *  
     77     * @param parseTree Mapping for each function node and corresponding parameters & variables names 
     78     * @param indent How much to indent the decompiled result 
     79     * @param flags Flags specifying format of decompilation output 
     80     * @return compressed script 
     81     */ 
     82    final String compress(ScriptOrFnNode parseTree, int indent, int flags) 
     83    { 
     84        String encodedSource = getEncodedSource(); 
     85        if (encodedSource == null) { 
     86            return super.compress(indent, flags); 
     87        } else { 
     88            UintMap properties = new UintMap(1); 
     89            properties.put(Decompiler.INITIAL_INDENT_PROP, indent); 
     90            return Decompiler.compress(encodedSource, flags, properties, parseTree); 
     91        } 
     92    } 
    7393    public int getLength() 
    7494    { 
    7595        int paramCount = getParamCount(); 
  • src/org/mozilla/javascript/TokenStream.java

    RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/TokenStream.java,v
    retrieving revision 1.63
    diff -u -r1.63 TokenStream.java
     
    6464    private final static int 
    6565        EOF_CHAR = -1; 
    6666 
     67    public StringBuffer lastComment; 
     68     
    6769    TokenStream(Parser parser, Reader sourceReader, String sourceString, 
    6870                int lineno) 
    6971    { 
     72        this.lastComment = new StringBuffer(); 
    7073        this.parser = parser; 
    7174        this.lineno = lineno; 
    7275        if (sourceReader != null) { 
     
    736739 
    737740            case '/': 
    738741                // is it a // comment? 
     742                // FIXME: RAR: comment, need to set config to optionally keep 
     743                // instead of skipping! 
    739744                if (matchChar('/')) { 
    740745                    skipLine(); 
    741746                    continue retry; 
  • src/org/mozilla/javascript/Context.java

    RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/Context.java,v
    retrieving revision 1.244
    diff -u -r1.244 Context.java
     
    11781178        } 
    11791179    } 
    11801180 
     1181        public final String decompileReader(Scriptable scope, Reader in, 
     1182                                                       String sourceName, int lineno, 
     1183                                                       Object securityDomain) 
     1184                        throws IOException 
     1185                    { 
     1186                        Script script = compileReader(scope, in, sourceName, lineno, 
     1187                                                      securityDomain); 
     1188                        if (script != null) { 
     1189                                        // System.err.println(script); 
     1190                            return decompileScript(script, 0); 
     1191                        } else { 
     1192                            return null; 
     1193                        } 
     1194                    } 
     1195                 
     1196        public final String compressReader(Scriptable scope, Script script, String source, 
     1197                        String sourceName, int lineno, Object securityDomain){ 
     1198                 
     1199                if (script != null) { 
     1200                        // System.err.println(script);                           
     1201                        return compressScript(script, 0, source,lineno);                         
     1202                } else { 
     1203                        return null; 
     1204                } 
     1205        } 
     1206        
     1207                 
    11811208    /** 
    11821209     * Check whether a string is ready to be compiled. 
    11831210     * <p> 
     
    13611388    } 
    13621389 
    13631390    /** 
     1391     * Compress the script. 
     1392     * <p> 
     1393     * Compressed script is returned. 
     1394     *  
     1395     * @param script the script object 
     1396     * @param indent the number of spaces to indent the result 
     1397     * @return a string representing the script source 
     1398     */ 
     1399    public final String compressScript(Script script, int indent, String source,int lineno) 
     1400    { 
     1401        //Make sure to clear out the TokenMapper state before running. 
     1402        //This allows for more than one script to be compressed. 
     1403        //However, this is not a very clean way to do the reset. 
     1404        TokenMapper.reset(); 
     1405        Decompiler.tm = new TokenMapper(); 
     1406 
     1407        NativeFunction scriptImpl = (NativeFunction) script; 
     1408         
     1409        CompilerEnvirons compilerEnv = new CompilerEnvirons(); 
     1410 
     1411        Parser parser = new Parser(compilerEnv, compilerEnv.getErrorReporter()); 
     1412         
     1413        ScriptOrFnNode tree = parser.parse(source, null, lineno); 
     1414  
     1415        return scriptImpl.compress( tree,indent, 0); 
     1416    }    
     1417    /** 
    13641418     * Decompile a JavaScript Function. 
    13651419     * <p> 
    13661420     * Decompiles a previously compiled JavaScript function object to 
     
    22402294                sourceReader = null; 
    22412295            } 
    22422296        } 
    2243  
    22442297        Parser p = new Parser(compilerEnv, compilationErrorReporter); 
    22452298        if (returnFunction) { 
    22462299            p.calledByCompileFunction = true; 
     
    22512304        } else { 
    22522305            tree = p.parse(sourceReader, sourceName, lineno); 
    22532306        } 
     2307         
    22542308        if (returnFunction) { 
    22552309            if (!(tree.getFunctionCount() == 1 
    22562310                  && tree.getFirstChild() != null 
  • src/org/mozilla/javascript/Decompiler.java

    RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/Decompiler.java,v
    retrieving revision 1.19
    diff -u -r1.19 Decompiler.java
     
    3737 
    3838package org.mozilla.javascript; 
    3939 
     40import java.util.ArrayList; 
     41import java.util.Arrays; 
     42import java.util.HashMap; 
     43import java.util.List; 
     44 
    4045/** 
    4146 * The following class save decompilation information about the source. 
    4247 * Source information is returned from the parser as a String 
     
    7075 * the final constant pool entry from information available at parse 
    7176 * time. 
    7277 */ 
     78 
     79class TokenMapper { 
     80        private ArrayList functionBracePositions = new ArrayList(); 
     81 
     82        /** 
     83         * Map of all replaced tokens 
     84         */ 
     85        private ArrayList replacedTokens = new ArrayList(); 
     86 
     87        /** 
     88         * Collection of Function nodes 
     89         */ 
     90        private static ObjArray funcObjects = new ObjArray(); 
     91 
     92        /** 
     93         * Map of each Function node and all the variables in its current function 
     94         * scope, other variables found while traversing the prototype chain and 
     95         * variables found in the top-level scope. 
     96         */ 
     97        private static ArrayList functionVarMappings = new ArrayList(); 
     98 
     99        public int functionNum = 0; 
     100 
     101        private int parentScope = 0; 
     102 
     103        private int lastTokenCount = 0; 
     104 
     105        /** 
     106         * Reset the static members for the TokenMapper. 
     107         */ 
     108        public static void reset() { 
     109                funcObjects = new ObjArray(); 
     110                functionVarMappings = new ArrayList(); 
     111        } 
     112 
     113        /** 
     114         * Generate new compressed tokens 
     115         * <p> 
     116         *  
     117         * @param token 
     118         *            value of the string token 
     119         * @param hasNewMapping 
     120         *            boolean value indicating a new variable binding 
     121         * @return compressed token 
     122         */ 
     123        private String getMappedToken(String token, boolean hasNewMapping) { 
     124                String newToken = null; 
     125                HashMap tokens = null; 
     126                String blank = new String(""); 
     127                int localScope = functionBracePositions.size() - 1; 
     128 
     129                String oldToken = getPreviousTokenMapping(token, hasNewMapping); 
     130 
     131                if (!oldToken.equalsIgnoreCase(blank)) { 
     132                        return oldToken; 
     133                } else if ((hasNewMapping || isInScopeChain(token))) { 
     134                        lastTokenCount++; 
     135                        newToken = new String("_" + Integer.toHexString(lastTokenCount)); 
     136                        if (newToken.length() >= token.length()) { 
     137                                newToken = token; 
     138                        } 
     139                        if (hasNewMapping) { 
     140                                tokens = (HashMap) replacedTokens.get(localScope); 
     141                        } else { 
     142                                tokens = (HashMap) replacedTokens.get(parentScope); 
     143                        } 
     144 
     145                        tokens.put(token, newToken); 
     146                        return newToken; 
     147                } 
     148                return token; 
     149        } 
     150 
     151        /** 
     152         * Checks for variable names in prototype chain 
     153         * <p> 
     154         *  
     155         * @param token 
     156         *            value of the string token 
     157         * @return boolean value indicating if the token is present in the chained 
     158         *         scope 
     159         */ 
     160        private boolean isInScopeChain(String token) { 
     161                int scope = functionBracePositions.size(); 
     162                HashMap chainedScopeVars = (HashMap) functionVarMappings 
     163                                .get(functionNum); 
     164                if (!chainedScopeVars.isEmpty()) { 
     165                        for (int i = scope; i > 0; i--) { 
     166                                if (chainedScopeVars.containsKey(new Integer(i))) { 
     167                                        parentScope = i - 1; 
     168                                        List temp = Arrays.asList((String[]) chainedScopeVars 
     169                                                        .get(new Integer(i))); 
     170                                        if (temp.indexOf(token) != -1) { 
     171                                                return true; 
     172                                        } 
     173                                } 
     174                        } 
     175                } 
     176                return false; 
     177        } 
     178 
     179        /** 
     180         * Checks previous token mapping 
     181         * <p> 
     182         *  
     183         * @param token 
     184         *            value of the string token 
     185         * @param hasNewMapping 
     186         *            boolean value indicating a new variable binding 
     187         * @return string value of the previous token or blank string 
     188         */ 
     189        private String getPreviousTokenMapping(String token, boolean hasNewMapping) { 
     190                String result = new String(""); 
     191                int scope = replacedTokens.size() - 1; 
     192 
     193                if (scope < 0) { 
     194                        return result; 
     195                } 
     196 
     197                if (hasNewMapping) { 
     198                        HashMap tokens = (HashMap) (replacedTokens.get(scope)); 
     199                        if (tokens.containsKey(token)) { 
     200                                result = (String) tokens.get(token); 
     201                                return result; 
     202                        } 
     203                } else { 
     204                        for (int i = scope; i > -1; i--) { 
     205                                HashMap tokens = (HashMap) (replacedTokens.get(i)); 
     206                                if (tokens.containsKey(token)) { 
     207                                        result = (String) tokens.get(token); 
     208                                        return result; 
     209                                } 
     210                        } 
     211                } 
     212                return result; 
     213        } 
     214 
     215        /** 
     216         * Generate mappings for each Function node and parameters and variables 
     217         * names associated with it. 
     218         * <p> 
     219         *  
     220         * @param parseTree 
     221         *            Mapping for each function node and corresponding parameters & 
     222         *            variables names 
     223         */ 
     224        private void collectFunctionMappings(ScriptOrFnNode parseTree) { 
     225                int level = -1; 
     226                collectFuncNodes(parseTree, level); 
     227        } 
     228 
     229        /** 
     230         * Recursive method to traverse all Function nodes 
     231         * <p> 
     232         *  
     233         * @param parseTree 
     234         *            Mapping for each function node and corresponding parameters & 
     235         *            variables names 
     236         * @param level 
     237         *            scoping level 
     238         */ 
     239        private static void collectFuncNodes(ScriptOrFnNode parseTree, int level) { 
     240                level++; 
     241                functionVarMappings.add(new HashMap()); 
     242 
     243                HashMap bindingNames = (HashMap) functionVarMappings 
     244                                .get(functionVarMappings.size() - 1); 
     245                bindingNames.put(new Integer(level), parseTree.getParamAndVarNames()); 
     246                funcObjects.add(parseTree); 
     247 
     248                int nestedCount = parseTree.getFunctionCount(); 
     249                for (int i = 0; i != nestedCount; ++i) { 
     250                        collectFuncNodes(parseTree.getFunctionNode(i), level); 
     251                        bindingNames = (HashMap) functionVarMappings 
     252                                        .get(functionVarMappings.size() - 1); 
     253                        bindingNames.put(new Integer(level), parseTree 
     254                                        .getParamAndVarNames()); 
     255                } 
     256        } 
     257 
     258        /** 
     259         * Compress the script 
     260         * <p> 
     261         *  
     262         * @param encodedSource 
     263         *            encoded source string 
     264         * @param offset 
     265         *            position within the encoded source 
     266         * @param asQuotedString 
     267         *            boolean value indicating a quoted string 
     268         * @param sb 
     269         *            String buffer reference 
     270         * @param prevToken 
     271         *            Previous token in encoded source 
     272         * @param inArgsList 
     273         *            boolean value indicating position inside arguments list 
     274         * @param currentLevel 
     275         *            embeded function level 
     276         * @param parseTree 
     277         *            Mapping of each function node and corresponding parameters & 
     278         *            variables names 
     279         * @return compressed script 
     280         */ 
     281        public int sourceCompress(String encodedSource, int offset, 
     282                        boolean asQuotedString, StringBuffer sb, int prevToken, 
     283                        boolean inArgsList, int currentLevel, ScriptOrFnNode parseTree) { 
     284 
     285                boolean hasNewMapping = false; 
     286 
     287                if (functionVarMappings.isEmpty()) 
     288                        collectFunctionMappings(parseTree); 
     289 
     290                int length = encodedSource.charAt(offset); 
     291                ++offset; 
     292                if ((0x8000 & length) != 0) { 
     293                        length = ((0x7FFF & length) << 16) | encodedSource.charAt(offset); 
     294                        ++offset; 
     295                } 
     296                if (sb != null) { 
     297                        String str = encodedSource.substring(offset, offset + length); 
     298                        String sourceStr = new String(str); 
     299                        if ((prevToken == Token.VAR) || (inArgsList)) { 
     300                                hasNewMapping = true; 
     301                        } 
     302                        if (((functionBracePositions.size() > 0) && (currentLevel >= (((Integer) functionBracePositions 
     303                                        .get(functionBracePositions.size() - 1)).intValue()))) 
     304                                        || (inArgsList)) { 
     305                                if (prevToken != Token.DOT) { 
     306                                        str = this.getMappedToken(str, hasNewMapping); 
     307                                } 
     308                        } 
     309                        if ((!inArgsList) && (asQuotedString)) { 
     310                                if ((prevToken == Token.LC) || (prevToken == Token.COMMA)) { 
     311                                        str = sourceStr; 
     312                                } 
     313                        } 
     314                        if (!asQuotedString) { 
     315                                sb.append(str); 
     316                        } else { 
     317                                sb.append('"'); 
     318                                sb.append(ScriptRuntime.escapeString(str)); 
     319                                sb.append('"'); 
     320                        } 
     321                } 
     322                return offset + length; 
     323        } 
     324 
     325        public void enterNestingLevel(int braceNesting) { 
     326                functionBracePositions.add(new Integer(braceNesting + 1)); 
     327                replacedTokens.add(new HashMap()); 
     328        } 
     329 
     330        public void leaveNestingLevel(int braceNesting) { 
     331                Integer bn = new Integer(braceNesting); 
     332 
     333                if ((functionBracePositions.contains(bn)) 
     334                                && (replacedTokens.size() > 0)) { 
     335                        // remove our mappings now! 
     336                        int scopedSize = replacedTokens.size(); 
     337                        replacedTokens.remove(scopedSize - 1); 
     338                        functionBracePositions.remove(bn); 
     339                } 
     340        } 
     341} 
     342         
     343         
    73344public class Decompiler 
    74345{ 
    75346    /** 
     
    266537        return new String(sourceBuffer, offset, sourceTop - offset); 
    267538    } 
    268539 
     540    //Used to be private, but making it public so we 
     541    //can reset the token state between compression runs. 
     542    //Not very pretty. 
     543    public static TokenMapper tm = new TokenMapper(); 
     544     
     545    /** 
     546     * Compress the script 
     547     * <p> 
     548     *  
     549     * @param encodedSource encoded source string 
     550     * @param flags Flags specifying format of decompilation output 
     551     * @param properties Decompilation properties 
     552     * @param parseTree Mapping for each function node and corresponding parameters & variables names 
     553     * @return compressed script 
     554     */ 
     555    public static String compress(String encodedSource, int flags, 
     556            UintMap properties, ScriptOrFnNode parseTree){ 
     557         
     558         int length = encodedSource.length(); 
     559         if (length == 0) { return ""; } 
     560         int indent = properties.getInt(INITIAL_INDENT_PROP, 0); 
     561         if (indent < 0) throw new IllegalArgumentException(); 
     562         int indentGap = properties.getInt(INDENT_GAP_PROP, 4); 
     563         if (indentGap < 0) throw new IllegalArgumentException(); 
     564         int caseGap = properties.getInt(CASE_GAP_PROP, 2); 
     565         if (caseGap < 0) throw new IllegalArgumentException(); 
     566         StringBuffer result = new StringBuffer(); 
     567         boolean justFunctionBody = (0 != (flags & Decompiler.ONLY_BODY_FLAG)); 
     568         boolean toSource = (0 != (flags & Decompiler.TO_SOURCE_FLAG)); 
     569         // Spew tokens in source, for debugging. 
     570         // as TYPE number char 
     571         if (printSource) { 
     572             System.err.println("length:" + length); 
     573             for (int i = 0; i < length; ++i) { 
     574                 // Note that tokenToName will fail unless Context.printTrees 
     575                 // is true. 
     576                 String tokenname = null; 
     577                 if (Token.printNames) { 
     578                     tokenname = Token.name(encodedSource.charAt(i)); 
     579                 } 
     580                 if (tokenname == null) { 
     581                     tokenname = "---"; 
     582                 } 
     583                 String pad = tokenname.length() > 7 
     584                     ? "\t" 
     585                     : "\t\t"; 
     586                 System.err.println 
     587                     (tokenname 
     588                      + pad + (int)encodedSource.charAt(i) 
     589                      + "\t'" + ScriptRuntime.escapeString 
     590                      (encodedSource.substring(i, i+1)) 
     591                      + "'"); 
     592             } 
     593             System.err.println(); 
     594         } 
     595         int braceNesting = 0; 
     596         boolean afterFirstEOL = false; 
     597         int i = 0; 
     598        int prevToken = 0; 
     599        boolean primeFunctionNesting = false; 
     600        boolean inArgsList = false; 
     601        boolean primeInArgsList = false; 
     602         int topFunctionType; 
     603         if (encodedSource.charAt(i) == Token.SCRIPT) { 
     604             ++i; 
     605             topFunctionType = -1; 
     606         } else { 
     607             topFunctionType = encodedSource.charAt(i + 1); 
     608         } 
     609         if (!toSource) { 
     610             // add an initial newline to exactly match js. 
     611             // result.append('\n'); 
     612             for (int j = 0; j < indent; j++){ 
     613                 // result.append(' '); 
     614                 result.append(""); 
     615                } 
     616         } else { 
     617             if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) { 
     618                 result.append('('); 
     619             } 
     620         } 
     621         while (i < length) { 
     622                if(i>0){ 
     623                        prevToken = encodedSource.charAt(i-1); 
     624                } 
     625                // System.out.println(Token.name(getNext(source, length, i))); 
     626             switch(encodedSource.charAt(i)) { 
     627             case Token.NAME: 
     628             case Token.REGEXP:  // re-wrapped in '/'s in parser... 
     629                        int jumpPos = getSourceStringEnd(encodedSource, i+1); 
     630                        if(Token.OBJECTLIT == encodedSource.charAt(jumpPos)){ 
     631                                i = printSourceString(encodedSource, i + 1, false, result); 
     632                        }else{ 
     633                                i = tm.sourceCompress(  encodedSource, i + 1, false, result, prevToken,  
     634                                                                                inArgsList, braceNesting, parseTree); 
     635                        } 
     636                 continue; 
     637             case Token.STRING: 
     638                 i = printSourceString(encodedSource, i + 1, true, result); 
     639                 continue; 
     640             case Token.NUMBER: 
     641                 i = printSourceNumber(encodedSource, i + 1, result); 
     642                 continue; 
     643             case Token.TRUE: 
     644                 result.append("true"); 
     645                 break; 
     646             case Token.FALSE: 
     647                 result.append("false"); 
     648                 break; 
     649             case Token.NULL: 
     650                 result.append("null"); 
     651                 break; 
     652             case Token.THIS: 
     653                 result.append("this"); 
     654                 break; 
     655             case Token.FUNCTION: 
     656                 ++i; // skip function type 
     657                 tm.functionNum++; 
     658                        primeInArgsList = true; 
     659                        primeFunctionNesting = true; 
     660                 result.append("function"); 
     661                 if (Token.LP != getNext(encodedSource, length, i)) { 
     662                     result.append(' '); 
     663                 } 
     664                 break; 
     665             case FUNCTION_END: 
     666                 // Do nothing 
     667                 break; 
     668             case Token.COMMA: 
     669                 result.append(","); 
     670                 break; 
     671             case Token.LC: 
     672                        ++braceNesting; 
     673                 if (Token.EOL == getNext(encodedSource, length, i)){ 
     674                     indent += indentGap; 
     675                        } 
     676                 result.append('{'); 
     677                 // // result.append('\n'); 
     678                 break; 
     679             case Token.RC: { 
     680                        tm.leaveNestingLevel(braceNesting); 
     681                 --braceNesting; 
     682                 /* don't print the closing RC if it closes the 
     683                  * toplevel function and we're called from 
     684                  * decompileFunctionBody. 
     685                  */ 
     686                 if(justFunctionBody && braceNesting == 0){ 
     687                     break; 
     688                        } 
     689                 // // result.append('\n'); 
     690                 result.append('}'); 
     691                 // // result.append(' '); 
     692                 switch (getNext(encodedSource, length, i)) { 
     693                     case Token.EOL: 
     694                     case FUNCTION_END: 
     695                         indent -= indentGap; 
     696                         break; 
     697                     case Token.WHILE: 
     698                     case Token.ELSE: 
     699                         indent -= indentGap; 
     700                         // result.append(' '); 
     701                         result.append(""); 
     702                         break; 
     703                 } 
     704                 break; 
     705             } 
     706             case Token.LP: 
     707                        if(primeInArgsList){ 
     708                                inArgsList = true; 
     709                                primeInArgsList = false; 
     710                        }