diff options
author | John Resig <jeresig@gmail.com> | 2006-08-26 00:43:41 +0000 |
---|---|---|
committer | John Resig <jeresig@gmail.com> | 2006-08-26 00:43:41 +0000 |
commit | a2af24b064bd1384c24b896fdd9c7d322954546b (patch) | |
tree | adf478fef953c6e6d26bc21f895ce5213f3301ea /build | |
parent | 94fc6aac1990dc3233c70f471432c5b9f230e756 (diff) | |
download | jquery-a2af24b064bd1384c24b896fdd9c7d322954546b.tar.gz jquery-a2af24b064bd1384c24b896fdd9c7d322954546b.zip |
Quick bug fix, formatted pack better.
Diffstat (limited to 'build')
-rw-r--r-- | build/js/pack.js | 317 |
1 files changed, 316 insertions, 1 deletions
diff --git a/build/js/pack.js b/build/js/pack.js index ef6a4230a..56bfdd1a2 100644 --- a/build/js/pack.js +++ b/build/js/pack.js @@ -1 +1,316 @@ -/*
packer, version 2.0.2 (2005-08-19)
Copyright 2004-2005, Dean Edwards
License: http://creativecommons.org/licenses/LGPL/2.1/
*/
function pack(_script, _encoding, _fastDecode, _specialChars) {
// constants
var $IGNORE = "$1";
// validate parameters
_script += "\n";
_encoding = Math.min(parseInt(_encoding), 95);
// apply all parsing routines
function _pack($script) {
var i, $parse;
for (i = 0; ($parse = _parsers[i]); i++) {
$script = $parse($script);
}
return $script;
};
// unpacking function - this is the boot strap function
// data extracted from this packing routine is passed to
// this function when decoded in the target
var _unpack = function($packed, $ascii, $count, $keywords, $encode, $decode) {
while ($count--)
if ($keywords[$count])
$packed = $packed.replace(new RegExp('\\b' + $encode($count) + '\\b', 'g'), $keywords[$count]);
return $packed;
};
// code-snippet inserted into the unpacker to speed up decoding
var _decode = function() {
// does the browser support String.replace where the
// replacement value is a function?
if (!''.replace(/^/, String)) {
// decode all the values we need
while ($count--) $decode[$encode($count)] = $keywords[$count] || $encode($count);
// global replacement function
$keywords = [function($encoded){return $decode[$encoded]}];
// generic match
$encode = function(){return'\\w+'};
// reset the loop counter - we are now doing a global replace
$count = 1;
}
};
// keep a list of parsing functions, they'll be executed all at once
var _parsers = [];
function _addParser($parser) {
_parsers[_parsers.length] = $parser;
};
// zero encoding - just removal of white space and comments
function _basicCompression($script) {
var $parser = new ParseMaster;
// make safe
$parser.escapeChar = "\\";
// protect strings
$parser.add(/'[^'\n\r]*'/, $IGNORE);
$parser.add(/"[^"\n\r]*"/, $IGNORE);
// remove comments
$parser.add(/\/\/[^\n\r]*[\n\r]/, " ");
$parser.add(/\/\*[^*]*\*+([^\/][^*]*\*+)*\//, " ");
// protect regular expressions
$parser.add(/\s+(\/[^\/\n\r\*][^\/\n\r]*\/g?i?)/, "$2"); // IGNORE
$parser.add(/[^\w\x24\/'"*)\?:]\/[^\/\n\r\*][^\/\n\r]*\/g?i?/, $IGNORE);
// remove: ;;; doSomething();
if (_specialChars) $parser.add(/;;;[^\n\r]+[\n\r]/);
// remove redundant semi-colons
$parser.add(/\(;;\)/, $IGNORE); // protect for (;;) loops
$parser.add(/;+\s*([};])/, "$2");
// apply the above
$script = $parser.exec($script);
// remove white-space
$parser.add(/(\b|\x24)\s+(\b|\x24)/, "$2 $3");
$parser.add(/([+\-])\s+([+\-])/, "$2 $3");
$parser.add(/\s+/, "");
// done
return $parser.exec($script);
};
function _encodeSpecialChars($script) {
var $parser = new ParseMaster;
// replace: $name -> n, $$name -> na
$parser.add(/((\x24+)([a-zA-Z$_]+))(\d*)/, function($match, $offset) {
var $length = $match[$offset + 2].length;
var $start = $length - Math.max($length - $match[$offset + 3].length, 0);
return $match[$offset + 1].substr($start, $length) + $match[$offset + 4];
});
// replace: _name -> _0, double-underscore (__name) is ignored
var $regexp = /\b_[A-Za-z\d]\w*/;
// build the word list
var $keywords = _analyze($script, _globalize($regexp), _encodePrivate);
// quick ref
var $encoded = $keywords.$encoded;
$parser.add($regexp, function($match, $offset) {
return $encoded[$match[$offset]];
});
return $parser.exec($script);
};
function _encodeKeywords($script) {
// escape high-ascii values already in the script (i.e. in strings)
if (_encoding > 62) $script = _escape95($script);
// create the parser
var $parser = new ParseMaster;
var $encode = _getEncoder(_encoding);
// for high-ascii, don't encode single character low-ascii
var $regexp = (_encoding > 62) ? /\w\w+/ : /\w+/;
// build the word list
$keywords = _analyze($script, _globalize($regexp), $encode);
var $encoded = $keywords.$encoded;
// encode
$parser.add($regexp, function($match, $offset) {
return $encoded[$match[$offset]];
});
// if encoded, wrap the script in a decoding function
return $script && _bootStrap($parser.exec($script), $keywords);
};
function _analyze($script, $regexp, $encode) {
// analyse
// retreive all words in the script
var $all = $script.match($regexp);
var $$sorted = []; // list of words sorted by frequency
var $$encoded = {}; // dictionary of word->encoding
var $$protected = {}; // instances of "protected" words
if ($all) {
var $unsorted = []; // same list, not sorted
var $protected = {}; // "protected" words (dictionary of word->"word")
var $values = {}; // dictionary of charCode->encoding (eg. 256->ff)
var $count = {}; // word->count
var i = $all.length, j = 0, $word;
// count the occurrences - used for sorting later
do {
$word = "$" + $all[--i];
if (!$count[$word]) {
$count[$word] = 0;
$unsorted[j] = $word;
// make a dictionary of all of the protected words in this script
// these are words that might be mistaken for encoding
$protected["$" + ($values[j] = $encode(j))] = j++;
}
// increment the word counter
$count[$word]++;
} while (i);
// prepare to sort the word list, first we must protect
// words that are also used as codes. we assign them a code
// equivalent to the word itself.
// e.g. if "do" falls within our encoding range
// then we store keywords["do"] = "do";
// this avoids problems when decoding
i = $unsorted.length;
do {
$word = $unsorted[--i];
if ($protected[$word] != null) {
$$sorted[$protected[$word]] = $word.slice(1);
$$protected[$protected[$word]] = true;
$count[$word] = 0;
}
} while (i);
// sort the words by frequency
$unsorted.sort(function($match1, $match2) {
return $count[$match2] - $count[$match1];
});
j = 0;
// because there are "protected" words in the list
// we must add the sorted words around them
do {
if ($$sorted[i] == null) $$sorted[i] = $unsorted[j++].slice(1);
$$encoded[$$sorted[i]] = $values[i];
} while (++i < $unsorted.length);
}
return {$sorted: $$sorted, $encoded: $$encoded, $protected: $$protected};
};
// build the boot function used for loading and decoding
function _bootStrap($packed, $keywords) {
var $ENCODE = _safeRegExp("$encode\\($count\\)", "g");
// $packed: the packed script
$packed = "'" + _escape($packed) + "'";
// $ascii: base for encoding
var $ascii = Math.min($keywords.$sorted.length, _encoding) || 1;
// $count: number of words contained in the script
var $count = $keywords.$sorted.length;
// $keywords: list of words contained in the script
for (var i in $keywords.$protected) $keywords.$sorted[i] = "";
// convert from a string to an array
$keywords = "'" + $keywords.$sorted.join("|") + "'.split('|')";
// $encode: encoding function (used for decoding the script)
var $encode = _encoding > 62 ? _encode95 : _getEncoder($ascii);
$encode = String($encode).replace(/_encoding/g, "$ascii").replace(/arguments\.callee/g, "$encode");
var $inline = "$count" + ($ascii > 10 ? ".toString($ascii)" : "");
// $decode: code snippet to speed up decoding
if (_fastDecode) {
// create the decoder
var $decode = _getFunctionBody(_decode);
if (_encoding > 62) $decode = $decode.replace(/\\\\w/g, "[\\xa1-\\xff]");
// perform the encoding inline for lower ascii values
else if ($ascii < 36) $decode = $decode.replace($ENCODE, $inline);
// special case: when $count==0 there are no keywords. I want to keep
// the basic shape of the unpacking funcion so i'll frig the code...
if (!$count) $decode = $decode.replace(_safeRegExp("($count)\\s*=\\s*1"), "$1=0");
}
// boot function
var $unpack = String(_unpack);
if (_fastDecode) {
// insert the decoder
$unpack = $unpack.replace(/\{/, "{" + $decode + ";");
}
$unpack = $unpack.replace(/"/g, "'");
if (_encoding > 62) { // high-ascii
// get rid of the word-boundaries for regexp matches
$unpack = $unpack.replace(/'\\\\b'\s*\+|\+\s*'\\\\b'/g, "");
}
if ($ascii > 36 || _encoding > 62 || _fastDecode) {
// insert the encode function
$unpack = $unpack.replace(/\{/, "{$encode=" + $encode + ";");
} else {
// perform the encoding inline
$unpack = $unpack.replace($ENCODE, $inline);
}
// pack the boot function too
$unpack = pack($unpack, 0, false, true);
// arguments
var $params = [$packed, $ascii, $count, $keywords];
if (_fastDecode) {
// insert placeholders for the decoder
$params = $params.concat(0, "{}");
}
// the whole thing
return "eval(" + $unpack + "(" + $params + "))\n";
};
// mmm.. ..which one do i need ??
function _getEncoder($ascii) {
return $ascii > 10 ? $ascii > 36 ? $ascii > 62 ? _encode95 : _encode62 : _encode36 : _encode10;
};
// zero encoding
// characters: 0123456789
var _encode10 = function($charCode) {
return $charCode;
};
// inherent base36 support
// characters: 0123456789abcdefghijklmnopqrstuvwxyz
var _encode36 = function($charCode) {
return $charCode.toString(36);
};
// hitch a ride on base36 and add the upper case alpha characters
// characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
var _encode62 = function($charCode) {
return ($charCode < _encoding ? '' : arguments.callee(parseInt($charCode / _encoding))) +
(($charCode = $charCode % _encoding) > 35 ? String.fromCharCode($charCode + 29) : $charCode.toString(36));
};
// use high-ascii values
var _encode95 = function($charCode) {
return ($charCode < _encoding ? '' : arguments.callee($charCode / _encoding)) +
String.fromCharCode($charCode % _encoding + 161);
};
// special _chars
var _encodePrivate = function($charCode) {
return "_" + $charCode;
};
// protect characters used by the parser
function _escape($script) {
return $script.replace(/([\\'])/g, "\\$1");
};
// protect high-ascii characters already in the script
function _escape95($script) {
return $script.replace(/[\xa1-\xff]/g, function($match) {
return "\\x" + $match.charCodeAt(0).toString(16);
});
};
function _safeRegExp($string, $flags) {
return new RegExp($string.replace(/\$/g, "\\$"), $flags);
};
// extract the body of a function
function _getFunctionBody($function) {
with (String($function)) return slice(indexOf("{") + 1, lastIndexOf("}"));
};
// set the global flag on a RegExp (you have to create a new one)
function _globalize($regexp) {
return new RegExp(String($regexp).slice(1, -1), "g");
};
// build the parsing routine
_addParser(_basicCompression);
if (_specialChars) _addParser(_encodeSpecialChars);
if (_encoding) _addParser(_encodeKeywords);
// go!
return _pack(_script);
};
\ No newline at end of file +/* + packer, version 2.0.2 (2005-08-19) + Copyright 2004-2005, Dean Edwards + License: http://creativecommons.org/licenses/LGPL/2.1/ +*/ + +function pack(_script, _encoding, _fastDecode, _specialChars) { + // constants + var $IGNORE = "$1"; + + // validate parameters + _script += "\n"; + _encoding = Math.min(parseInt(_encoding), 95); + + // apply all parsing routines + function _pack($script) { + var i, $parse; + for (i = 0; ($parse = _parsers[i]); i++) { + $script = $parse($script); + } + return $script; + }; + + // unpacking function - this is the boot strap function + // data extracted from this packing routine is passed to + // this function when decoded in the target + var _unpack = function($packed, $ascii, $count, $keywords, $encode, $decode) { + while ($count--) + if ($keywords[$count]) + $packed = $packed.replace(new RegExp('\\b' + $encode($count) + '\\b', 'g'), $keywords[$count]); + return $packed; + }; + + // code-snippet inserted into the unpacker to speed up decoding + var _decode = function() { + // does the browser support String.replace where the + // replacement value is a function? + if (!''.replace(/^/, String)) { + // decode all the values we need + while ($count--) $decode[$encode($count)] = $keywords[$count] || $encode($count); + // global replacement function + $keywords = [function($encoded){return $decode[$encoded]}]; + // generic match + $encode = function(){return'\\w+'}; + // reset the loop counter - we are now doing a global replace + $count = 1; + } + }; + + // keep a list of parsing functions, they'll be executed all at once + var _parsers = []; + function _addParser($parser) { + _parsers[_parsers.length] = $parser; + }; + + // zero encoding - just removal of white space and comments + function _basicCompression($script) { + var $parser = new ParseMaster; + // make safe + $parser.escapeChar = "\\"; + // protect strings + $parser.add(/'[^'\n\r]*'/, $IGNORE); + $parser.add(/"[^"\n\r]*"/, $IGNORE); + // remove comments + $parser.add(/\/\/[^\n\r]*[\n\r]/, " "); + $parser.add(/\/\*[^*]*\*+([^\/][^*]*\*+)*\//, " "); + // protect regular expressions + $parser.add(/\s+(\/[^\/\n\r\*][^\/\n\r]*\/g?i?)/, "$2"); // IGNORE + $parser.add(/[^\w\x24\/'"*)\?:]\/[^\/\n\r\*][^\/\n\r]*\/g?i?/, $IGNORE); + // remove: ;;; doSomething(); + if (_specialChars) $parser.add(/;;;[^\n\r]+[\n\r]/); + // remove redundant semi-colons + $parser.add(/\(;;\)/, $IGNORE); // protect for (;;) loops + $parser.add(/;+\s*([};])/, "$2"); + // apply the above + $script = $parser.exec($script); + + // remove white-space + $parser.add(/(\b|\x24)\s+(\b|\x24)/, "$2 $3"); + $parser.add(/([+\-])\s+([+\-])/, "$2 $3"); + $parser.add(/\s+/, ""); + // done + return $parser.exec($script); + }; + + function _encodeSpecialChars($script) { + var $parser = new ParseMaster; + // replace: $name -> n, $$name -> na + $parser.add(/((\x24+)([a-zA-Z$_]+))(\d*)/, function($match, $offset) { + var $length = $match[$offset + 2].length; + var $start = $length - Math.max($length - $match[$offset + 3].length, 0); + return $match[$offset + 1].substr($start, $length) + $match[$offset + 4]; + }); + // replace: _name -> _0, double-underscore (__name) is ignored + var $regexp = /\b_[A-Za-z\d]\w*/; + // build the word list + var $keywords = _analyze($script, _globalize($regexp), _encodePrivate); + // quick ref + var $encoded = $keywords.$encoded; + $parser.add($regexp, function($match, $offset) { + return $encoded[$match[$offset]]; + }); + return $parser.exec($script); + }; + + function _encodeKeywords($script) { + // escape high-ascii values already in the script (i.e. in strings) + if (_encoding > 62) $script = _escape95($script); + // create the parser + var $parser = new ParseMaster; + var $encode = _getEncoder(_encoding); + // for high-ascii, don't encode single character low-ascii + var $regexp = (_encoding > 62) ? /\w\w+/ : /\w+/; + // build the word list + $keywords = _analyze($script, _globalize($regexp), $encode); + var $encoded = $keywords.$encoded; + // encode + $parser.add($regexp, function($match, $offset) { + return $encoded[$match[$offset]]; + }); + // if encoded, wrap the script in a decoding function + return $script && _bootStrap($parser.exec($script), $keywords); + }; + + function _analyze($script, $regexp, $encode) { + // analyse + // retreive all words in the script + var $all = $script.match($regexp); + var $$sorted = []; // list of words sorted by frequency + var $$encoded = {}; // dictionary of word->encoding + var $$protected = {}; // instances of "protected" words + if ($all) { + var $unsorted = []; // same list, not sorted + var $protected = {}; // "protected" words (dictionary of word->"word") + var $values = {}; // dictionary of charCode->encoding (eg. 256->ff) + var $count = {}; // word->count + var i = $all.length, j = 0, $word; + // count the occurrences - used for sorting later + do { + $word = "$" + $all[--i]; + if (!$count[$word]) { + $count[$word] = 0; + $unsorted[j] = $word; + // make a dictionary of all of the protected words in this script + // these are words that might be mistaken for encoding + $protected["$" + ($values[j] = $encode(j))] = j++; + } + // increment the word counter + $count[$word]++; + } while (i); + // prepare to sort the word list, first we must protect + // words that are also used as codes. we assign them a code + // equivalent to the word itself. + // e.g. if "do" falls within our encoding range + // then we store keywords["do"] = "do"; + // this avoids problems when decoding + i = $unsorted.length; + do { + $word = $unsorted[--i]; + if ($protected[$word] != null) { + $$sorted[$protected[$word]] = $word.slice(1); + $$protected[$protected[$word]] = true; + $count[$word] = 0; + } + } while (i); + // sort the words by frequency + $unsorted.sort(function($match1, $match2) { + return $count[$match2] - $count[$match1]; + }); + j = 0; + // because there are "protected" words in the list + // we must add the sorted words around them + do { + if ($$sorted[i] == null) $$sorted[i] = $unsorted[j++].slice(1); + $$encoded[$$sorted[i]] = $values[i]; + } while (++i < $unsorted.length); + } + return {$sorted: $$sorted, $encoded: $$encoded, $protected: $$protected}; + }; + + // build the boot function used for loading and decoding + function _bootStrap($packed, $keywords) { + var $ENCODE = _safeRegExp("$encode\\($count\\)", "g"); + + // $packed: the packed script + $packed = "'" + _escape($packed) + "'"; + + // $ascii: base for encoding + var $ascii = Math.min($keywords.$sorted.length, _encoding) || 1; + + // $count: number of words contained in the script + var $count = $keywords.$sorted.length; + + // $keywords: list of words contained in the script + for (var i in $keywords.$protected) $keywords.$sorted[i] = ""; + // convert from a string to an array + $keywords = "'" + $keywords.$sorted.join("|") + "'.split('|')"; + + // $encode: encoding function (used for decoding the script) + var $encode = _encoding > 62 ? _encode95 : _getEncoder($ascii); + $encode = String($encode).replace(/_encoding/g, "$ascii").replace(/arguments\.callee/g, "$encode"); + var $inline = "$count" + ($ascii > 10 ? ".toString($ascii)" : ""); + + // $decode: code snippet to speed up decoding + if (_fastDecode) { + // create the decoder + var $decode = _getFunctionBody(_decode); + if (_encoding > 62) $decode = $decode.replace(/\\\\w/g, "[\\xa1-\\xff]"); + // perform the encoding inline for lower ascii values + else if ($ascii < 36) $decode = $decode.replace($ENCODE, $inline); + // special case: when $count==0 there are no keywords. I want to keep + // the basic shape of the unpacking funcion so i'll frig the code... + if (!$count) $decode = $decode.replace(_safeRegExp("($count)\\s*=\\s*1"), "$1=0"); + } + + // boot function + var $unpack = String(_unpack); + if (_fastDecode) { + // insert the decoder + $unpack = $unpack.replace(/\{/, "{" + $decode + ";"); + } + $unpack = $unpack.replace(/"/g, "'"); + if (_encoding > 62) { // high-ascii + // get rid of the word-boundaries for regexp matches + $unpack = $unpack.replace(/'\\\\b'\s*\+|\+\s*'\\\\b'/g, ""); + } + if ($ascii > 36 || _encoding > 62 || _fastDecode) { + // insert the encode function + $unpack = $unpack.replace(/\{/, "{$encode=" + $encode + ";"); + } else { + // perform the encoding inline + $unpack = $unpack.replace($ENCODE, $inline); + } + // pack the boot function too + $unpack = pack($unpack, 0, false, true); + + // arguments + var $params = [$packed, $ascii, $count, $keywords]; + if (_fastDecode) { + // insert placeholders for the decoder + $params = $params.concat(0, "{}"); + } + + // the whole thing + return "eval(" + $unpack + "(" + $params + "))\n"; + }; + + // mmm.. ..which one do i need ?? + function _getEncoder($ascii) { + return $ascii > 10 ? $ascii > 36 ? $ascii > 62 ? _encode95 : _encode62 : _encode36 : _encode10; + }; + + // zero encoding + // characters: 0123456789 + var _encode10 = function($charCode) { + return $charCode; + }; + + // inherent base36 support + // characters: 0123456789abcdefghijklmnopqrstuvwxyz + var _encode36 = function($charCode) { + return $charCode.toString(36); + }; + + // hitch a ride on base36 and add the upper case alpha characters + // characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + var _encode62 = function($charCode) { + return ($charCode < _encoding ? '' : arguments.callee(parseInt($charCode / _encoding))) + + (($charCode = $charCode % _encoding) > 35 ? String.fromCharCode($charCode + 29) : $charCode.toString(36)); + }; + + // use high-ascii values + var _encode95 = function($charCode) { + return ($charCode < _encoding ? '' : arguments.callee($charCode / _encoding)) + + String.fromCharCode($charCode % _encoding + 161); + }; + + // special _chars + var _encodePrivate = function($charCode) { + return "_" + $charCode; + }; + + // protect characters used by the parser + function _escape($script) { + return $script.replace(/([\\'])/g, "\\$1"); + }; + + // protect high-ascii characters already in the script + function _escape95($script) { + return $script.replace(/[\xa1-\xff]/g, function($match) { + return "\\x" + $match.charCodeAt(0).toString(16); + }); + }; + + function _safeRegExp($string, $flags) { + return new RegExp($string.replace(/\$/g, "\\$"), $flags); + }; + + // extract the body of a function + function _getFunctionBody($function) { + with (String($function)) return slice(indexOf("{") + 1, lastIndexOf("}")); + }; + + // set the global flag on a RegExp (you have to create a new one) + function _globalize($regexp) { + return new RegExp(String($regexp).slice(1, -1), "g"); + }; + + // build the parsing routine + _addParser(_basicCompression); + if (_specialChars) _addParser(_encodeSpecialChars); + if (_encoding) _addParser(_encodeKeywords); + + // go! + return _pack(_script); +}; |