Skip to content

Commit a9a37e3

Browse files
committed
Fix for nolanlawson#7: Not as optimized for Webpack as it could be. Adds ability to wrap functions that are elements of an array literal in an argument list
1 parent f1e03b3 commit a9a37e3

File tree

5 files changed

+75
-22
lines changed

5 files changed

+75
-22
lines changed

lib/index.js

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,16 @@ function optimizeJs (jsString, opts) {
2121
var postChar = jsString.charAt(node.end)
2222
var postPostChar = jsString.charAt(node.end + 1)
2323

24-
// assuming this node is an argument to a function, return true if it itself
25-
// is already padded with parentheses
24+
// assuming this node is an argument to a function or an element in an array,
25+
// return true if it itself is already padded with parentheses
2626
function isPaddedArgument (node) {
27-
var idx = node.parentNode.arguments.indexOf(node)
27+
var parentArray = node.parentNode.arguments ? node.parentNode.arguments : node.parentNode.elements
28+
var idx = parentArray.indexOf(node)
2829
if (idx === 0) { // first arg
2930
if (prePreChar === '(' && preChar === '(' && postChar === ')') { // already padded
3031
return true
3132
}
32-
} else if (idx === node.parentNode.arguments.length - 1) { // last arg
33+
} else if (idx === parentArray.length - 1) { // last arg
3334
if (preChar === '(' && postChar === ')' && postPostChar === ')') { // already padded
3435
return true
3536
}
@@ -41,24 +42,48 @@ function optimizeJs (jsString, opts) {
4142
return false
4243
}
4344

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, ')')
61-
}
45+
function isCallExpression (node) {
46+
return node && node.type === 'CallExpression'
47+
}
48+
49+
function isArrayExpression (node) {
50+
return node && node.type === 'ArrayExpression'
51+
}
52+
53+
// returns true iff node is an argument to a function call expression.
54+
function isArgumentToFunctionCall (node) {
55+
return isCallExpression(node.parentNode) &&
56+
node.parentNode.arguments.length &&
57+
node.parentNode.arguments.indexOf(node) !== -1
58+
}
59+
60+
// returns true iff node is an element of an array literal which is in turn
61+
// an argument to a function call expression.
62+
function isElementOfArrayArgumentToFunctionCall (node) {
63+
return isArrayExpression(node.parentNode) &&
64+
node.parentNode.elements.indexOf(node) !== -1 &&
65+
isArgumentToFunctionCall(node.parentNode)
66+
}
67+
68+
// returns true iff node is an IIFE.
69+
function isIIFE (node) {
70+
return isCallExpression(node.parentNode) &&
71+
node.parentNode.callee === node
72+
}
73+
74+
if (isArgumentToFunctionCall(node) || isElementOfArrayArgumentToFunctionCall(node)) {
75+
// function passed in to another function, either as an argument, or as an element
76+
// of an array argument. these are almost _always_ executed, e.g. webpack bundles,
77+
// UMD bundles, Browserify bundles, Node-style errbacks, Promise then()s and catch()s, etc.
78+
if (!isPaddedArgument(node)) { // don't double-pad
79+
magicString = magicString.insertLeft(node.start, '(')
80+
.insertRight(node.end, ')')
81+
}
82+
} else if (isIIFE(node)) {
83+
// this function is getting immediately invoked, e.g. function(){}()
84+
if (preChar !== '(') {
85+
magicString.insertLeft(node.start, '(')
86+
.insertRight(node.end, ')')
6287
}
6388
}
6489
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
!function(o){
2+
return o[0]();
3+
}([function(o,r,t){
4+
console.log("webpack style element 0");
5+
},function(o,r,t){
6+
console.log("webpack style element 1");
7+
},function(o,r,t){
8+
console.log("webpack style element 2");
9+
}]);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
!(function(o){
2+
return o[0]();
3+
})([(function(o,r,t){
4+
console.log("webpack style element 0");
5+
}),(function(o,r,t){
6+
console.log("webpack style element 1");
7+
}),(function(o,r,t){
8+
console.log("webpack style element 2");
9+
})]);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
!function(o){
2+
return o[0]();
3+
}([function(o,r,t){
4+
console.log("webpack style!");
5+
}]);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
!(function(o){
2+
return o[0]();
3+
})([(function(o,r,t){
4+
console.log("webpack style!");
5+
})]);

0 commit comments

Comments
 (0)