aboutsummaryrefslogtreecommitdiff
path: root/lib/scope.js
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2017-06-23 20:05:31 +0800
committerGitHub <noreply@github.com>2017-06-23 20:05:31 +0800
commit94e5e00c0321b92aca1abf170c12a02d6c3275b5 (patch)
treed674cfc01a9d85e895e1f84e866e9d91d5e3a28b /lib/scope.js
parentdc6bcaa18eda80f31674a1f8167d7fbe997f743b (diff)
downloadtracifyjs-94e5e00c0321b92aca1abf170c12a02d6c3275b5.tar.gz
tracifyjs-94e5e00c0321b92aca1abf170c12a02d6c3275b5.zip
refactor `compute_char_frequency()` (#2152)
- minimise maintenance when updating AST - maximise code sharing between `master` & `harmony`
Diffstat (limited to 'lib/scope.js')
-rw-r--r--lib/scope.js123
1 files changed, 45 insertions, 78 deletions
diff --git a/lib/scope.js b/lib/scope.js
index c147ce00..f8ecedb5 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -361,7 +361,8 @@ AST_Function.DEFMETHOD("next_mangled", function(options, def){
});
AST_Symbol.DEFMETHOD("unmangleable", function(options){
- return this.definition().unmangleable(options);
+ var def = this.definition();
+ return !def || def.unmangleable(options);
});
// labels are always mangleable
@@ -460,103 +461,69 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
options = this._default_mangler_options(options);
- var tw = new TreeWalker(function(node){
- if (node instanceof AST_Constant)
- base54.consider(node.print_to_string());
- else if (node instanceof AST_Return)
- base54.consider("return");
- else if (node instanceof AST_Throw)
- base54.consider("throw");
- else if (node instanceof AST_Continue)
- base54.consider("continue");
- else if (node instanceof AST_Break)
- base54.consider("break");
- else if (node instanceof AST_Debugger)
- base54.consider("debugger");
- else if (node instanceof AST_Directive)
- base54.consider(node.value);
- else if (node instanceof AST_While)
- base54.consider("while");
- else if (node instanceof AST_Do)
- base54.consider("do while");
- else if (node instanceof AST_If) {
- base54.consider("if");
- if (node.alternative) base54.consider("else");
- }
- else if (node instanceof AST_Var)
- base54.consider("var");
- else if (node instanceof AST_Lambda)
- base54.consider("function");
- else if (node instanceof AST_For)
- base54.consider("for");
- else if (node instanceof AST_ForIn)
- base54.consider("for in");
- else if (node instanceof AST_Switch)
- base54.consider("switch");
- else if (node instanceof AST_Case)
- base54.consider("case");
- else if (node instanceof AST_Default)
- base54.consider("default");
- else if (node instanceof AST_With)
- base54.consider("with");
- else if (node instanceof AST_ObjectSetter)
- base54.consider("set" + node.key);
- else if (node instanceof AST_ObjectGetter)
- base54.consider("get" + node.key);
- else if (node instanceof AST_ObjectKeyVal)
- base54.consider(node.key);
- else if (node instanceof AST_New)
- base54.consider("new");
- else if (node instanceof AST_This)
- base54.consider("this");
- else if (node instanceof AST_Try)
- base54.consider("try");
- else if (node instanceof AST_Catch)
- base54.consider("catch");
- else if (node instanceof AST_Finally)
- base54.consider("finally");
- else if (node instanceof AST_Symbol && node.unmangleable(options))
- base54.consider(node.name);
- else if (node instanceof AST_Unary || node instanceof AST_Binary)
- base54.consider(node.operator);
- else if (node instanceof AST_Dot)
- base54.consider(node.property);
- });
- this.walk(tw);
+ try {
+ AST_Node.prototype.print = function(stream, force_parens) {
+ this._print(stream, force_parens);
+ if (this instanceof AST_Symbol && !this.unmangleable(options)) {
+ base54.consider(this.name, -1);
+ } else if (options.properties) {
+ if (this instanceof AST_Dot) {
+ base54.consider(this.property, -1);
+ } else if (this instanceof AST_Sub) {
+ skip_string(this.property);
+ }
+ }
+ };
+ base54.consider(this.print_to_string(), 1);
+ } finally {
+ AST_Node.prototype.print = AST_Node.prototype._print;
+ }
base54.sort();
+
+ function skip_string(node) {
+ if (node instanceof AST_String) {
+ base54.consider(node.value, -1);
+ } else if (node instanceof AST_Conditional) {
+ skip_string(node.consequent);
+ skip_string(node.alternative);
+ } else if (node instanceof AST_Sequence) {
+ skip_string(node.expressions[node.expressions.length - 1]);
+ }
+ }
});
var base54 = (function() {
- var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
+ var leading = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_".split("");
+ var digits = "0123456789".split("");
var chars, frequency;
function reset() {
frequency = Object.create(null);
- chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
- chars.forEach(function(ch){ frequency[ch] = 0 });
+ leading.forEach(function(ch) {
+ frequency[ch] = 0;
+ });
+ digits.forEach(function(ch) {
+ frequency[ch] = 0;
+ });
}
- base54.consider = function(str){
+ base54.consider = function(str, delta) {
for (var i = str.length; --i >= 0;) {
- var code = str.charCodeAt(i);
- if (code in frequency) ++frequency[code];
+ frequency[str[i]] += delta;
}
};
+ function compare(a, b) {
+ return frequency[b] - frequency[a];
+ }
base54.sort = function() {
- chars = mergeSort(chars, function(a, b){
- if (is_digit(a) && !is_digit(b)) return 1;
- if (is_digit(b) && !is_digit(a)) return -1;
- return frequency[b] - frequency[a];
- });
+ chars = mergeSort(leading, compare).concat(mergeSort(digits, compare));
};
base54.reset = reset;
reset();
- base54.get = function(){ return chars };
- base54.freq = function(){ return frequency };
function base54(num) {
var ret = "", base = 54;
num++;
do {
num--;
- ret += String.fromCharCode(chars[num % base]);
+ ret += chars[num % base];
num = Math.floor(num / base);
base = 64;
} while (num > 0);