Skip to content

Commit bc694bc

Browse files
committed
Re: #24 - Added removeUseStricts option and optimized empty factory functions to make sure they default to undefined
1 parent 4c767f2 commit bc694bc

File tree

4 files changed

+66
-15
lines changed

4 files changed

+66
-15
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,8 @@ amdclean.clean({
387387
ignoreModules: [],
388388
// Determines if all of the require() method calls will be removed
389389
removeAllRequires: false,
390+
// Determines if all of the 'use strict' statements will be removed
391+
removeUseStricts: true,
390392
// Allows you to pass an expression that will override shimmed modules return values
391393
// e.g. { 'backbone': 'window.Backbone' }
392394
shimOverrides: {},

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "amdclean",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "A build tool that converts AMD code to standard JavaScript",
55
"main": "./src/amdclean",
66
"repository": {

src/amdclean.js

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! amdclean - v1.0.0 - 2014-02-09
1+
/*! amdclean - v1.1.0 - 2014-02-09
22
* http://gregfranko.com/amdclean
33
* Copyright (c) 2014 Greg Franko; Licensed MIT*/
44

@@ -34,13 +34,14 @@
3434
// The Public API object
3535
publicAPI = {
3636
// Current project version number
37-
'VERSION': '1.0.0',
37+
'VERSION': '1.1.0',
3838
// Default Options
3939
'defaultOptions': {
4040
'globalObject': false,
4141
'globalObjectName': 'amdclean',
4242
'rememberGlobalObject': true,
4343
'removeAllRequires': false,
44+
'removeUseStricts': true,
4445
'ignoreModules': [],
4546
'escodegen': {
4647
'comment': true
@@ -153,6 +154,16 @@
153154
_.isPlainObject(expression.callee) &&
154155
expression.callee.type === 'FunctionExpression');
155156
},
157+
// isUseStrict
158+
// -----------
159+
// Returns if the current AST node is a 'use strict' expression
160+
// e.g. 'use strict'
161+
'isUseStrict': function(expression) {
162+
return (expression &&
163+
_.isPlainObject(expression) &&
164+
expression.type === 'Literal' &&
165+
expression.value === 'use strict');
166+
},
156167
// isAMDConditional
157168
// ----------------
158169
// Returns if the current AST node is an if statement AMD check
@@ -353,7 +364,7 @@
353364
isOptimized = obj.isOptimized,
354365
callbackFunc = (function() {
355366
var cbFunc = obj.callbackFunc;
356-
if(cbFunc.type === 'Identifier') {
367+
if(cbFunc.type === 'Identifier' && cbFunc.name !== 'undefined') {
357368
cbFunc = {
358369
'type': 'FunctionExpression',
359370
'id': null,
@@ -383,7 +394,7 @@
383394
dependencyNames = obj.dependencyNames,
384395
options = publicAPI.options,
385396
cb = (function() {
386-
if(callbackFunc.type === 'Literal' || isOptimized === true) {
397+
if(callbackFunc.type === 'Literal' || (callbackFunc.type === 'Identifier' && callbackFunc.name === 'undefined') || isOptimized === true) {
387398
return callbackFunc;
388399
} else {
389400
return {
@@ -498,9 +509,13 @@
498509
returnStatementArg;
499510
// If the module has NO dependencies and the callback function is not empty
500511
if(!depLength && callbackFunc && callbackFunc.type === 'FunctionExpression' && callbackFunc.body && _.isArray(callbackFunc.body.body) && callbackFunc.body.body.length) {
501-
body = callbackFunc.body.body;
512+
// Filter 'use strict' statements
513+
body = _.filter(callbackFunc.body.body, function(node) {
514+
if(publicAPI.options.removeUseStricts === true) return !publicAPI.isUseStrict(node.expression);
515+
else return node;
516+
});
502517
// Returns an array of all return statements
503-
returnStatements = _.where(callbackFunc.body.body, { 'type': 'ReturnStatement' });
518+
returnStatements = _.where(body, { 'type': 'ReturnStatement' });
504519
// If there is a return statement
505520
if(returnStatements.length) {
506521
firstReturnStatement = returnStatements[0];
@@ -519,6 +534,12 @@
519534
}
520535
}
521536
}
537+
} else if(callbackFunc && callbackFunc.type === 'FunctionExpression' && callbackFunc.body && _.isArray(callbackFunc.body.body) && callbackFunc.body.body.length === 0) {
538+
callbackFunc = {
539+
'type': 'Identifier',
540+
'name': 'undefined'
541+
};
542+
depLength = 0;
522543
}
523544
return callbackFunc;
524545
}()),

test/specs/convert.js

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,34 @@ describe('amdclean specs', function() {
99
it('should convert function return values to immediately invoked function declarations', function() {
1010
var AMDcode = "define('example', [], function() {});",
1111
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
12-
standardJavaScript = "var example=function (){}();";
12+
standardJavaScript = "var example=undefined;";
1313
expect(cleanedCode).toBe(standardJavaScript);
1414
});
1515

1616
it('should passing a file path instead of the code directly', function() {
1717
var cleanedCode = amdclean.clean({ filePath: __dirname + '/../filePathTest.js', escodegen: { format: { compact: true } } }),
18-
standardJavaScript = "var example=function (){}();";
18+
standardJavaScript = "var example=undefined;";
1919
expect(cleanedCode).toBe(standardJavaScript);
2020
});
2121

2222
it('should correctly set callback parameters to the callback function', function() {
23-
var AMDcode = "define('example', ['example1', 'example2'], function(one, two) {});",
23+
var AMDcode = "define('example', ['example1', 'example2'], function(one, two) {var test = true;});",
2424
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
25-
standardJavaScript = "var example=function (one,two){}(example1,example2);";
25+
standardJavaScript = "var example=function (one,two){var test=true;}(example1,example2);";
2626
expect(cleanedCode).toBe(standardJavaScript);
2727
});
2828

2929
it('should correctly normalize relative file paths', function() {
30-
var AMDcode = "define('./modules/example', ['example1', 'example2'], function(one, two) {});",
30+
var AMDcode = "define('./modules/example', ['example1', 'example2'], function(one, two) {var test = true;});",
3131
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
32-
standardJavaScript = "var modules_example=function (one,two){}(example1,example2);";
32+
standardJavaScript = "var modules_example=function (one,two){var test=true;}(example1,example2);";
3333
expect(cleanedCode).toBe(standardJavaScript);
3434
});
3535

3636
it('should correctly normalize multi-level relative file paths', function() {
37-
var AMDcode = "define('./foo/prototype/commonMethodName.js', ['example1', 'example2'], function(one, two) {});",
37+
var AMDcode = "define('./foo/prototype/commonMethodName.js', ['example1', 'example2'], function(one, two) { var test = true;});",
3838
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
39-
standardJavaScript = "var foo_prototype_commonMethodNamejs=function (one,two){}(example1,example2);";
39+
standardJavaScript = "var foo_prototype_commonMethodNamejs=function (one,two){var test=true;}(example1,example2);";
4040
expect(cleanedCode).toBe(standardJavaScript);
4141
});
4242

@@ -155,13 +155,41 @@ describe('amdclean specs', function() {
155155
expect(cleanedCode).toBe(standardJavaScript);
156156
});
157157

158+
it('should optimize basic define() methods that have an empty factory function', function() {
159+
var AMDcode = "define('optimized', function () {});",
160+
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
161+
standardJavaScript = "var optimized=undefined;";
162+
expect(cleanedCode).toBe(standardJavaScript);
163+
});
164+
158165
it('should optimize more complex define() methods that return a function expression', function() {
159166
var AMDcode = "define('optimized', function () { return function ( thing ) { var anotherThing = true; return !isNaN( parseFloat( thing ) ) && isFinite( thing );};});",
160167
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
161168
standardJavaScript = "var optimized=function(thing){var anotherThing=true;return!isNaN(parseFloat(thing))&&isFinite(thing);};";
162169
expect(cleanedCode).toBe(standardJavaScript);
163170
});
164171

172+
it('should optimize more complex define() methods that have a "use strict" statement and return a function expression', function() {
173+
var AMDcode = "define('optimized', function () { 'use strict'; return function ( thing ) { return !isNaN( parseFloat( thing ) ) && isFinite( thing );};});",
174+
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
175+
standardJavaScript = "var optimized=function(thing){return!isNaN(parseFloat(thing))&&isFinite(thing);};";
176+
expect(cleanedCode).toBe(standardJavaScript);
177+
});
178+
179+
it('should not optimize more complex define() methods that have a "use strict" statement and return a function expression, but have also set the removeUseStricts option to false', function() {
180+
var AMDcode = "define('optimized', function () { 'use strict'; return function ( thing ) { return !isNaN( parseFloat( thing ) ) && isFinite( thing );};});",
181+
cleanedCode = amdclean.clean({ removeUseStricts: false, code: AMDcode, escodegen: { format: { compact: true } } }),
182+
standardJavaScript = "var optimized=function (){'use strict';return function(thing){return!isNaN(parseFloat(thing))&&isFinite(thing);};}();";
183+
expect(cleanedCode).toBe(standardJavaScript);
184+
});
185+
186+
it('should not optimize define() methods that have logic outside of the return statement', function() {
187+
var AMDcode = "define('optimized', [], function () { var test = true; return function ( thing ) { var anotherThing = true; return !isNaN( parseFloat( thing ) ) && isFinite( thing );};});",
188+
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),
189+
standardJavaScript = "var optimized=function (){var test=true;return function(thing){var anotherThing=true;return!isNaN(parseFloat(thing))&&isFinite(thing);};}();";
190+
expect(cleanedCode).toBe(standardJavaScript);
191+
});
192+
165193
it('should not optimize define() methods that have one or more dependencies', function() {
166194
var AMDcode = "define('optimized', ['exampleDependency'], function () { return function ( thing ) { var anotherThing = true; return !isNaN( parseFloat( thing ) ) && isFinite( thing );};});",
167195
cleanedCode = amdclean.clean({ code: AMDcode, escodegen: { format: { compact: true } } }),

0 commit comments

Comments
 (0)