|
1 | 1 | 'use strict' |
2 | 2 |
|
3 | 3 | var acorn = require('acorn') |
4 | | -var walk = require('walk-ast') |
5 | 4 | var MagicString = require('magic-string') |
| 5 | +var walk = require('estree-walker').walk |
6 | 6 |
|
7 | 7 | function optimizeJs (jsString, opts) { |
8 | 8 | opts = opts || {} |
9 | 9 | var ast = acorn.parse(jsString) |
10 | 10 | var magicString = new MagicString(jsString) |
11 | 11 |
|
12 | | - function walkIt (node) { |
13 | | - if (node.type === 'FunctionExpression') { |
14 | | - handleFunctionExpression(node) |
15 | | - } |
16 | | - } |
17 | | - |
18 | | - function handleFunctionExpression (node) { |
19 | | - var prePreChar = jsString.charAt(node.start - 2) |
20 | | - var preChar = jsString.charAt(node.start - 1) |
21 | | - var postChar = jsString.charAt(node.end) |
22 | | - var postPostChar = jsString.charAt(node.end + 1) |
23 | | - |
24 | | - // assuming this node is an argument to a function, return true if it itself |
25 | | - // is already padded with parentheses |
26 | | - function isPaddedArgument (node) { |
27 | | - var idx = node.parentNode.arguments.indexOf(node) |
28 | | - if (idx === 0) { // first arg |
29 | | - if (prePreChar === '(' && preChar === '(' && postChar === ')') { // already padded |
30 | | - return true |
31 | | - } |
32 | | - } else if (idx === node.parentNode.arguments.length - 1) { // last arg |
33 | | - if (preChar === '(' && postChar === ')' && postPostChar === ')') { // already padded |
34 | | - return true |
35 | | - } |
36 | | - } else { // middle arg |
37 | | - if (preChar === '(' && postChar === ')') { // already padded |
38 | | - return true |
| 12 | + walk(ast, { |
| 13 | + enter: function (node, parent) { |
| 14 | + // assuming this node is an argument to a function, return true if it itself |
| 15 | + // is already padded with parentheses |
| 16 | + function isPaddedArgument (node) { |
| 17 | + var idx = parent.arguments.indexOf(node) |
| 18 | + if (idx === 0) { // first arg |
| 19 | + if (prePreChar === '(' && preChar === '(' && postChar === ')') { // already padded |
| 20 | + return true |
| 21 | + } |
| 22 | + } else if (idx === parent.arguments.length - 1) { // last arg |
| 23 | + if (preChar === '(' && postChar === ')' && postPostChar === ')') { // already padded |
| 24 | + return true |
| 25 | + } |
| 26 | + } else { // middle arg |
| 27 | + if (preChar === '(' && postChar === ')') { // already padded |
| 28 | + return true |
| 29 | + } |
39 | 30 | } |
| 31 | + return false |
40 | 32 | } |
41 | | - return false |
42 | | - } |
43 | 33 |
|
44 | | - if (node.parentNode && node.parentNode.type === 'CallExpression') { |
45 | | - // this function is getting called itself or |
46 | | - // it is getting passed in to another call expression |
47 | | - // the else statement is strictly never hit, but I think the code is easier to read this way |
48 | | - /* istanbul ignore else */ |
49 | | - if (node.parentNode.arguments.length && node.parentNode.arguments.indexOf(node) !== -1) { |
50 | | - // function passed in to another function. these are almost _always_ executed, e.g. |
51 | | - // UMD bundles, Browserify bundles, Node-style errbacks, Promise then()s and catch()s, etc. |
52 | | - if (!isPaddedArgument(node)) { // don't double-pad |
53 | | - magicString = magicString.insertLeft(node.start, '(') |
54 | | - .insertRight(node.end, ')') |
55 | | - } |
56 | | - } else if (node.parentNode.callee === node) { |
57 | | - // this function is getting immediately invoked, e.g. function(){}() |
58 | | - if (preChar !== '(') { |
59 | | - magicString.insertLeft(node.start, '(') |
60 | | - .insertRight(node.end, ')') |
| 34 | + if (node.type === 'FunctionExpression') { |
| 35 | + var prePreChar = jsString.charAt(node.start - 2) |
| 36 | + var preChar = jsString.charAt(node.start - 1) |
| 37 | + var postChar = jsString.charAt(node.end) |
| 38 | + var postPostChar = jsString.charAt(node.end + 1) |
| 39 | + |
| 40 | + if (parent && parent.type === 'CallExpression') { |
| 41 | + // this function is getting called itself or |
| 42 | + // it is getting passed in to another call expression |
| 43 | + // the else statement is strictly never hit, but I think the code is easier to read this way |
| 44 | + /* istanbul ignore else */ |
| 45 | + if (parent.arguments && parent.arguments.indexOf(node) !== -1) { |
| 46 | + // function passed in to another function. these are almost _always_ executed, e.g. |
| 47 | + // UMD bundles, Browserify bundles, Node-style errbacks, Promise then()s and catch()s, etc. |
| 48 | + if (!isPaddedArgument(node)) { // don't double-pad |
| 49 | + magicString = magicString.insertLeft(node.start, '(') |
| 50 | + .insertRight(node.end, ')') |
| 51 | + } |
| 52 | + } else if (parent.callee === node) { |
| 53 | + // this function is getting immediately invoked, e.g. function(){}() |
| 54 | + if (preChar !== '(') { |
| 55 | + magicString.insertLeft(node.start, '(') |
| 56 | + .insertRight(node.end, ')') |
| 57 | + } |
| 58 | + } |
61 | 59 | } |
62 | 60 | } |
63 | 61 | } |
64 | | - } |
| 62 | + }) |
65 | 63 |
|
66 | | - walk(ast, walkIt) |
67 | 64 | var out = magicString.toString() |
68 | 65 | if (opts.sourceMap) { |
69 | 66 | out += '\n//# sourceMappingURL=' + magicString.generateMap().toUrl() |
|
0 commit comments