Index: /CKPackager/trunk/_source/ckpackager.js
===================================================================
--- /CKPackager/trunk/_source/ckpackager.js	(revision 3145)
+++ /CKPackager/trunk/_source/ckpackager.js	(revision 3145)
@@ -0,0 +1,82 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+importPackage( org.mozilla.javascript );
+
+importClass( java.lang.System );
+importClass( java.io.File );
+importClass( java.io.BufferedWriter );
+importClass( java.io.FileWriter );
+
+var jarPath = JavaAdapter(org.mozilla.javascript.Parser)["class"].getResource("/org/mozilla/javascript").toString();
+var packagerPath = jarPath.replaceFirst( "^jar:", '' ).replaceFirst( "\/js\.jar\!\/org\/mozilla\/javascript$", '');
+
+load( packagerPath + "/includes/ckpackager.js" );
+
+function error( msg )
+{
+	print( msg );
+	print( '' );
+	quit();
+}
+
+if ( arguments[0] == '-dump' )
+{
+	CKPACKAGER.loadCode( 'includes/parser.js' );
+	CKPACKAGER.parser.dumpThree( CKPACKAGER.tools.readFile( arguments[1] ) );
+	quit();
+}
+else if ( arguments[0] == '-compress' )
+{
+	CKPACKAGER.loadCode( 'includes/scriptcompressor.js' );
+
+	var compressed = CKPACKAGER.scriptCompressor.compress( CKPACKAGER.tools.readFile( arguments[1] ) );
+
+	if ( arguments[2] )
+	{
+		var out = new BufferedWriter( new FileWriter( arguments[2] ) );
+		out.write( compressed );
+		out.close();
+	}
+
+	print( compressed );
+	quit();
+}
+else if ( arguments[0] == '-test' )
+{
+	CKPACKAGER.loadCode( 'test/test.js' );
+	quit();
+}
+
+CKPACKAGER.packFile = arguments[0];
+
+if ( !CKPACKAGER.packFile )
+	error( 'Usage:java -jar js.jar ckpackager.js sample.pack' );
+
+CKPACKAGER.packDir = (function()
+{
+	var packFile = new File( CKPACKAGER.packFile );
+
+	if ( !packFile.isFile() )
+		error( 'The file name "' + CKPACKAGER.packFile + '" was not found.' );
+
+	return packFile.getParent() || './';
+})();
+
+CKPACKAGER.outputDir = CKPACKAGER.packDir;
+
+CKPACKAGER.loadCode( 'includes/packager.js' );
+
+//for ( var o in CKPACKAGER )
+//	print( o + ': ' + CKPACKAGER[o] );
+
+// print( String( System.getProperties() ).replace( /,/g, '\n') );
+
+(function()
+{
+	var packager = new CKPACKAGER.packager();
+	packager.loadDefinitionFile( CKPACKAGER.packFile );
+	packager.run();
+})();
Index: /CKPackager/trunk/_source/includes/ckpackager.js
===================================================================
--- /CKPackager/trunk/_source/includes/ckpackager.js	(revision 3145)
+++ /CKPackager/trunk/_source/includes/ckpackager.js	(revision 3145)
@@ -0,0 +1,60 @@
+/*
+Copyright (c) 2003-2008, Frederico Caldeira Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+var CKPACKAGER =
+{
+	dir : (function()
+		{
+			var packagerDir = new File( System.getProperty( 'java.class.path' ) );
+			return packagerDir.getParent();
+		})(),
+
+	getPackPath : function( relativePath )
+	{
+		var file = new File( CKPACKAGER.packDir, relativePath );
+		return file.getAbsolutePath();
+	},
+
+	getOutputPath : function( relativePath )
+	{
+		var file = new File( CKPACKAGER.outputDir, relativePath );
+		return file.getAbsolutePath();
+	},
+
+	getPackagerPath : function( relativePath )
+	{
+		var file = new File( CKPACKAGER.dir, relativePath );
+		return file.getAbsolutePath();
+	},
+
+	_loadedCode : {},
+
+	loadCode : function( path )
+	{
+		if ( this._loadedCode[ path ] )
+			return;
+
+		load( CKPACKAGER.getPackagerPath( path ) );
+
+		this._loadedCode[ path ] = true;
+	},
+
+	tools :
+	{
+		readFile : function( file )
+		{
+			var data = readFile( file, "UTF-8" );
+
+			// Remove the UTF-8 BOM.
+			return data.replace( /^\xEF\xBB\xBF/, '' );
+		},
+
+		getFileName : function( file )
+		{
+			file = new File( file );
+			return file.getName();
+		}
+	}
+};
Index: /CKPackager/trunk/_source/includes/packagefile.js
===================================================================
--- /CKPackager/trunk/_source/includes/packagefile.js	(revision 3145)
+++ /CKPackager/trunk/_source/includes/packagefile.js	(revision 3145)
@@ -0,0 +1,72 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+importClass( java.io.BufferedWriter );
+importClass( java.io.FileWriter );
+
+CKPACKAGER.loadCode( 'includes/scriptcompressor.js' );
+
+CKPACKAGER.packageFile = function( outputFile )
+{
+	this.output = outputFile;
+
+	this.header = null;
+	this.noCheck = false;
+	this.constants = null;
+	this.renameGlobals = false;
+	this.compactJavascript = true;
+	this.wrap = false;
+	this.files = [];
+};
+
+CKPACKAGER.packageFile.prototype =
+{
+	createFile : function()
+	{
+		var source = [];
+
+		print( 'Packaging file ' + CKPACKAGER.tools.getFileName( this.output ) + '\n' );
+
+		for ( var i = 0 ; i < this.files.length ; i++ )
+		{
+			var file = this.files[ i ];
+
+			print( '    Adding ' + CKPACKAGER.tools.getFileName( file ) );
+
+			source.push( CKPACKAGER.tools.readFile( file ), '\n' );
+		}
+
+		source = source.join( '' );
+
+		var compressed = this.compactJavascript ?
+			CKPACKAGER.scriptCompressor.compress( source, this.renameGlobals, this.constants, this.noCheck, this.wrap ) :
+			source;
+
+		if ( this.header )
+			compressed = this.header + compressed;
+
+		compressed += '\n';
+
+		try
+		{
+			var file = new File( this.output );
+			file['delete']();
+
+			var out = new BufferedWriter( new FileWriter( this.output ) );
+			out.write( compressed );
+			out.close();
+	    }
+	    catch ( e )
+	    {
+			throw e;
+	    }
+
+		print( '' );
+		print( '    Number of files processed: ' + this.files.length );
+		print( '    Original size............: ' + source.length + ' bytes' );
+		print( '    Output file size.........: ' + compressed.length + ' bytes (' + Math.round( compressed.length / source.length * 100 ) + '% of original)' );
+		print( '' );
+	}
+};
Index: /CKPackager/trunk/_source/includes/packager.js
===================================================================
--- /CKPackager/trunk/_source/includes/packager.js	(revision 3145)
+++ /CKPackager/trunk/_source/includes/packager.js	(revision 3145)
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKPACKAGER.loadCode( 'includes/packagefile.js' );
+
+CKPACKAGER.packager = function()
+{
+	this.packageFiles = [];
+};
+
+CKPACKAGER.packager.prototype =
+{
+	loadDefinitionFile : function( filePath )
+	{
+		var file = new File( filePath );
+
+		// Evaluate the package definition, moving its contents to CKPACKAGER.packDefinition.
+		var packCode = 'var pack = { ' + CKPACKAGER.tools.readFile( filePath ) + '\n};';
+
+		var cx = Context.enter(),
+			scope = cx.initStandardObjects();
+
+		cx.evaluateString( scope, packCode, file.getName(), 1, null );
+
+		this.loadDefinition( scope.pack );
+	},
+
+	loadDefinition : function( definitionObject )
+	{
+		var packages = definitionObject.packages;
+
+		if ( packages )
+		{
+			for ( var i = 0 ; i < packages.length ; i++ )
+			{
+				var packDefinition = packages[ i ];
+
+				if ( !packDefinition.output )
+					error( 'The "output" value must be set for all packages in the packager defintion file(' + CKPACKAGER.packFile + ').' );
+
+				var packFile = new CKPACKAGER.packageFile( CKPACKAGER.getOutputPath( packDefinition.output ) );
+
+				if ( definitionObject.header )
+					packFile.header = definitionObject.header;
+
+				if ( typeof definitionObject.noCheck != 'undefined' )
+					packFile.noCheck = definitionObject.noCheck;
+
+				if ( definitionObject.constants )
+					packFile.constants = definitionObject.constants;
+
+				if ( typeof packDefinition.renameGlobals != 'undefined' )
+					packFile.renameGlobals = packDefinition.renameGlobals;
+
+				if ( typeof packDefinition.compactJavascript != 'undefined' )
+					packFile.compactJavascript = packDefinition.compactJavascript;
+
+				if ( typeof packDefinition.wrap != 'undefined' )
+					packFile.wrap = packDefinition.wrap;
+
+				var files = packDefinition.files;
+
+				if ( files )
+				{
+					for ( var f = 0 ; f < files.length ; f++ )
+						packFile.files.push( CKPACKAGER.getPackPath( files[ f ] ) );
+				}
+
+				this.packageFiles.push( packFile );
+			}
+		}
+	},
+
+	run : function()
+	{
+		var time = new Date();
+
+		for ( var i = 0 ; i < this.packageFiles.length ; i++ )
+		{
+			this.packageFiles[ i ].createFile();
+		}
+
+		time = ( new Date() ) - time;
+		time = time / 1000;
+
+		switch ( this.packageFiles.length )
+		{
+			case 0 :
+				print( 'No files defined' );
+				break;
+			case 1 :
+				print( 'The generation of the package file has been completed in ' + time + ' seconds.' );
+				break;
+			default :
+				print( 'The generation of ' + this.packageFiles.length + ' files has been completed in ' + time + ' seconds.' );
+				break;
+		}
+
+		print( '' );
+	}
+};
Index: /CKPackager/trunk/_source/includes/parser.js
===================================================================
--- /CKPackager/trunk/_source/includes/parser.js	(revision 3145)
+++ /CKPackager/trunk/_source/includes/parser.js	(revision 3145)
@@ -0,0 +1,121 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+load( '../includes/token.js' );
+
+importPackage( org.mozilla.javascript );
+
+importClass( java.io.File );
+importClass( java.io.FileReader );
+
+(function()
+{
+	var indentation,
+		tree;
+
+	var printNode = function( node )
+	{
+		var str,
+			type = node.getType(),
+			currentTree = tree;
+
+		str =
+			node instanceof Node.StringNode ?
+				node.getString()
+			: type == Token.NUMBER ?
+				str = node.getDouble()
+			:
+				'';
+
+		switch ( type )
+		{
+			case Token.FUNCTION :
+
+				var fnIndex = node.getExistingIntProp( Node.FUNCTION_PROP ),
+					fn		= tree.getFunctionNode(fnIndex),
+					args	= [];
+
+				if ( fn.symbolTable != null )
+				{
+					var iter = fn.symbolTable.keySet().iterator();
+					while ( args.length < fn.getParamCount() )
+						args.push( iter.next() );
+				}
+
+				str += '(' + args + ')';
+
+				node = tree = fn;
+				break;
+
+			case Token.REGEXP :
+				str = '/' + tree.getRegexpString( node.getExistingIntProp( Node.REGEXP_PROP ) ) + '/';
+				str += tree.getRegexpFlags( node.getExistingIntProp( Node.REGEXP_PROP ) );
+				break;
+
+			case Token.CASE :
+			case Token.GOTO :
+				str = node.target.getNext();
+				break;
+
+			case Token.LOOP :
+				str = node.target;
+				break;
+
+			case Token.TARGET :
+				str = node.labelId();
+				break;
+		}
+
+		try { str = node.getString(); } catch (e) {}
+
+		print( indentation + node + ': ' + GetTokenName( type ) +
+			' (' + node.getLineno() + ')' +
+			( node instanceof Node.Scope ? ' (scope)' : '' ) +
+			( str !== '' ? ' = ' + str : '' ) );
+
+		indentation += '.';
+
+		node = node.getFirstChild()
+
+		while ( node )
+		{
+			printNode( node );
+			node = node.getNext();
+		}
+
+		if ( type == Token.FUNCTION )
+		{
+			tree = currentTree;
+		}
+
+		// Uncomment to stop on a specific token type.
+		/*
+		if ( type == Token.USE_STACK )
+			quit();
+		*/
+
+		indentation = indentation.substr( 1 );
+	}
+
+	CKPACKAGER.parser =
+	{
+		dumpThree : function( script )
+		{
+			// Setup the compiler environment, error reporter...
+			var compilerEnv = new CompilerEnvirons();
+			var errorReporter = compilerEnv.getErrorReporter();
+
+			// Create an instance of the parser...
+			var parser = new Parser(compilerEnv, errorReporter);
+
+			var scriptOrFnNode = parser.parse(script, null, 1);
+			tree = scriptOrFnNode;
+
+			indentation = '';
+
+			printNode( scriptOrFnNode );
+		}
+	};
+})();
Index: /CKPackager/trunk/_source/includes/scope.js
===================================================================
--- /CKPackager/trunk/_source/includes/scope.js	(revision 3145)
+++ /CKPackager/trunk/_source/includes/scope.js	(revision 3145)
@@ -0,0 +1,151 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+(function()
+{
+	var preProcess = function ( scope, node, names )
+	{
+		var child = node.getFirstChild();
+		while( child )
+		{
+			switch ( child.getType() )
+			{
+				case Token.THIS :
+					scope.thisCount++;
+					break;
+
+				case Token.FUNCTION :
+
+					// Functions are considered declared since the very start
+					// of the scope execution. So, we must look for them here.
+					// Unfortunately Symbol.declType is not public in the Rhino
+					// code.
+
+					scope.functionCount++;
+
+					var name = String( child.getString() );
+					if ( name.length > 0 )
+						scope.declaredNames[ name ] = 1;
+					break;
+
+				default:
+					preProcess( scope, child, names );
+			}
+
+			child = child.getNext();
+		}
+
+		return names;
+	};
+
+	CKPACKAGER.scope = function( rhinoNode, parentScope )
+	{
+		this.node = rhinoNode;
+		this.parent = parentScope;
+		this.args = [];
+		this.names = {};
+		this.declaredNames =
+		{
+			'this' : 1
+		};
+		this.thisCount = 0;
+		this.functionCount = 0;
+		this.noRename = false;
+
+		this.newNames = {};
+		this.nameCounter = parentScope ? parentScope.nameCounter : 0;
+
+		if ( rhinoNode.symbolTable != null )
+		{
+			var iter = rhinoNode.symbolTable.keySet().iterator(),
+				paramCount = rhinoNode.getParamCount();
+
+			while ( iter.hasNext() )
+			{
+				var symbol = String( iter.next() );
+
+				if ( this.args.length < paramCount )
+				{
+					this.args.push( symbol );
+					this.declaredNames[ symbol ] = 1;
+				}
+
+				this.names[ symbol ] = getNextName( this );
+			}
+		}
+
+		preProcess( this, rhinoNode );
+	}
+
+	var nameChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.split( '' ),
+		nameCharsLength = nameChars.length;
+
+	// Mangles the list, having a different order for each run.
+	/*
+	nameChars.sort( function( a, b )
+		{
+			return Math.random() < 0.5 ? -1 : 1;
+		});
+	*/
+
+	var getNextName = function( scope )
+	{
+		var name;
+
+		do
+		{
+			var number = ++scope.nameCounter;
+
+			name = '';
+
+			while ( true )
+			{
+				var mod = number % nameCharsLength;
+				number = Math.floor( number / nameCharsLength );
+
+				if ( mod == 0 )
+				{
+					name = nameChars[ nameCharsLength - 1 ] + name;
+					number--;
+				}
+				else
+				{
+					name = nameChars[ mod - 1 ] + name;
+				}
+
+				if ( number <= 0 )
+					break;
+			}
+		}
+		while ( !isNaN( name.substr( 0, 1 ) ) )
+
+		return name;
+	};
+
+	CKPACKAGER.scope.prototype.getNewName = function( name, includeNotDeclared, includeNotListed )
+	{
+		if ( !this.noRename )
+		{
+			if ( ( includeNotDeclared || this.declaredNames[ name ] ) && this.names[ name ] )
+				return this.names[ name ];
+			else if ( includeNotListed || name == 'this' )
+				return ( this.declaredNames[ name ] = this.names[ name ] = getNextName( this ) );
+			else if ( this.parent )
+				return this.parent.getNewName( name, true );
+		}
+
+		return name;
+	};
+
+	CKPACKAGER.scope.prototype.declareName = function( name )
+	{
+		this.declaredNames[ name ] = 1;
+	};
+
+	CKPACKAGER.scope.prototype.addRenamedRef = function( name )
+	{
+		return this.names[ name ] = getNextName( this );
+	};
+})();
Index: /CKPackager/trunk/_source/includes/scriptcompressor.js
===================================================================
--- /CKPackager/trunk/_source/includes/scriptcompressor.js	(revision 3145)
+++ /CKPackager/trunk/_source/includes/scriptcompressor.js	(revision 3145)
@@ -0,0 +1,1217 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+importPackage( org.mozilla.javascript );
+importPackage( java.util.regex );
+
+importClass( java.io.File );
+importClass( java.io.FileReader );
+
+CKPACKAGER.loadCode( 'includes/scope.js' );
+CKPACKAGER.loadCode( 'includes/token.js' );
+
+(function()
+{
+	var scope,
+		tree,
+		noGlobals,
+		constantList,
+		lastWasVar,
+		ignoreSiblings,
+		isLoop,
+		output,
+		outputSize = 0,
+		maxSize = 2500;
+
+	var lang = {};
+
+	lang[ Token.NOT ] = '!';
+	lang[ Token.BITNOT ] = '~';
+	lang[ Token.POS ] = '+';
+	lang[ Token.NEG ] = '-';
+	lang[ Token.TYPEOF ] = 'typeof ';
+	lang[ Token.MUL ] = '*';
+	lang[ Token.DIV ] = '/';
+	lang[ Token.MOD ] = '%';
+	lang[ Token.ADD ] = '+';
+	lang[ Token.SUB ] = '-';
+	lang[ Token.RSH ] = '>>';
+	lang[ Token.LSH ] = '<<';
+	lang[ Token.URSH ] = '>>>';
+	lang[ Token.LT ] = '<';
+	lang[ Token.LE ] = '<=';
+	lang[ Token.GT ] = '>';
+	lang[ Token.GE ] = '>=';
+	lang[ Token.EQ ] = '==';
+	lang[ Token.NE ] = '!=';
+	lang[ Token.SHEQ ] = '===';
+	lang[ Token.SHNE ] = '!==';
+	lang[ Token.BITAND ] = '&';
+	lang[ Token.BITXOR ] = '^';
+	lang[ Token.BITOR ] = '|';
+	lang[ Token.AND ] = '&&';
+	lang[ Token.OR ] = '||';
+	lang[ Token.COMMA ] = ',';
+	lang[ Token.IN ] = ' in ';
+
+	// From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Operators:Operator_Precedence
+	var precedence = {};
+	precedence[ Token.DOT ] = 1;
+	precedence[ Token.INC ] = precedence[ Token.DEC ] = 3;
+	precedence[ Token.NOT ] = precedence[ Token.BITNOT ] = precedence[ Token.POS ] = precedence[ Token.NEG ] = precedence[ Token.TYPEOF ] = 4;
+	precedence[ Token.MUL ] = precedence[ Token.DIV ] = precedence[ Token.MOD ] = 5;
+	precedence[ Token.ADD ] = precedence[ Token.SUB ] = 6;
+	precedence[ Token.RSH ] = precedence[ Token.LSH ] = precedence[ Token.URSH ] = 7;
+	precedence[ Token.LT ] = precedence[ Token.LE ] = precedence[ Token.GT ] = precedence[ Token.GE ] = precedence[ Token.INSTANCEOF ] = precedence[ Token.IN ] = 8;
+	precedence[ Token.EQ ] = precedence[ Token.NE ] = precedence[ Token.SHEQ ] = precedence[ Token.SHNE ] = 9;
+	precedence[ Token.BITAND ] = 10;
+	precedence[ Token.BITXOR ] = 11;
+	precedence[ Token.BITOR ] = 12;
+	precedence[ Token.AND ] = 13;
+	precedence[ Token.OR ] = 14;
+	precedence[ Token.HOOK ] = 15;
+	precedence[ Token.SETNAME ] = precedence[ Token.SETPROP ] = precedence[ Token.SETELEM ] = 16;
+	precedence[ Token.COMMA ] = 17;
+
+	// Tokens having right-to-left associativity.
+	// From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Operators:Operator_Precedence
+	var associativityRTL = {};
+	associativityRTL[ Token.SETNAME ] =
+	associativityRTL[ Token.SETPROP ] =
+	associativityRTL[ Token.SETELEM ] =
+	associativityRTL[ Token.HOOK ] =
+	associativityRTL[ Token.TYPEOF ] =
+	associativityRTL[ Token.NEG ] =
+	associativityRTL[ Token.POS ] =
+	associativityRTL[ Token.NOT ] = 1;
+
+	var noAssociativity = {};
+	noAssociativity[ Token.AND ] =
+	noAssociativity[ Token.OR ] = 1;
+
+	//Other
+	precedence[ Token.FUNCTION ] = 100;
+
+	var noSpaceChars = {' ':1,';':1,',':1,'.':1,'(':1,')':1,'[':1,']':1,'{':1,'}':1,'?':1,':':1,'!':1,'=':1,'>':1,'<':1,'*':1,'/':1,'%':1,'+':1,'-':1,'&':1,'|':1,'^':1};
+	var out = function()
+	{
+		if ( out.checkSpace )
+		{
+			var first = String( arguments[ 0 ] );
+			first = first.substr( 0, 1 );
+
+			if (
+				( first == '+' && out.last == '+' ) ||
+				( first == '-' && out.last == '-' ) ||
+				( out.mayNeedSpace && !noSpaceChars[ first ] && !noSpaceChars[ out.last ] ) )
+			{
+				output.push( ' ' );
+				outputSize++;
+			}
+		}
+
+		var last = String( arguments[ arguments.length - 1 ] );
+		last = out.last = last.substr( last.length - 1 );
+		out.mayNeedSpace = ( last == '+' || last == '-' || !noSpaceChars[ last ] );
+
+		for ( var i = 0 ; i < arguments.length ; i++ )
+		{
+			var str = String( arguments[i] );
+			outputSize += str.length;
+			output.push( str );
+		}
+
+		if ( outputSize > maxSize && last == ';' )
+		{
+			output.push( '\n' );
+			outputSize = 0;
+		}
+	};
+
+	out.mayNeedSpace = false;
+	out.checkSpace = true;
+	out.size = 0;
+
+	var outString = function( str )
+	{
+		var value = String( str ),
+			singleParts = value.split( "'" ),
+			doubleParts = value.split( '"' );
+
+		value = value.replace( /[\b\t\n\v\f\r\\]/g, function( match )
+			{
+				var chars =
+				{
+					'\b' : '\\b',
+					'\t' : '\\t',
+					'\n' : '\\n',
+					'\v' : '\\v',
+					'\f' : '\\f',
+					'\r' : '\\r',
+					'\\' : '\\\\'
+				};
+
+				return chars[ match ];
+			} );
+
+		if ( doubleParts.length > singleParts.length )
+			out( "'", value.replace( /'/g, "\\'" ), "'" );
+		else if ( singleParts.length > 1 )
+			out( '"', value.replace( /"/g, '\\"' ), '"' );
+		else
+			out( "'", value, "'" );
+	};
+
+	var isReserved = function( word )
+	{
+		return !!isReserved.words[ word ];
+	};
+	// Taken from the ECMA-262.
+	isReserved.words = { 'break':1,'else':1,'new':1,'var':1,'case':1,'finally':1,'return':1,'void':1,'catch':1,'for':1,'switch':1,'while':1,'continue':1,'function':1,'this':1,'with':1,'default':1,'if':1,'throw':1,'delete':1,'in':1,'try':1,'do':1,'instanceof':1,'typeof':1,'abstract':1,'enum':1,'int':1,'short':1,'boolean':1,'export':1,'interface':1,'static':1,'byte':1,'extends':1,'long':1,'super':1,'char':1,'final':1,'native':1,'synchronized':1,'class':1,'float':1,'package':1,'throws':1,'const':1,'goto':1,'private':1,'transient':1,'debugger':1,'implements':1,'protected':1,'volatile':1,'double':1,'import':1,'public':1 };
+
+	var getPropParts = function( propNode, parts )
+	{
+		if ( !parts )
+			parts = [];
+
+		var owner		= propNode.getFirstChild(),
+			property	= propNode.getLastChild();
+
+		if ( owner )
+		{
+			if ( owner.getType() == Token.GETPROP )
+				getPropParts( owner, parts );
+			else
+				parts.push( owner );
+
+			parts.push( property );
+		}
+		else
+			parts.push( propNode );
+
+		return parts;
+	};
+
+	var writeNode = function( node, opt )
+	{
+		if ( !node )
+			return;
+
+		var type = node.getType();
+
+		if ( type != Token.VAR )
+			lastWasVar = false;
+
+		switch ( type )
+		{
+			case Token.SCRIPT :
+				scope = new CKPACKAGER.scope( node, scope );
+				scope.noRename = noGlobals;
+
+				tree = node;
+				writeChildren( node );
+				break;
+
+			case Token.NAME :
+			case Token.BINDNAME :
+				var name = node.getString();
+				if ( constantList[ name ] )
+					out( constantList[ name ] );
+				else
+					out( scope.getNewName( name ) );
+				break;
+
+			case Token.VAR :
+				if ( lastWasVar )
+					out( ',' );
+				else
+					out( 'var ' );
+
+				var child = node.getFirstChild();
+				while ( child )
+				{
+					var name = child.getString();
+
+					out( scope.getNewName( name, true ) );
+
+					if ( child.getFirstChild() )
+					{
+						out( '=' );
+						writeChildren( child );
+					}
+
+					scope.declareName( name );
+
+					child = child.getNext();
+
+					if ( child )
+						out( ',' );
+				}
+
+				lastWasVar = ( node.getNext() && node.getNext().getType() == Token.VAR );
+
+				if ( !lastWasVar && ( !opt || !opt.noSemiColon ) )
+					out( ';' );
+
+				break;
+
+			case Token.SETNAME :
+				var name = node.getFirstChild().getString();
+
+				writeNode( node.getFirstChild() );
+
+				var value = node.getLastChild();
+
+				switch ( value.getType() )
+				{
+					case Token.MUL :
+					case Token.DIV :
+					case Token.MOD :
+					case Token.ADD :
+					case Token.SUB :
+					case Token.BITAND :
+					case Token.BITXOR :
+					case Token.BITOR :
+					case Token.LSH :
+					case Token.RSH :
+					case Token.URSH :
+
+						if ( ( value.getFirstChild().getType() == Token.NAME && value.getFirstChild().getString() == name ) )
+						{
+							out( lang[ value.getType() ], '=' );
+							writeNode( value.getLastChild() );
+							break;
+						}
+
+					default :
+						out( '=' );
+						writeNode( value );
+						break;
+				}
+
+				break;
+
+			case Token.NEW :
+				var child = node.getFirstChild(),
+					isArray,
+					isObject;
+
+				if ( child.getType() == Token.NAME )
+				{
+					if ( child.getString() == 'Array' && ( !child.getNext() || child.getNext().getType() != Token.NUMBER || child.getNext().getNext() ) )
+					{
+						out( '[' );
+						isArray = true;
+					}
+					else if ( child.getString() == 'Object' && !child.getNext() )
+					{
+						out( '{' );
+						isObject = true;
+					}
+				}
+
+				if ( !isArray && !isObject )
+				{
+					out( 'new ' );
+					writeNode( child );
+					out( '(' );
+				}
+
+				child = child.getNext();
+
+				while ( child )
+				{
+					if ( !writeNode( child ) )
+						break;
+
+					child = child.getNext();
+
+					if ( child )
+						out( ',' );
+				}
+
+				if ( isArray )
+					out( ']' );
+				else if ( isObject )
+					out( '}' );
+				else
+					out( ')' );
+				break;
+
+			case Token.FUNCTION :
+				var name = node.getString();
+
+				out( 'function' );
+
+				if ( name.length() )
+					out( ' ', scope.getNewName( name, true ) );
+
+				var currentTree = tree,
+					fnIndex = node.getExistingIntProp( Node.FUNCTION_PROP ),
+					fn = tree.getFunctionNode(fnIndex);
+
+				scope = new CKPACKAGER.scope( fn, scope );
+
+				out( '(' );
+
+				for ( var i = 0, len = scope.args.length ; i < len ; i++ )
+				{
+					if ( i > 0 )
+						out( ',' );
+					out( scope.getNewName( scope.args[ i ] ) );
+				}
+
+				out( '){' );
+
+				// Initialize the "this" replacement. Changes here must be
+				// reflected in the Token.THIS case.
+				if ( !scope.functionCount && scope.thisCount > 3 )
+					out( 'var ', scope.getNewName( 'this' ), '=this;' );
+
+				tree = fn;
+				writeNode( fn.getFirstChild(), { isFunction : true } );
+
+				scope = scope.parent;
+				tree = currentTree;
+
+				out( '}' );
+
+				if ( name.length() )
+					out( ';' );
+				break;
+
+			case Token.CALL :
+				var child = node.getFirstChild(),
+					childType = child.getType(),
+					isFunctionCall = ( childType == Token.FUNCTION || childType == Token.SETPROP || childType == Token.SETELEM );
+
+				if ( childType == Token.NAME && child.getString() == 'PACKAGER_RENAME' )
+				{
+					var renamed = child.getNext(),
+						renamedRef = '',
+						parts = getPropParts( renamed );
+
+					for ( var i = 0 ; i < parts.length ; i++ )
+					{
+						if ( i > 0 )
+							renamedRef += '.';
+						renamedRef += parts[ i ].getString();
+					}
+
+					// print( '[' + renamedRef + ']' );
+
+					out( 'var ', scope.addRenamedRef( renamedRef ), '=' );
+					writeNode( renamed );
+
+					scope.declareName( renamedRef );
+
+					break;
+				}
+
+				if ( isFunctionCall )
+					out( '(' );
+
+				writeNode( child );
+
+				if ( isFunctionCall )
+					out( ')' );
+
+				out( '(' );
+
+				var param = child.getNext();
+				while( param )
+				{
+					if ( !writeNode( param ) )
+						break;
+
+					param = param.getNext();
+
+					if ( param )
+						out( ',' );
+				}
+
+				out( ')' );
+				break;
+
+			case Token.LOCAL_BLOCK :
+				writeChildren( node );
+				break;
+
+			case Token.BLOCK :
+				var child = node.getFirstChild(),
+					isLoop = opt && opt.isLoop,
+					isFunction = opt && opt.isFunction,
+					ignoreChildren = false;
+
+				if ( !child )
+					break;
+
+				if ( child.getType() == Token.IFNE )
+				{
+					writeNode( child );
+					break;
+				}
+				else if ( child.getType() == Token.SWITCH )
+				{
+					out( 'switch(' );
+					writeNode( child.getFirstChild() );
+					out( '){' );
+
+					var caseChild = child.getFirstChild().getNext();
+					while( caseChild )
+					{
+						writeNode( caseChild );
+						caseChild = caseChild.getNext();
+					}
+
+					caseChild = child.getNext().target.getNext();
+					if ( caseChild )
+					{
+						out( 'default:' );
+						writeChildren( caseChild );
+					}
+
+					out( '}' );
+
+					break;
+				}
+				else if ( child.getType() == Token.ENTERWITH )
+				{
+					out( 'with(' );
+					writeNode( child.getFirstChild() );
+					out( '){' );
+					writeChildren( child.getNext() );
+					out( '}' );
+					break;
+				}
+
+				while( child )
+				{
+					if ( child.getType() == Token.CONTINUE )
+					{
+						if ( !isLoop )
+							writeNode( child );
+						ignoreChildren = true;
+					}
+					else if ( child.getType() == Token.RETURN )
+					{
+						if ( !isFunction || child.getFirstChild() )
+							writeNode( child );
+						ignoreChildren = true;
+					}
+
+					// All children are ignored, except functions.
+					if ( !ignoreChildren || child.getType() == Token.FUNCTION )
+					{
+						if ( !writeNode( child ) )
+							break;
+					}
+
+					child = child.getNext();
+				}
+
+				break;
+
+			case Token.CASE :
+				out( 'case' );
+				writeNode( node.getFirstChild() );
+				out( ':' );
+				writeChildren( node.target.getNext() );
+				break;
+
+			case Token.BREAK :
+				out( 'break;' )
+				break;
+
+			case Token.LOOP :
+				var child = node.getFirstChild(),
+					block,
+					isDo = false;
+
+				if ( child.getType() == Token.GOTO )	// while (x) && for (;[x];[x])
+				{
+					// The block is located two nodes after it.
+					block = child.getNext().getNext();
+
+					// The increment expression is two steps from the block, if available.
+					var incrementExpression = block.getNext().getNext();
+
+					var expression = child.target.getNext();
+
+					if ( incrementExpression.getType() == Token.EXPR_VOID )	// for
+					{
+						out( 'for(;' );
+
+						if ( expression.getFirstChild().getType() != Token.TRUE )
+							writeNode( expression, { noSemiColon : true } );
+
+						out( ';' );
+
+						writeNode( incrementExpression, { noSemiColon : true } );
+
+						out( ')' );
+					}
+					else
+					{
+						if ( expression.getFirstChild().getType() == Token.TRUE )
+							out( 'for(;;)' );
+						else
+						{
+							out( 'while(' );
+							writeNode( expression );
+							out( ')' );
+						}
+					}
+				}
+				else if ( child.getType() == Token.TARGET )		// do { ... } while()
+				{
+					isDo = true;
+
+					out( 'do' );
+					block = child.getNext();
+				}
+				else	// for (x;[x];[x]) / for ( x in o )
+				{
+					out( 'for(' );
+
+					var hasName = false;
+
+					if ( child.getType() != Token.ENUM_INIT_KEYS )
+					{
+						writeNode( child, { noSemiColon : true } );
+
+						child = child.getNext();
+						hasName = true;
+					}
+
+					if ( child.getType() == Token.ENUM_INIT_KEYS )
+					{
+						block = child.getNext().getNext().getNext();
+
+						// Gets the BINDNAME token.
+						if ( !hasName )
+							writeNode( block.getFirstChild().getFirstChild().getFirstChild() );
+
+						writeNode( child );
+
+						block = block.getFirstChild().getNext();
+					}
+
+					if ( child.getType() == Token.GOTO )
+					{
+						out( ';' );
+						writeNode( child.target.getNext(), { noSemiColon : true } );
+						out( ';' );
+
+						block = child.getNext().getNext();
+
+						// The increment expression is two steps from the block, if available.
+						var incrementExpression = block.getNext().getNext();
+
+						if ( incrementExpression.getType() == Token.EXPR_VOID )
+						{
+							writeNode( incrementExpression, { noSemiColon : true } );
+						}
+					}
+
+					out( ')' );
+				}
+
+				var hasCurly = ( !block || !block.getFirstChild() || !!block.getFirstChild().getNext() );
+
+				if ( hasCurly )
+					out( '{' );
+
+				writeNode( block, { isLoop : true } );
+
+				if ( hasCurly )
+					out( '}' );
+
+				if ( isDo )
+				{
+					out( 'while(' );
+					writeNode( block.getNext().getNext() );
+					out( ')' );
+				}
+
+				break;
+
+			case Token.ENUM_INIT_KEYS :
+				out( ' in ' );
+				writeNode( node.getFirstChild() );
+				break;
+
+			case Token.EXPR_RESULT :
+			case Token.EXPR_VOID :
+				writeChildren( node );
+
+				if ( !opt || !opt.noSemiColon )
+					out( ';' );
+
+				break;
+
+			case Token.GETPROP :
+				var child = node.getFirstChild(),
+					name = child.getNext().getString(),
+					finalName = name;
+
+				// Get all parts that compose this node (part1.part2.partN).
+				var parts = getPropParts( node ),
+					startAt = 0,
+					names = [];
+
+				// Get all part names form the start.
+				for ( var i = 0 ; i < parts.length ; i++ )
+				{
+					var part = parts[ i ],
+						partType = part.getType();
+					if ( partType == Token.NAME || partType == Token.STRING )
+						names.push( String( part.getString() ) );
+					else
+						break;
+				}
+
+				// Check if the name parts are to be replaced.
+				for ( var i = names.length ; i > 0 ; i-- )
+				{
+					// Build the full name (e.g. Obj.prop1.prop2).
+					var fullName = i == 1 ? names[ 0 ] : names.slice( 0, i ).join( '.' );
+
+					// If we have a property composed by names only.
+					if ( i == parts.length && typeof constantList[ fullName ] != 'undefined' )
+					{
+						out( constantList[ fullName ] )
+						return true;
+					}
+
+					var newName = scope.getNewName( fullName );
+
+					// If a new names is available.
+					if ( newName != fullName )
+					{
+						// Send the new name.
+						out( newName );
+
+						// Removed the replaced names from the parts list.
+						startAt = i;
+						break;
+					}
+				}
+
+				for ( var i = startAt ; i < parts.length ; i++ )
+				{
+					var part = parts[ i ],
+						partType = part.getType(),
+						parenthesis = !!precedence[ partType ];
+
+					if ( i > 0 )
+						out( '.' );
+
+					if ( partType == Token.STRING )
+						out( part.getString() );
+					else
+					{
+						if ( parenthesis )
+							out( '(' );
+
+						writeNode( part );
+
+						if ( parenthesis )
+							out( ')' );
+					}
+				}
+
+				break;
+
+			case Token.GETELEM :
+			case Token.DELPROP :
+			case Token.SETPROP :
+			case Token.SETELEM :
+			case Token.SETPROP_OP :
+			case Token.SETELEM_OP :
+				var owner = node.getFirstChild(),
+					prop = owner.getNext(),
+					ownerParenthesis = !!precedence[ owner.getType() ];
+
+				if ( type == Token.DELPROP )
+					out( 'delete ' );
+
+				if ( ownerParenthesis )
+					out( '(' );
+
+				writeNode( owner );
+
+				if ( ownerParenthesis )
+					out( ')' );
+
+				if ( prop.getType() == Token.STRING && !isReserved( prop.getString() ) && /^[a-zA-Z$_][\w$_]*$/.test( prop.getString() ) )
+				{
+					out( '.' );
+					out( prop.getString() );
+				}
+				else
+				{
+					out( '[' );
+					writeNode( prop );
+					out( ']' );
+				}
+
+				if ( type == Token.SETPROP || type == Token.SETELEM )
+				{
+					out( '=' );
+					writeNode( node.getLastChild() );
+				}
+
+				if ( type == Token.SETPROP_OP || type == Token.SETELEM_OP )
+				{
+					out( lang[ node.getLastChild().getType() ] );
+					out( '=' );
+					writeChildren( node.getLastChild() );
+				}
+				break;
+
+			case Token.IFNE :
+				out( 'if(' );
+				writeNode( node.getFirstChild() );
+				out( ')' );
+
+				var block = node.getNext(),
+					hasCurly = true;
+
+				hasCurly = ( !block || ( block.getType() == Token.BLOCK && ( !block.getFirstChild() || block.getFirstChild().getNext() ) ) );
+
+				if ( hasCurly )
+					out( '{' );
+
+				writeNode( block );
+
+				if ( hasCurly )
+					out( '}' );
+
+				block = block.getNext();
+				if ( block.getType() == Token.GOTO )
+				{
+					out( 'else' );
+					block = block.getNext().getNext();
+
+					hasCurly = ( !block || ( block.getType() == Token.BLOCK && ( !block.getFirstChild() || block.getFirstChild().getType() != Token.IFNE && block.getFirstChild().getNext() ) ) );
+
+					if ( hasCurly )
+						out( '{' );
+
+					writeNode( block );
+
+					if ( hasCurly )
+						out( '}' );
+				}
+
+				break;
+
+			case Token.IFEQ :
+				writeNode( node.getFirstChild() );
+				break;
+
+			case Token.STRING :
+				outString( node.getString() );
+				break;
+
+			case Token.NUMBER :
+				out( node.getDouble() );
+				break;
+
+			case Token.TRUE :
+				out( 'true' );
+				break;
+
+			case Token.FALSE :
+				out( 'false' );
+				break;
+
+			case Token.ARRAYLIT :
+				out( '[' );
+				var child = node.getFirstChild();
+				while( child )
+				{
+					if ( !writeNode( child ) )
+						break;
+
+					child = child.getNext();
+
+					if ( child )
+						out( ',' );
+				}
+				out( ']' );
+				break;
+
+			case Token.OBJECTLIT :
+				out( '{' );
+
+				var ids = node.getProp(Node.OBJECT_IDS_PROP),
+					counter = 0;
+
+				var child = node.getFirstChild();
+				while( child )
+				{
+					var id = String( ids[ counter++ ] );
+
+					if ( isReserved( id ) || !/^(?:(?:[a-zA-Z$_][\w$_]*)|(?:\d+))$/.test( id ) )
+						outString( id );
+					else
+						out( id );
+
+					out( ':' );
+					if ( !writeNode( child ) )
+						break;
+
+					child = child.getNext();
+
+					if ( child )
+						out( ',' );
+				}
+
+				out( '}' );
+				break;
+
+			case Token.THIS :
+				// Replace "this" with a shorter name. Changes here must be
+				// reflected in the Token.FUNCTION case, which initialized the
+				// replacement variable.
+				if ( !scope.functionCount && scope.thisCount > 3 )
+					out( scope.getNewName( 'this' ) );
+				else
+					out( 'this' );
+				break;
+
+			case Token.NULL :
+				out( 'null' );
+				break;
+
+			case Token.CONTINUE :
+				out ( 'continue', ';' );
+				break;
+
+			case Token.RETURN :
+				var value = node.getFirstChild();
+
+				out( 'return' );
+
+				if ( value )
+					writeNode( value );
+
+				out( ';' );
+
+				break;
+
+			case Token.HOOK :
+				writeNode( node = node.getFirstChild() );
+				out( '?' );
+				writeNode( node = node.getNext() );
+				out( ':' );
+				writeNode( node.getNext() );
+				break;
+
+			case Token.REGEXP :
+				out( '/',
+					tree.getRegexpString( node.getExistingIntProp( Node.REGEXP_PROP ) ),
+					'/',
+					tree.getRegexpFlags( node.getExistingIntProp( Node.REGEXP_PROP ) ) );
+
+				break;
+
+			case Token.TRY :
+				// Get the "try" body.
+				var child = node.getFirstChild(),
+					finallyNode;
+
+				out( 'try{' );
+				writeNode( child );
+				out( '}' );
+
+				child = child.getNext();
+
+				// If a GOTO node is following it, then we have a "catch" block.
+				if ( child.getType() == Token.GOTO )
+				{
+					// The catch definition is 2 steps later (LOCAL_BLOCK node).
+					child = child.getNext().getNext();
+
+					var catchScopeVar = child.getFirstChild().getFirstChild().getString(),
+						overrideLocal = !!scope.names[ catchScopeVar ];
+
+					if ( !overrideLocal )
+						scope.names[ catchScopeVar ] = scope.declaredNames[ catchScopeVar ] = scope.getNewName( catchScopeVar, true, true );
+
+					out( 'catch(' );
+					// Send the catch scope (CATCH_SCOPE).
+					writeNode( child.getFirstChild().getFirstChild() );
+					out( '){' );
+
+					// Because of the scope, the catch block is in a much deeper node.
+					writeNode( child.getFirstChild().getNext().getFirstChild().getNext().getFirstChild() );
+
+					if ( !overrideLocal )
+						scope.names[ catchScopeVar ] = scope.declaredNames[ catchScopeVar ] = null;
+
+					out( '}' );
+				}
+
+				while ( child )
+				{
+					if ( child.getType() == Token.FINALLY )
+					{
+						out( 'finally{' );
+						writeNode( child.getFirstChild() );
+						out( '}' );
+						break;
+					}
+					child = child.getNext();
+				}
+
+				break;
+
+			case Token.THROW :
+				out( 'throw ' );
+				writeNode( node.getFirstChild() );
+				out( ';' );
+				break;
+
+			case Token.VOID :
+				out( 'void(' );
+				writeChildren( node );
+				out( ')' );
+				break;
+
+			case Token.INSTANCEOF :
+				writeNode( node.getFirstChild() );
+				out( ' instanceof ' );
+				writeNode( node.getLastChild() );
+				break;
+
+			case Token.TYPEOFNAME :
+				out( 'typeof ', scope.getNewName( node.getString() ) );
+				break;
+
+			case Token.TYPEOF :
+			case Token.NOT :
+			case Token.BITNOT :
+			case Token.POS :
+			case Token.NEG :
+				var child = node.getFirstChild();
+				var parenthesis = ( precedence[ type ] < ( precedence[ child.getType() ] || 0 ) );
+
+				out( lang[ type ] );
+
+				if ( parenthesis )
+					out( '(' );
+
+				writeNode( child );
+
+				if ( parenthesis )
+					out( ')' );
+
+				break;
+
+			case Token.MUL :
+			case Token.DIV :
+			case Token.MOD :
+			case Token.ADD :
+			case Token.SUB :
+			case Token.RSH :
+			case Token.LSH :
+			case Token.URSH :
+			case Token.LT :
+			case Token.LE :
+			case Token.GT :
+			case Token.GE :
+			case Token.EQ :
+			case Token.NE :
+			case Token.SHEQ :
+			case Token.SHNE :
+			case Token.BITAND :
+			case Token.BITXOR :
+			case Token.BITOR :
+			case Token.AND :
+			case Token.OR :
+			case Token.COMMA :
+			case Token.IN :
+				var left = node.getFirstChild(),
+					right = node.getLastChild(),
+					parenthesis;
+
+				// Check the operator precedence, to properly isolate things on
+				// parenthesis.
+				parenthesis = ( precedence[ type ] < ( precedence[ left.getType() ] || 0 ) );
+
+				if ( !parenthesis && associativityRTL[ type ] )
+					parenthesis = ( precedence[ type ] == ( precedence[ left.getType() ] || 0 ) );
+
+				if ( parenthesis )
+					out( '(' );
+
+				// The left side.
+				writeNode( left );
+
+				if ( parenthesis )
+					out( ')' );
+
+				// The operator.
+				out( lang[ type ] );
+
+				// The right side.
+				if ( !parenthesis )
+					parenthesis = ( precedence[ type ] < ( precedence[ right.getType() ] || 0 ) );
+
+				if ( !parenthesis && !associativityRTL[ type ] && !noAssociativity[ type ] )
+					parenthesis = ( precedence[ type ] == ( precedence[ right.getType() ] || 0 ) );
+
+				if ( parenthesis )
+					out( '(' );
+
+				writeNode( right );
+
+				if ( parenthesis )
+					out( ')' );
+
+				break;
+
+			case Token.INC :
+			case Token.DEC :
+				var post = ( node.getExistingIntProp(Node.INCRDECR_PROP) & Node.POST_FLAG ) != 0,
+					str = type == Token.INC ? '++' : '--';
+
+				if ( !post )
+					out( str );
+
+				out.checkSpace = false;
+
+				writeNode( node.getFirstChild() );
+
+				if ( post )
+					out( str );
+
+				out.checkSpace = true;
+				break;
+
+			case Token.GOTO:
+			case Token.EMPTY:
+			case Token.LEAVEWITH:		// TRY
+			case Token.USE_STACK:		// SETPROP_OP
+				break;
+
+			default :
+				print( 'WARNING: Unknown token ' + GetTokenName( type ) );
+				break;
+		}
+
+		return true;
+	};
+
+	var writeChildren = function( node )
+	{
+		node = node.getFirstChild()
+
+		while ( node )
+		{
+			if ( !writeNode( node ) )
+				break;
+
+			node = node.getNext();
+		}
+	};
+
+	var regexLib =
+	{
+		packagerRemove : Pattern.compile( '(?m-s:^.*?@Packager\\.Remove\\.Start).*?(?m-s:@Packager\\.Remove\\.End.*?$)', Pattern.DOTALL ),
+		packagerRemoveLine : Pattern.compile( '^.*@Packager\\.RemoveLine.*$', Pattern.MULTILINE ),
+		packagerRename : Pattern.compile( '^.*PACKAGER_RENAME\\(\\s*([^\\s]+).*$', Pattern.MULTILINE )
+	};
+
+	var preProcess = function( script )
+	{
+		// Protect IE conditional comments. We are doing it in a way that works
+		// for CKEditor, but this is not a generic solution.
+		script = script.replace( /\/\*@([\s\S]+?)@\*\/(?:)/g, function( match, contents )
+			{
+				return 'CKPACKAGER_COND_COMMENT("' + encodeURIComponent( contents ) + '")||'
+			});
+
+		// The Java regex here is much faster.
+		script = String( regexLib.packagerRemove.matcher( script ).replaceAll( '' ) );
+//		script = script.replace( /[^\r\n]*@Packager\.Remove\.Start[\s\S]*?@Packager\.Remove\.End[^\r\n]*/g, '' );
+
+		// The Java regex makes no much difference here instead, but for
+		// consistense let's use it again.
+		script = String( regexLib.packagerRemoveLine.matcher( script ).replaceAll( '' ) );
+//		script = script.replace( /^.*@Packager\.RemoveLine.*/gm, '' );
+
+		script = String( regexLib.packagerRename.matcher( script ).replaceAll( 'PACKAGER_RENAME($1);' ) );
+
+		return script;
+	};
+
+	var postProcess = function( script )
+	{
+		script = script.replace( /CKPACKAGER_COND_COMMENT\(["']([\s\S]+?)["']\)\|\|/g, function( match, contents )
+			{
+				return '/*@' + decodeURIComponent( contents ) + '@*/'
+			});
+
+		return script;
+	};
+
+	CKPACKAGER.scriptCompressor =
+	{
+		compress : function( script, renameGlobals, constants, noCheck, wrap )
+		{
+			script = preProcess( script );
+
+			// Reset.
+			scope = null;
+			tree = null;
+			lastWasVar = false;
+			ignoreSiblings = false;
+			isLoop = false;
+
+			if ( wrap )
+				script = '(function(){' + script + '})();';
+
+			var compilerEnv = new CompilerEnvirons(),
+				errorReporter = compilerEnv.getErrorReporter(),
+				parser = new Parser(compilerEnv, errorReporter),
+				scriptNode = parser.parse( script, null, 1 );
+
+			noGlobals = !wrap && !renameGlobals;
+			constantList = constants || {};
+
+			// Reset the output.
+			output = [];
+			outputSize = 0;
+
+			// Start writting the "script" node.
+			writeNode( scriptNode );
+
+			var compressed = output.join( '' );
+
+			compressed = postProcess( compressed );
+
+			/*
+			print( '' );
+			print( compressed );
+			*/
+
+			// Try to parse the compressed results. If the resulting script is
+			// not valid, an error will be thrown here.
+
+			if ( !noCheck )
+			{
+				print( '' );
+				print( '    Checking compressed code...' );
+				parser.parse( compressed/*.replace( /;/g, ';\n' )*/, null, 1 );
+			}
+
+			return compressed;
+		}
+	}
+})();
Index: /CKPackager/trunk/_source/includes/token.js
===================================================================
--- /CKPackager/trunk/_source/includes/token.js	(revision 3145)
+++ /CKPackager/trunk/_source/includes/token.js	(revision 3145)
@@ -0,0 +1,264 @@
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+function GetTokenName( token )
+{
+    switch ( token )
+    {
+      case Token.ERROR:           return "ERROR";
+      case Token.EOF:             return "EOF";
+      case Token.EOL:             return "EOL";
+      case Token.ENTERWITH:       return "ENTERWITH";
+      case Token.LEAVEWITH:       return "LEAVEWITH";
+      case Token.RETURN:          return "RETURN";
+      case Token.GOTO:            return "GOTO";
+      case Token.IFEQ:            return "IFEQ";
+      case Token.IFNE:            return "IFNE";
+      case Token.SETNAME:         return "SETNAME";
+      case Token.BITOR:           return "BITOR";
+      case Token.BITXOR:          return "BITXOR";
+      case Token.BITAND:          return "BITAND";
+      case Token.EQ:              return "EQ";
+      case Token.NE:              return "NE";
+      case Token.LT:              return "LT";
+      case Token.LE:              return "LE";
+      case Token.GT:              return "GT";
+      case Token.GE:              return "GE";
+      case Token.LSH:             return "LSH";
+      case Token.RSH:             return "RSH";
+      case Token.URSH:            return "URSH";
+      case Token.ADD:             return "ADD";
+      case Token.SUB:             return "SUB";
+      case Token.MUL:             return "MUL";
+      case Token.DIV:             return "DIV";
+      case Token.MOD:             return "MOD";
+      case Token.NOT:             return "NOT";
+      case Token.BITNOT:          return "BITNOT";
+      case Token.POS:             return "POS";
+      case Token.NEG:             return "NEG";
+      case Token.NEW:             return "NEW";
+      case Token.DELPROP:         return "DELPROP";
+      case Token.TYPEOF:          return "TYPEOF";
+      case Token.GETPROP:         return "GETPROP";
+      case Token.GETPROPNOWARN:   return "GETPROPNOWARN";
+      case Token.SETPROP:         return "SETPROP";
+      case Token.GETELEM:         return "GETELEM";
+      case Token.SETELEM:         return "SETELEM";
+      case Token.CALL:            return "CALL";
+      case Token.NAME:            return "NAME";
+      case Token.NUMBER:          return "NUMBER";
+      case Token.STRING:          return "STRING";
+      case Token.NULL:            return "NULL";
+      case Token.THIS:            return "THIS";
+      case Token.FALSE:           return "FALSE";
+      case Token.TRUE:            return "TRUE";
+      case Token.SHEQ:            return "SHEQ";
+      case Token.SHNE:            return "SHNE";
+      case Token.REGEXP:          return "REGEXP";
+      case Token.BINDNAME:        return "BINDNAME";
+      case Token.THROW:           return "THROW";
+      case Token.RETHROW:         return "RETHROW";
+      case Token.IN:              return "IN";
+      case Token.INSTANCEOF:      return "INSTANCEOF";
+      case Token.LOCAL_LOAD:      return "LOCAL_LOAD";
+      case Token.GETVAR:          return "GETVAR";
+      case Token.SETVAR:          return "SETVAR";
+      case Token.CATCH_SCOPE:     return "CATCH_SCOPE";
+      case Token.ENUM_INIT_KEYS:  return "ENUM_INIT_KEYS";
+      case Token.ENUM_INIT_VALUES:return "ENUM_INIT_VALUES";
+      case Token.ENUM_INIT_ARRAY: return "ENUM_INIT_ARRAY";
+      case Token.ENUM_NEXT:       return "ENUM_NEXT";
+      case Token.ENUM_ID:         return "ENUM_ID";
+      case Token.THISFN:          return "THISFN";
+      case Token.RETURN_RESULT:   return "RETURN_RESULT";
+      case Token.ARRAYLIT:        return "ARRAYLIT";
+      case Token.OBJECTLIT:       return "OBJECTLIT";
+      case Token.GET_REF:         return "GET_REF";
+      case Token.SET_REF:         return "SET_REF";
+      case Token.DEL_REF:         return "DEL_REF";
+      case Token.REF_CALL:        return "REF_CALL";
+      case Token.REF_SPECIAL:     return "REF_SPECIAL";
+      case Token.DEFAULTNAMESPACE:return "DEFAULTNAMESPACE";
+      case Token.ESCXMLTEXT:      return "ESCXMLTEXT";
+      case Token.ESCXMLATTR:      return "ESCXMLATTR";
+      case Token.REF_MEMBER:      return "REF_MEMBER";
+      case Token.REF_NS_MEMBER:   return "REF_NS_MEMBER";
+      case Token.REF_NAME:        return "REF_NAME";
+      case Token.REF_NS_NAME:     return "REF_NS_NAME";
+      case Token.TRY:             return "TRY";
+      case Token.SEMI:            return "SEMI";
+      case Token.LB:              return "LB";
+      case Token.RB:              return "RB";
+      case Token.LC:              return "LC";
+      case Token.RC:              return "RC";
+      case Token.LP:              return "LP";
+      case Token.RP:              return "RP";
+      case Token.COMMA:           return "COMMA";
+      case Token.ASSIGN:          return "ASSIGN";
+      case Token.ASSIGN_BITOR:    return "ASSIGN_BITOR";
+      case Token.ASSIGN_BITXOR:   return "ASSIGN_BITXOR";
+      case Token.ASSIGN_BITAND:   return "ASSIGN_BITAND";
+      case Token.ASSIGN_LSH:      return "ASSIGN_LSH";
+      case Token.ASSIGN_RSH:      return "ASSIGN_RSH";
+      case Token.ASSIGN_URSH:     return "ASSIGN_URSH";
+      case Token.ASSIGN_ADD:      return "ASSIGN_ADD";
+      case Token.ASSIGN_SUB:      return "ASSIGN_SUB";
+      case Token.ASSIGN_MUL:      return "ASSIGN_MUL";
+      case Token.ASSIGN_DIV:      return "ASSIGN_DIV";
+      case Token.ASSIGN_MOD:      return "ASSIGN_MOD";
+      case Token.HOOK:            return "HOOK";
+      case Token.COLON:           return "COLON";
+      case Token.OR:              return "OR";
+      case Token.AND:             return "AND";
+      case Token.INC:             return "INC";
+      case Token.DEC:             return "DEC";
+      case Token.DOT:             return "DOT";
+      case Token.FUNCTION:        return "FUNCTION";
+      case Token.EXPORT:          return "EXPORT";
+      case Token.IMPORT:          return "IMPORT";
+      case Token.IF:              return "IF";
+      case Token.ELSE:            return "ELSE";
+      case Token.SWITCH:          return "SWITCH";
+      case Token.CASE:            return "CASE";
+      case Token.DEFAULT:         return "DEFAULT";
+      case Token.WHILE:           return "WHILE";
+      case Token.DO:              return "DO";
+      case Token.FOR:             return "FOR";
+      case Token.BREAK:           return "BREAK";
+      case Token.CONTINUE:        return "CONTINUE";
+      case Token.VAR:             return "VAR";
+      case Token.WITH:            return "WITH";
+      case Token.CATCH:           return "CATCH";
+      case Token.FINALLY:         return "FINALLY";
+      case Token.VOID:            return "VOID";
+      case Token.RESERVED:        return "RESERVED";
+      case Token.EMPTY:           return "EMPTY";
+      case Token.BLOCK:           return "BLOCK";
+      case Token.LABEL:           return "LABEL";
+      case Token.TARGET:          return "TARGET";
+      case Token.LOOP:            return "LOOP";
+      case Token.EXPR_VOID:       return "EXPR_VOID";
+      case Token.EXPR_RESULT:     return "EXPR_RESULT";
+      case Token.JSR:             return "JSR";
+      case Token.SCRIPT:          return "SCRIPT";
+      case Token.TYPEOFNAME:      return "TYPEOFNAME";
+      case Token.USE_STACK:       return "USE_STACK";
+      case Token.SETPROP_OP:      return "SETPROP_OP";
+      case Token.SETELEM_OP:      return "SETELEM_OP";
+      case Token.LOCAL_BLOCK:     return "LOCAL_BLOCK";
+      case Token.SET_REF_OP:      return "SET_REF_OP";
+      case Token.DOTDOT:          return "DOTDOT";
+      case Token.COLONCOLON:      return "COLONCOLON";
+      case Token.XML:             return "XML";
+      case Token.DOTQUERY:        return "DOTQUERY";
+      case Token.XMLATTR:         return "XMLATTR";
+      case Token.XMLEND:          return "XMLEND";
+      case Token.TO_OBJECT:       return "TO_OBJECT";
+      case Token.TO_DOUBLE:       return "TO_DOUBLE";
+      case Token.GET:             return "GET";
+      case Token.SET:             return "SET";
+      case Token.LET:             return "LET";
+      case Token.YIELD:           return "YIELD";
+      case Token.CONST:           return "CONST";
+      case Token.SETCONST:        return "SETCONST";
+      case Token.ARRAYCOMP:       return "ARRAYCOMP";
+      case Token.WITHEXPR:        return "WITHEXPR";
+      case Token.LETEXPR:         return "LETEXPR";
+      case Token.DEBUGGER:        return "DEBUGGER";
+    }
+
+    return '??? ' + token;
+}
+
+/*
+	The following tokens are not managed by the compressor.
+
+          case ERROR:           return "ERROR";
+          case EOF:             return "EOF";
+          case EOL:             return "EOL";
+          case GETPROPNOWARN:   return "GETPROPNOWARN";
+          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 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 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 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 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 COLON:           return "COLON";
+          case DOT:             return "DOT";
+          case EXPORT:          return "EXPORT";
+          case IMPORT:          return "IMPORT";
+          case IF:              return "IF";
+          case ELSE:            return "ELSE";
+          case DEFAULT:         return "DEFAULT";
+          case WHILE:           return "WHILE";
+          case DO:              return "DO";
+          case FOR:             return "FOR";
+          case WITH:            return "WITH";
+          case RESERVED:        return "RESERVED";
+          case EMPTY:           return "EMPTY";
+          case LABEL:           return "LABEL";
+          case JSR:             return "JSR";
+          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";
+*/
Index: Packager/trunk/ckpackager.js
===================================================================
--- /CKPackager/trunk/ckpackager.js	(revision 3144)
+++ 	(revision )
@@ -1,82 +1,0 @@
-/*
-Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.html or http://ckeditor.com/license
-*/
-
-importPackage( org.mozilla.javascript );
-
-importClass( java.lang.System );
-importClass( java.io.File );
-importClass( java.io.BufferedWriter );
-importClass( java.io.FileWriter );
-
-var jarPath = JavaAdapter(org.mozilla.javascript.Parser)["class"].getResource("/org/mozilla/javascript").toString();
-var packagerPath = jarPath.replaceFirst( "^jar:", '' ).replaceFirst( "\/js\.jar\!\/org\/mozilla\/javascript$", '');
-
-load( packagerPath + "/includes/ckpackager.js" );
-
-function error( msg )
-{
-	print( msg );
-	print( '' );
-	quit();
-}
-
-if ( arguments[0] == '-dump' )
-{
-	CKPACKAGER.loadCode( 'includes/parser.js' );
-	CKPACKAGER.parser.dumpThree( CKPACKAGER.tools.readFile( arguments[1] ) );
-	quit();
-}
-else if ( arguments[0] == '-compress' )
-{
-	CKPACKAGER.loadCode( 'includes/scriptcompressor.js' );
-
-	var compressed = CKPACKAGER.scriptCompressor.compress( CKPACKAGER.tools.readFile( arguments[1] ) );
-
-	if ( arguments[2] )
-	{
-		var out = new BufferedWriter( new FileWriter( arguments[2] ) );
-		out.write( compressed );
-		out.close();
-	}
-
-	print( compressed );
-	quit();
-}
-else if ( arguments[0] == '-test' )
-{
-	CKPACKAGER.loadCode( 'test/test.js' );
-	quit();
-}
-
-CKPACKAGER.packFile = arguments[0];
-
-if ( !CKPACKAGER.packFile )
-	error( 'Usage:java -jar js.jar ckpackager.js sample.pack' );
-
-CKPACKAGER.packDir = (function()
-{
-	var packFile = new File( CKPACKAGER.packFile );
-
-	if ( !packFile.isFile() )
-		error( 'The file name "' + CKPACKAGER.packFile + '" was not found.' );
-
-	return packFile.getParent() || './';
-})();
-
-CKPACKAGER.outputDir = CKPACKAGER.packDir;
-
-CKPACKAGER.loadCode( 'includes/packager.js' );
-
-//for ( var o in CKPACKAGER )
-//	print( o + ': ' + CKPACKAGER[o] );
-
-// print( String( System.getProperties() ).replace( /,/g, '\n') );
-
-(function()
-{
-	var packager = new CKPACKAGER.packager();
-	packager.loadDefinitionFile( CKPACKAGER.packFile );
-	packager.run();
-})();
