All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dojotoolkit.shrinksafe.TokenMapper Maven / Gradle / Ivy

There is a newer version: 1.9.0
Show newest version
/*
 * Version: MPL 1.1
 *
 * 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):
 *   Alex Russell
 *   Richard Backhouse
 */
 
package org.dojotoolkit.shrinksafe;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.mozilla.javascript.ScriptOrFnNode;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Token;

public class TokenMapper {
	private List functionBracePositions = new ArrayList();

	/**
	 * Map of all replaced tokens
	 */
	private List replacedTokens = new ArrayList();

	/**
	 * Map of each Function node and all the variables in its current function
	 * scope, other variables found while traversing the prototype chain and
	 * variables found in the top-level scope.
	 */
	private List functionVarMappings = new ArrayList();
	private Map debugDataList = new HashMap();

	private int functionNum = 0;

	private int parentScope = 0;

	private int lastTokenCount = 0;
	
	public TokenMapper(ScriptOrFnNode parseTree) {
		collectFunctionMappings(parseTree);
	}

	public void incrementFunctionNumber() {
		functionNum++;
	}
	
	/**
	 * Generate new compressed tokens
	 * 

* * @param token * value of the string token * @param hasNewMapping * boolean value indicating a new variable binding * @return compressed token */ private String getMappedToken(String token, boolean hasNewMapping) { String newToken = null; Map tokens = null; String blank = new String(""); int localScope = functionBracePositions.size() - 1; String oldToken = getPreviousTokenMapping(token, hasNewMapping); if (!oldToken.equalsIgnoreCase(blank)) { return oldToken; } else if ((hasNewMapping || isInScopeChain(token))) { newToken = new String("_" + Integer.toHexString(++lastTokenCount)); if (newToken.length() >= token.length() && token.charAt(0) != '_') { newToken = token; lastTokenCount--; } tokens = (Map) replacedTokens.get(hasNewMapping ? localScope : parentScope); tokens.put(token, newToken); return newToken; } return token; } /** * Checks for variable names in prototype chain *

* * @param token * value of the string token * @return boolean value indicating if the token is present in the chained * scope */ private boolean isInScopeChain(String token) { int scope = functionBracePositions.size(); Map chainedScopeVars = (Map) functionVarMappings.get(functionNum); if (!chainedScopeVars.isEmpty()) { for (int i = scope; i > 0; i--) { if (chainedScopeVars.containsKey(new Integer(i))) { parentScope = i - 1; List temp = Arrays.asList((String[]) chainedScopeVars.get(new Integer(i))); if (temp.indexOf(token) != -1) { return true; } } } } return false; } /** * Checks previous token mapping *

* * @param token * value of the string token * @param hasNewMapping * boolean value indicating a new variable binding * @return string value of the previous token or blank string */ private String getPreviousTokenMapping(String token, boolean hasNewMapping) { String result = new String(""); int scope = replacedTokens.size() - 1; if (scope < 0) { return result; } if (hasNewMapping) { Map tokens = (Map) (replacedTokens.get(scope)); if (tokens.containsKey(token)) { result = (String) tokens.get(token); return result; } } else { for (int i = scope; i > -1; i--) { Map tokens = (Map) (replacedTokens.get(i)); if (tokens.containsKey(token)) { result = (String) tokens.get(token); return result; } } } return result; } /** * Generate mappings for each Function node and parameters and variables * names associated with it. *

* * @param parseTree * Mapping for each function node and corresponding parameters & * variables names */ private void collectFunctionMappings(ScriptOrFnNode parseTree) { int level = -1; collectFuncNodes(parseTree, level, null); } /** * Recursive method to traverse all Function nodes *

* * @param parseTree * Mapping for each function node and corresponding parameters & * variables names * @param level * scoping level */ private void collectFuncNodes(ScriptOrFnNode parseTree, int level, ScriptOrFnNode parent) { level++; DebugData debugData = new DebugData(); debugData.start = parseTree.getBaseLineno(); debugData.end = parseTree.getEndLineno(); debugData.paramAndVarNames = parseTree.getParamAndVarNames(); debugDataList.put(new Integer(parseTree.getEncodedSourceStart()), debugData); functionVarMappings.add(new HashMap()); Map bindingNames = (Map) functionVarMappings.get(functionVarMappings.size() - 1); bindingNames.put(new Integer(level), parseTree.getParamAndVarNames()); if (parent != null) { bindingNames.put(new Integer(level-1), parent.getParamAndVarNames()); } int nestedCount = parseTree.getFunctionCount(); for (int i = 0; i != nestedCount; ++i) { collectFuncNodes(parseTree.getFunctionNode(i), level, parseTree); bindingNames = (Map) functionVarMappings.get(functionVarMappings.size() - 1); bindingNames.put(new Integer(level), parseTree.getParamAndVarNames()); } } /** * Compress the script *

* * @param encodedSource * encoded source string * @param offset * position within the encoded source * @param asQuotedString * boolean value indicating a quoted string * @param sb * String buffer reference * @param prevToken * Previous token in encoded source * @param inArgsList * boolean value indicating position inside arguments list * @param currentLevel * embeded function level * @param parseTree * Mapping of each function node and corresponding parameters & * variables names * @return compressed script */ public int sourceCompress(String encodedSource, int offset, boolean asQuotedString, StringBuffer sb, int prevToken, boolean inArgsList, int currentLevel, ReplacedTokens replacedTokens) { boolean hasNewMapping = false; int length = encodedSource.charAt(offset); ++offset; if ((0x8000 & length) != 0) { length = ((0x7FFF & length) << 16) | encodedSource.charAt(offset); ++offset; } String str = encodedSource.substring(offset, offset + length); if ((prevToken == Token.VAR) || (inArgsList)) { hasNewMapping = true; } if (sb != null) { String sourceStr = new String(str); if (((functionBracePositions.size() > 0) && (currentLevel >= (((Integer) functionBracePositions.get(functionBracePositions.size() - 1)).intValue()))) || (inArgsList)) { if (prevToken != Token.DOT) { // Look for replacement token in provided lookup object. str = replacedTokens.find(str); } } if ((!inArgsList) && (asQuotedString)) { if ((prevToken == Token.LC) || (prevToken == Token.COMMA)) { str = sourceStr; } } if (!asQuotedString) { sb.append(str); } else { sb.append('"'); sb.append(ScriptRuntime.escapeString(str)); sb.append('"'); } } else if (((functionBracePositions.size() > 0) && (currentLevel >= (((Integer) functionBracePositions.get(functionBracePositions.size() - 1)).intValue()))) || (inArgsList)) { if (prevToken != Token.DOT) { getMappedToken(str, hasNewMapping); } } return offset + length; } public void enterNestingLevel(int braceNesting) { functionBracePositions.add(new Integer(braceNesting + 1)); replacedTokens.add(new HashMap()); } public boolean leaveNestingLevel(int braceNesting) { boolean tokensRemoved = false; Integer bn = new Integer(braceNesting); if ((functionBracePositions.contains(bn)) && (replacedTokens.size() > 0)) { // remove our mappings now! int scopedSize = replacedTokens.size(); replacedTokens.remove(scopedSize - 1); functionBracePositions.remove(bn); tokensRemoved = true; } return tokensRemoved; } public Map getCurrentTokens() { Map m = null; if (replacedTokens.size() > 0) { m = (Map)replacedTokens.get(replacedTokens.size() - 1); } return m; } public DebugData getDebugData(Integer functionPosition) { return (DebugData)debugDataList.get(functionPosition); } public void reset() { functionNum = 0; parentScope = 0; lastTokenCount = 0; functionBracePositions = new ArrayList(); replacedTokens = new ArrayList(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy