|
1 | | -/*! amdclean - v0.6.2 - 2014-01-26 |
| 1 | +/*! amdclean - v0.7.0 - 2014-02-08 |
2 | 2 | * http://gregfranko.com/amdclean |
3 | 3 | * Copyright (c) 2014 Greg Franko; Licensed MIT*/ |
4 | 4 |
|
|
34 | 34 | // The Public API object |
35 | 35 | publicAPI = { |
36 | 36 | // Current project version number |
37 | | - 'VERSION': '0.6.2', |
| 37 | + 'VERSION': '0.7.0', |
38 | 38 | // Default Options |
39 | 39 | 'defaultOptions': { |
40 | 40 | 'globalObject': false, |
41 | 41 | 'globalObjectName': 'amdclean', |
42 | 42 | 'rememberGlobalObject': true, |
43 | 43 | 'removeAllRequires': false, |
44 | 44 | 'ignoreModules': [], |
45 | | - 'escodegen': {}, |
| 45 | + 'escodegen': { |
| 46 | + 'comment': true |
| 47 | + }, |
46 | 48 | 'esprima': { |
47 | 49 | 'comment': true, |
48 | | - 'loc': true |
| 50 | + 'loc': true, |
| 51 | + 'range': true, |
| 52 | + 'tokens': true |
49 | 53 | }, |
50 | 54 | 'globalModules': [], |
51 | 55 | 'commentCleanName': 'amdclean', |
|
346 | 350 | 'convertToIIFEDeclaration': function(obj) { |
347 | 351 | var moduleName = obj.moduleName, |
348 | 352 | callbackFuncParams = obj.callbackFuncParams, |
| 353 | + isOptimized = obj.isOptimized, |
349 | 354 | callbackFunc = (function() { |
350 | 355 | var cbFunc = obj.callbackFunc; |
351 | 356 | if(cbFunc.type === 'Identifier') { |
|
377 | 382 | }()), |
378 | 383 | dependencyNames = obj.dependencyNames, |
379 | 384 | options = publicAPI.options, |
380 | | - cb = { |
381 | | - 'type': 'CallExpression', |
382 | | - 'callee': { |
383 | | - 'type': 'FunctionExpression', |
384 | | - 'id': { |
385 | | - 'type': 'Identifier', |
386 | | - 'name': '' |
387 | | - }, |
388 | | - 'params': callbackFuncParams, |
389 | | - 'defaults': [], |
390 | | - 'body': callbackFunc.body, |
391 | | - 'rest': callbackFunc.rest, |
392 | | - 'generator': callbackFunc.generator, |
393 | | - 'expression': callbackFunc.expression |
394 | | - }, |
395 | | - 'arguments': dependencyNames |
396 | | - }, |
| 385 | + cb = (function() { |
| 386 | + if(callbackFunc.type === 'Literal' || isOptimized === true) { |
| 387 | + return callbackFunc; |
| 388 | + } else { |
| 389 | + return { |
| 390 | + 'type': 'CallExpression', |
| 391 | + 'callee': { |
| 392 | + 'type': 'FunctionExpression', |
| 393 | + 'id': { |
| 394 | + 'type': 'Identifier', |
| 395 | + 'name': '' |
| 396 | + }, |
| 397 | + 'params': callbackFuncParams, |
| 398 | + 'defaults': [], |
| 399 | + 'body': callbackFunc.body, |
| 400 | + 'rest': callbackFunc.rest, |
| 401 | + 'generator': callbackFunc.generator, |
| 402 | + 'expression': callbackFunc.expression |
| 403 | + }, |
| 404 | + 'arguments': dependencyNames |
| 405 | + }; |
| 406 | + } |
| 407 | + }()), |
397 | 408 | updatedNode = (function() { |
398 | 409 | if(options.globalObject === true && options.globalObjectName) { |
399 | 410 | return { |
|
414 | 425 | 'raw': "" + moduleName + "" |
415 | 426 | } |
416 | 427 | }, |
417 | | - "right": cb |
| 428 | + 'right': cb |
418 | 429 | } |
419 | 430 | }; |
420 | 431 | } else { |
|
443 | 454 | 'convertToFunctionExpression': function(obj) { |
444 | 455 | var isDefine = obj.isDefine, |
445 | 456 | isRequire = obj.isRequire, |
| 457 | + isOptimized = false, |
446 | 458 | node = obj.node, |
447 | 459 | moduleName = obj.moduleName, |
448 | 460 | dependencies = obj.dependencies, |
|
478 | 490 | } |
479 | 491 | return deps; |
480 | 492 | }()), |
481 | | - callbackFunc = obj.moduleReturnValue, |
| 493 | + callbackFunc = (function() { |
| 494 | + var callbackFunc = obj.moduleReturnValue, |
| 495 | + body, |
| 496 | + returnStatements, |
| 497 | + firstReturnStatement; |
| 498 | + // If the module has NO dependencies and the callback function is not empty |
| 499 | + if(!depLength && callbackFunc && callbackFunc.type === 'FunctionExpression' && callbackFunc.body && _.isArray(callbackFunc.body.body) && callbackFunc.body.body.length) { |
| 500 | + body = callbackFunc.body.body; |
| 501 | + // Returns an array of all return statements |
| 502 | + returnStatements = _.where(callbackFunc.body.body, { 'type': 'ReturnStatement' }); |
| 503 | + // If there is a return statement |
| 504 | + if(returnStatements.length) { |
| 505 | + firstReturnStatement = returnStatements[0]; |
| 506 | + // If something other than a function expression is getting returned |
| 507 | + // and there is more than one AST child node in the factory function |
| 508 | + // return early |
| 509 | + if(!publicAPI.isFunctionExpression(firstReturnStatement) && body.length > 1) { |
| 510 | + return callbackFunc; |
| 511 | + } else { |
| 512 | + // Optimize the AMD module by setting the callback function to the return statement argument |
| 513 | + callbackFunc = firstReturnStatement.argument; |
| 514 | + isOptimized = true; |
| 515 | + if(callbackFunc.params) { |
| 516 | + depLength = callbackFunc.params.length; |
| 517 | + } |
| 518 | + } |
| 519 | + } |
| 520 | + } |
| 521 | + return callbackFunc; |
| 522 | + }()), |
482 | 523 | hasReturnStatement = (function() { |
483 | 524 | var returns = []; |
484 | 525 | if(callbackFunc && callbackFunc.body && _.isArray(callbackFunc.body.body)) { |
|
533 | 574 | dependencyNames: dependencyNames, |
534 | 575 | callbackFuncParams: callbackFuncParams, |
535 | 576 | hasExportsParam: hasExportsParam, |
536 | | - callbackFunc: callbackFunc |
| 577 | + callbackFunc: callbackFunc, |
| 578 | + isOptimized: isOptimized |
537 | 579 | }); |
538 | 580 | } else if(isRequire) { |
539 | 581 | return publicAPI.convertToIIFE({ |
|
712 | 754 | 'createAst': function(obj) { |
713 | 755 | var filePath = obj.filePath, |
714 | 756 | code = obj.code || (filePath && publicAPI.env === 'node' ? publicAPI.readFile(filePath) : ''), |
715 | | - esprimaDefaultOptions = publicAPI.defaultOptions.esprima, |
716 | | - esprimaOptions = _.extend(esprimaDefaultOptions, (_.isPlainObject(obj.esprima) ? obj.esprima : {})); |
| 757 | + esprimaOptions = publicAPI.options.esprima; |
717 | 758 | if(!code) { |
718 | 759 | throw new Error(publicAPI.errorMsgs.emptyCode); |
719 | 760 | } else { |
|
751 | 792 | // ------------ |
752 | 793 | // Returns standard JavaScript generated by Escodegen |
753 | 794 | 'generateCode': function(ast, options) { |
| 795 | + var esprimaOptions = options.esprima || {}, |
| 796 | + escodegenOptions = options.escodegen || {}; |
754 | 797 | if(!_.isPlainObject(escodegen) || !_.isFunction(escodegen.generate)) { |
755 | 798 | throw new Error(publicAPI.errorMsgs.escodegen); |
756 | 799 | } |
757 | | - return escodegen.generate(ast, options); |
| 800 | + // Check if both the esprima and escodegen comment options are set to true |
| 801 | + if(esprimaOptions.comment === true && escodegenOptions.comment === true) { |
| 802 | + // Needed to keep source code comments when generating the code with escodegen |
| 803 | + ast = escodegen.attachComments(ast, ast.comments, ast.tokens); |
| 804 | + } |
| 805 | + return escodegen.generate(ast, escodegenOptions); |
758 | 806 | }, |
759 | 807 | // clean |
760 | 808 | // ----- |
761 | 809 | // Creates an AST using Esprima, traverse and updates the AST using Estraverse, and generates standard JavaScript using Escodegen. |
762 | 810 | 'clean': function(obj) { |
763 | 811 | var code = {}, |
764 | 812 | ast = {}, |
765 | | - options = {}; |
766 | | - |
767 | | - publicAPI.options = publicAPI.defaultOptions; |
768 | | - if(_.isPlainObject(obj)) { |
769 | | - publicAPI.options = options = _.extend({}, publicAPI.options, obj); |
770 | | - } |
| 813 | + options = {}, |
| 814 | + defaultOptions = _.cloneDeep(publicAPI.defaultOptions) || {}, |
| 815 | + userOptions = _.cloneDeep(obj) || {}; |
| 816 | + publicAPI.options = options = _.merge(defaultOptions, userOptions); |
771 | 817 | if(!_ || !_.isPlainObject) { |
772 | 818 | throw new Error(publicAPI.errorMsgs.lodash); |
773 | 819 | } |
|
858 | 904 | 'kind': 'var' |
859 | 905 | }); |
860 | 906 | } |
861 | | - return publicAPI.generateCode(ast, options.escodegen); |
| 907 | + return publicAPI.generateCode(ast, options); |
862 | 908 | } |
863 | 909 | }; |
864 | 910 | // Returns the public API for node and web environments |
|
0 commit comments