aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/js-optimizer.js98
-rw-r--r--tools/test-js-optimizer-output.js4
-rw-r--r--tools/test-js-optimizer.js4
3 files changed, 62 insertions, 44 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index f8e65f55..aa4ba39b 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -35,7 +35,7 @@ var FUNCTION = set('defun', 'function');
// it replaces the passed node in the tree.
// @arg post: A callback to call after traversing all children.
// @arg stack: If true, a stack will be implemented: If pre does not push on
-// the stack, we push a null. We pop when we leave the node. The
+// the stack, we push a 0. We pop when we leave the node. The
// stack is passed as a third parameter to the callbacks.
// @returns: If the root node was replaced, the new root node. If the traversal
// was stopped, true. Otherwise undefined.
@@ -46,7 +46,7 @@ function traverse(node, pre, post, stack) {
if (stack) len = stack.length;
var result = pre(node, type, stack);
if (result == true) return true;
- if (stack && len == stack.length) stack.push(null);
+ if (stack && len == stack.length) stack.push(0);
}
for (var i = 0; i < node.length; i++) {
var subnode = node[i];
@@ -66,6 +66,32 @@ function traverse(node, pre, post, stack) {
return result;
}
+// Walk the ast in a simple way, with an understanding of which JS variables are defined)
+function traverseWithVariables(ast, callback) {
+ traverse(ast, function(node, type, stack) {
+ if (type in FUNCTION) {
+ stack.push({ type: 'function', vars: node[2] });
+ } else if (type == 'var') {
+ // Find our function, add our vars
+ var func = stack[stack.length-1];
+ if (func) {
+ func.vars = func.vars.concat(node[1].map(function(varItem) { return varItem[0] }));
+ }
+ }
+ }, function(node, type, stack) {
+ if (type in FUNCTION) {
+ // We know all of the variables that are seen here, proceed to do relevant replacements
+ var allVars = stack.map(function(item) { return item ? item.vars : [] }).reduce(concatenator, []); // FIXME dictionary for speed?
+ traverse(node, function(node, type, stack) {
+ // Be careful not to look into our inner functions. They have already been processed.
+ if (sum(stack) > 1) return;
+ if (type in FUNCTION) stack.push(1);
+ return callback(node, type, allVars);
+ }, null, []);
+ }
+ }, []);
+}
+
function makeEmptyNode() {
return ['toplevel', []]
}
@@ -81,59 +107,47 @@ function unGlobalize(ast) {
// Find global renamings of the relevant values
ast[1].forEach(function(node, i) {
if (node[0] != 'var') return;
- node[1] = node[1].filter(function(varItem) {
- var key = varItem[0];
+ node[1] = node[1].filter(function(varItem, j) {
+ var ident = varItem[0];
var value = varItem[1];
if (!value) return true;
+ var possible = false;
if (value[0] == 'name' && value[1] == 'null') {
- values[key] = ['name','null'];
- return false;
- } else if (value[0] == 'unary-prefix' && value[1] == 'void' && value[2] && value[2].length == 2 && value[2][0] == 'num' && value[2][1] == 0){
- values[key] = ['unary-prefix','void',['num',0]];
- return false;
- } else if (value[0] == 'unary-prefix' && value[1] == '!' && value[2] && value[2].length == 2 && value[2][0] == 'num' && value[2][1] == 0){
- values[key] = ['unary-prefix','!',['num',0]];
- return false;
- } else if (value[0] == 'unary-prefix' && value[1] == '!' && value[2] && value[2].length == 2 && value[2][0] == 'num' && value[2][1] == 1){
- values[key] = ['unary-prefix','!',['num',1]];
+ possible = true;
+ } else if (value[0] == 'unary-prefix' && value[1] == 'void' && value[2] && value[2].length == 2 && value[2][0] == 'num' && value[2][1] == 0) {
+ possible = true;
+ } else if (value[0] == 'unary-prefix' && value[1] == '!' && value[2] && value[2].length == 2 && value[2][0] == 'num' && value[2][1] == 0) {
+ possible = true;
+ } else if (value[0] == 'unary-prefix' && value[1] == '!' && value[2] && value[2].length == 2 && value[2][0] == 'num' && value[2][1] == 1) {
+ possible = true;
+ }
+ if (!possible) return true;
+ // Make sure there are no assignments to this variable. (This isn't fast, we traverse many times..)
+ ast[1][i][1][j] = makeEmptyNode();
+ var assigned = false;
+ traverseWithVariables(ast, function(node, type, allVars) {
+ if (type == 'assign' && node[2][0] == 'name' && node[2][1] == ident) assigned = true;
+ });
+ ast[1][i][1][j] = [ident, value];
+ if (!assigned) {
+ values[ident] = value;
return false;
}
return true;
});
+
if (node[1].length == 0) {
ast[1][i] = makeEmptyNode();
}
});
- // Walk the ast, with an understanding of JS variable scope (i.e., function-level scoping)
- traverse(ast, function(node, type, stack) {
- if (type in FUNCTION) {
- stack.push({ type: 'function', vars: node[2] });
- } else if (type == 'var') {
- // Find our function, add our vars
- var func = stack[stack.length-1];
- if (func) {
- func.vars = func.vars.concat(node[1].map(function(varItem) { return varItem[0] }));
+ traverseWithVariables(ast, function(node, type, allVars) {
+ if (type == 'name') {
+ var ident = node[1];
+ if (ident in values && allVars.indexOf(ident) < 0) {
+ return copy(values[ident]);
}
}
- }, function(node, type, stack) {
- if (type in FUNCTION) {
- // We know all of the variables that are seen here, proceed to do relevant replacements
- var allVars = stack.map(function(item) { return item ? item.vars : [] }).reduce(concatenator, []); // FIXME dictionary for speed?
- traverse(node, function(node, type, stack) {
- // Be careful not to look into our inner functions. They have already been processed.
- if (type == 'name' && sum(stack) == 1) {
- var ident = node[1];
- if (ident in values && allVars.indexOf(ident) < 0) {
- return copy(values[ident]);
- }
- } else if (type in FUNCTION) {
- stack.push(1);
- } else {
- stack.push(0);
- }
- }, null, []);
- }
- }, []);
+ });
}
// Main
diff --git a/tools/test-js-optimizer-output.js b/tools/test-js-optimizer-output.js
index c50adde2..a53ca461 100644
--- a/tools/test-js-optimizer-output.js
+++ b/tools/test-js-optimizer-output.js
@@ -1,6 +1,6 @@
var c;
var b = 5;
-
+var s3 = !0;
function abc() {
var cheez = void 0;
var fleefl;
@@ -11,6 +11,7 @@ function abc() {
var waka3 = void 0, flake3 = 5, marfoosh3 = void 0;
var waka4 = void 0, flake4 = void 0, marfoosh4 = 5;
var test1 = !0, test2 = !1, test3 = null, test4 = z, test5 = b, test6 = void 0;
+ s3 = 9;
}
function xyz() {
var x = 52;
@@ -24,6 +25,7 @@ function xyz() {
var i = x, j = null, k = 5, l = t, m = s2;
var s2 = 8;
});
+ var patama = s3;
}
function xyz2(x) {
var cheez = x;
diff --git a/tools/test-js-optimizer.js b/tools/test-js-optimizer.js
index 14306740..f2674b31 100644
--- a/tools/test-js-optimizer.js
+++ b/tools/test-js-optimizer.js
@@ -1,6 +1,6 @@
var c;
var b = 5, x = void 0, y = null, t = !0;
-var s = !1, s2 = !1;
+var s = !1, s2 = !1, s3 = !0;
function abc() {
var cheez = x;
var fleefl;
@@ -11,6 +11,7 @@ function abc() {
var waka3 = x, flake3 = 5, marfoosh3 = x;
var waka4 = x, flake4 = x, marfoosh4 = 5;
var test1 = t, test2 = s, test3 = y, test4 = z, test5 = b, test6 = x;
+ s3 = 9;
}
function xyz() {
var x = 52;
@@ -24,6 +25,7 @@ function xyz() {
var i = x, j = y, k = 5, l = t, m = s2;
var s2 = 8;
};
+ var patama = s3;
}
function xyz2(x) {
var cheez = x;