diff options
| author | Alon Zakai <alonzakai@gmail.com> | 2011-11-19 23:00:04 -0800 | 
|---|---|---|
| committer | Alon Zakai <alonzakai@gmail.com> | 2011-11-19 23:00:04 -0800 | 
| commit | b27d8da1c798d2a4cfbf8d63585004ce77cf2c71 (patch) | |
| tree | 638bc1aea154c1fe603f4c50322347bbe8d8a0a6 | |
| parent | a6e94183b9ed09f3c07ed921745bde179bca3f9c (diff) | |
partial work to remove assigns of undefined in js optimizer
| -rw-r--r-- | src/utility.js | 4 | ||||
| -rw-r--r-- | tools/js-optimizer.js | 34 | ||||
| -rw-r--r-- | tools/test-js-optimizer-output.js | 1 | 
3 files changed, 28 insertions, 11 deletions
diff --git a/src/utility.js b/src/utility.js index 53555aa5..91c4abe3 100644 --- a/src/utility.js +++ b/src/utility.js @@ -272,3 +272,7 @@ function copy(x) {    return JSON.parse(JSON.stringify(x));  } +function jsonCompare(x, y) { +  return JSON.stringify(x) == JSON.stringify(y); +} + diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 372cbea3..f88b7d95 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -92,7 +92,7 @@ function traverseWithVariables(ast, callback) {    }, []);  } -function makeEmptyNode() { +function emptyNode() {    return ['toplevel', []]  } @@ -112,18 +112,15 @@ function unGlobalize(ast) {        var value = varItem[1];        if (!value) return true;        var possible = false; -      if (value[0] == 'name' && value[1] == 'null') { -        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) { +      if (jsonCompare(value, ['name', 'null']) || +          jsonCompare(value, ['unary-prefix', 'void', ['num', 0]]) || +          jsonCompare(value, ['unary-prefix', '!', ['num', 0]]) || +          jsonCompare(value, ['unary-prefix', '!', ['num', 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(); +      ast[1][i][1][j] = emptyNode();        var assigned = false;        traverseWithVariables(ast, function(node, type, allVars) {          if (type == 'assign' && node[2][0] == 'name' && node[2][1] == ident) assigned = true; @@ -137,7 +134,7 @@ function unGlobalize(ast) {      });      if (node[1].length == 0) { -      ast[1][i] = makeEmptyNode(); +      ast[1][i] = emptyNode();      }    });    traverseWithVariables(ast, function(node, type, allVars) { @@ -150,6 +147,22 @@ function unGlobalize(ast) {    });  } +// Closure compiler, when inlining, will insert assignments to +// undefined for the shared variables. However, in compiled code +// - and in library/shell code too! - we should never rely on +// undefined being assigned. So we can simply remove those assignments. +// +// This pass assumes that unGlobalize has been run, so undefined +// is now explicit. +function removeAssignsToUndefined(ast) { +  // TODO: in vars too +  traverse(ast, function(node, type) { +    if (type == 'assign' && jsonCompare(node[3], ['unary-prefix', 'void', ['num', 0]])) { +      return emptyNode(); +    } +  }); +} +  // Main  var src = fs.readFileSync('/dev/stdin').toString(); @@ -157,6 +170,7 @@ var src = fs.readFileSync('/dev/stdin').toString();  var ast = uglify.parser.parse(src);  unGlobalize(ast); +removeAssignsToUndefined(ast);  print(uglify.uglify.gen_code(ast, {    ascii_only: true, diff --git a/tools/test-js-optimizer-output.js b/tools/test-js-optimizer-output.js index a6e790c8..a08be0ca 100644 --- a/tools/test-js-optimizer-output.js +++ b/tools/test-js-optimizer-output.js @@ -6,7 +6,6 @@ function abc() {    var cheez = [ void 0 ];    var fleefl;    cheez = 10; -  fleefl = void 0;    var waka = void 0, flake = void 0, marfoosh = void 0;    var waka2 = 5, flake2 = void 0, marfoosh2 = void 0;    var waka3 = void 0, flake3 = 5, marfoosh3 = void 0;  | 
