Skip to content

Commit

Permalink
WIP: Changed build process to generate self executing closures arroun…
Browse files Browse the repository at this point in the history
…d modules.

TODO: Fix modules not  returning their export.
TODO: Test.

Fixes #153.
  • Loading branch information
Joscha Rohmann authored and Kanaye committed Dec 2, 2016
1 parent b324a83 commit 2f643c0
Showing 1 changed file with 84 additions and 8 deletions.
92 changes: 84 additions & 8 deletions build/tasks/build.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
module.exports = function (grunt) {
var blocks = require('blocks');
var esprima = require('esprima');
var escodegen = require('escodegen');
var estrvarse = require('estraverse');
var definedModuleNames = {};
var requirejsConfig = {};
var requirejsOptions = {
baseUrl: 'src',
Expand All @@ -8,7 +11,7 @@ module.exports = function (grunt) {
optimize: 'none',
skipSemiColonInsertion: true,
onBuildWrite: function (name, path, contents) {
var rdefineEnd = /\}\);[^}\w]*$/;
var rdefineEnd = /\}\);[^}\w]*$/;

if (/.\/var\//.test(path)) {
contents = contents
Expand All @@ -17,6 +20,46 @@ module.exports = function (grunt) {

} else {
contents = contents
.replace(/\/\*\s*ExcludeStart\s*\*\/[\w\W]*?\/\*\s*ExcludeEnd\s*\*\//ig, '')
.replace(/\/\/\s*BuildExclude\n\r?[\w\W]*?\n\r?/ig, '');
var ast = esprima.parse(contents, {
tokens: true,
comment: true,
range: true
});

estrvarse.attachComments(ast, ast.comments, ast.tokens);

if (ast.body[0].expression.callee.name == 'define') {
var moduleExpression = findModuleExpressionArgument(ast.body[0].expression.arguments);
if (!moduleExpression || !moduleExpression.body.body[0] || moduleExpression.body.body[0].type == 'ReturnStatement') {
// Null out empty define statements e.g. define(['./query/ready', '...'])
// and expresions without an expression or only an return statement e.g. define([], function () { return blocks; })
contents = '';
} else {
var moduleName;
try {
moduleName = findModuleExportIdentifier(moduleExpression.body.body) || /\/(\w+).?j?s?$/.exec(name)[1];
} catch(e) {}
if (moduleName && definedModuleNames[moduleName] && definedModuleNames[moduleName] != path) {
grunt.fail.warn('[NamingConflict]: Module ' + path + ' tried to define ' + moduleName + ' which is already defined by ' + definedModuleNames[moduleName] + ' !');
} else if (moduleName){
definedModuleNames[moduleName] = path;
}
ast = wrapModuleAst(moduleExpression, moduleName);
contents = escodegen.generate(ast, {
format: {
indent: {
style: ' ',
base: 0,
adjustMultilineComment: true
}
},
comment: true
});
}
}
/* contents = contents
.replace(/\s*return\s+[^\}]+(\}\);[^\w\}]*)$/, '$1')
// Multiple exports
.replace(/\s*exports\.\w+\s*=\s*\w+;/g, '');
Expand All @@ -29,19 +72,52 @@ module.exports = function (grunt) {
// Remove anything wrapped with
// /* ExcludeStart */ /* ExcludeEnd */
// or a single line directly after a // BuildExclude comment
contents = contents
.replace(/\/\*\s*ExcludeStart\s*\*\/[\w\W]*?\/\*\s*ExcludeEnd\s*\*\//ig, '')
.replace(/\/\/\s*BuildExclude\n\r?[\w\W]*?\n\r?/ig, '');

// Remove empty definitions
contents = contents
.replace(/define\(\[[^\]]+\]\)[\W\n]+$/, '');
/* contents = contents
.replace(/define\(\[[^\]]+\]\)[\W\n]+$/, '');*/

}

return contents;
}
};

function findModuleExportIdentifier (module) {
for (var i = module.length -1 ; i >= 0; i--) {
var expression = module[i];
if (expression.type == 'ReturnStatement') {
return expression.argument.name;
}
}
throw new Error('No return statement');
}

function findModuleExpressionArgument(args) {
for (var i in args) {
var arg = args[i];
if (arg.type == 'FunctionExpression') {
return arg;
}
}
}


function wrapModuleAst (node, exportName) {
var wrapedModule;
var bodyNode;
if (exportName) {
wrapedModule = esprima.parse('var ' + exportName + ' = (function () { })();');
bodyNode = wrapedModule.body[0].declarations[0].init.callee.body;
} else {
wrapedModule = esprima.parse('(function () { })();');
bodyNode = wrapedModule.body[0].expression.callee.body;
}
// insert body of the original "define"-function to the
bodyNode.body = node.body.body;
return wrapedModule;
}

var names = ['query', 'mvc', 'node'];
names.forEach(function (name) {
grunt.config.set('name', name);
Expand All @@ -54,7 +130,7 @@ module.exports = function (grunt) {
grunt.registerTask('build', function () {
var tasks = [];
for (var i = 0; i < arguments.length; i++) {
tasks.push('requirejs:' + arguments[i])
tasks.push('requirejs:' + arguments[i]);
}
grunt.task.run(tasks.length ? tasks : 'requirejs');
});
Expand Down

0 comments on commit 2f643c0

Please sign in to comment.