Skip to content
This repository has been archived by the owner on Oct 9, 2020. It is now read-only.

Commit

Permalink
compile refactor separation
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford committed Jun 18, 2015
1 parent 9a7fd5a commit 7a71fdb
Showing 1 changed file with 128 additions and 115 deletions.
243 changes: 128 additions & 115 deletions lib/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,158 +13,171 @@ var compilerMap = {
};

exports.compileLoad = compileLoad;
function compileLoad(loader, load, opts, compilers) {
return Promise.resolve()
.then(function() {
var format = load.metadata.format;
if (load.metadata.build === false) {
return {};
}
else if (format in compilerMap) {
// note which compilers we used
if (compilers)
compilers[format] = true;

return require(compilerMap[format]).compile(load, opts, loader);
}
else if (format == 'defined') {
return {source: ''};
}
else {
throw new Error("Unknown format " + format);
}
});
function compileLoad(loader, load, opts) {
if (load.metadata.build === false)
return {};

var format = load.metadata.format;

if (format in compilerMap)
return require(compilerMap[format]).compile(load, opts, loader);
else if (format == 'defined')
return { source: '' };
else
throw new Error("Unknown module format " + format);
}

// compiledTree is load tree with "source" and "output" set
exports.compileOutputs = compileOutputs;
function compileOutputs(loader, tree, opts, sfxEntryPoints) {
var modules = Object.keys(tree);

// store plugins with a bundle hook to allow post-processing
var plugins = {};
// store compiler list for sfx bundling
var pluginLoads = {};
var compilers = {};
var outputs = [];

var usesBabelHelpersGlobal, usesTraceurRuntimeGlobal;
// output array to create
var outputs = [];

return Promise.all(modules.map(function(name) {
var load = tree[name];
return Promise.resolve()

if (load === null)
throw new TypeError('"' + name + '" was defined via a bundle, so can only be used for subtraction or union operations.');
// pre-processing
.then(function() {

if (sfxEntryPoints && load.metadata.loader && load.metadata.build === false)
outputs.push('System.registerDynamic("' + load.name + '", [], false, function() { console.log("SystemJS Builder - Plugin for ' + load.name + ' does not support sfx builds"); });\n');
modules.forEach(function(name) {
var load = tree[name];

if (load.metadata.build === false)
return;
if (load === null)
throw new TypeError('"' + name + '" was defined via a bundle, so can only be used for subtraction or union operations.');

// support plugin "bundle" reduction hook
var plugin = load.metadata.loaderModule;
if (plugin) {
var entry = plugins[load.metadata.loader] = plugins[load.metadata.loader] || {
loads: [],
bundle: plugin.bundle
};
entry.loads.push(load);
}
// group plugin loads by plugin for bundle hook
var plugin = load.metadata.loaderModule;
if (plugin) {
if (load.metadata.build === false && sfxEntryPoints)
throw new TypeError("Plugin '" + load.metadata.loader + '" does not support SFX builds.');

return Promise.resolve(compileLoad(loader, load, opts, compilers))
.then(function(output) {
outputs.push(output);
if (plugin.bundle && load.metadata.build !== false) {
var loads = pluginLoads[load.metadata.loader] = pluginLoads[load.metadata.loader] || [];
loads.push(load);
}
}
});
}))
})

// create load output objects
.then(function() {
usesBabelHelpersGlobal = modules.some(function(name) {
return tree[name].metadata.usesBabelHelpersGlobal;
});
usesTraceurRuntimeGlobal = modules.some(function(name) {
return tree[name].metadata.usesTraceurRuntimeGlobal;
});
return Promise.all(modules.map(function(name) {
var load = tree[name];

if (load.metadata.build === false)
return;

// apply plugin "bundle" hook
return Promise.all(Object.keys(plugins).map(function(pluginName) {
var entry = plugins[pluginName];
if (entry.bundle)
return Promise.resolve(entry.bundle.call(loader.pluginLoader, entry.loads, opts))
.then(outputs.push.bind(outputs));
if (load.metadata.loaderModule && load.metadata.loaderModule.bundle)
return;

return Promise.resolve(compileLoad(loader, load, opts))
.then(function(output) {
outputs.push(output);
});
}));
})

// create bundle plugin outputs
.then(function() {
// normal bundle
if (!sfxEntryPoints)
return;

// include compiler helpers
Object.keys(compilers).forEach(function(format) {
compiler = require(compilerMap[format]);
if (compiler.sfx) {
var sfx = compiler.sfx(loader);
if (sfx)
outputs.unshift(sfx);
}
});
return Promise.all(Object.keys(pluginLoads).map(function(pluginName) {
var loads = pluginLoads[pluginName];
var bundle = tree[pluginName].metadata.loaderModule.bundle;

return Promise.resolve(bundle.call(loader.pluginLoader, entry.loads, opts))
.then(function(output) {
if (output instanceof Array)
outputs = outputs.concat(output);
else
outputs.push(output);
});
}));
})

// next wrap with the core code
return asp(fs.readFile)(path.resolve(__dirname, '../templates/sfx-core.js'))
.then(function(sfxcore) {
outputs.unshift(sfxcore.toString(), "(['" + sfxEntryPoints.join('\', \'') + "'], function(System) {\n");

outputs.push("})");

return asp(fs.readFile)(path.resolve(__dirname, '../templates/sfx-' + opts.sfxFormat + '.js'))
})
// then include the sfx module format wrapper
.then(function(formatWrapper) {
outputs.push(formatWrapper.toString());
})
// then wrap with the runtime
.then(function() {
if (opts.runtime && usesBabelHelpersGlobal)
return getModuleSource(loader, 'babel/external-helpers')
.then(function(source) {
outputs.unshift(source);
});
})
.then(function() {
if (opts.runtime && usesTraceurRuntimeGlobal)
return getModuleSource(loader, 'traceur-runtime')
.then(function(source) {
// protect System global clobbering
outputs.unshift("(function(){ var curSystem = typeof System != 'undefined' ? System : undefined;\n" + source + "\nSystem = curSystem; })();");
});
})
.then(function() {
outputs = outputs.map(stripMeta);
.then(function() {
if (sfxEntryPoints)
return wrapSFXOutputs(loader, tree, outputs, sfxEntryPoints, opts);
else
return outputs;
});
}

exports.wrapSFXOutputs = wrapSFXOutputs;
function wrapSFXOutputs(loader, tree, outputs, sfxEntryPoints, opts) {
var compilers = {};

var modules = Object.keys(tree);

// determine compilers used
modules.forEach(function(name) {
var load = tree[name];
if (load.metadata.build !== false)
compilers[load.metadata.format] = true;
});

// include compiler helpers at the beginning of outputs
Object.keys(compilers).forEach(function(format) {
compiler = require(compilerMap[format]);
if (compiler.sfx) {
var sfx = compiler.sfx(loader);
if (sfx)
outputs.unshift(sfx);
}
});

// next wrap with the core code
return asp(fs.readFile)(path.resolve(__dirname, '../templates/sfx-core.js'))
.then(function(sfxcore) {
outputs.unshift(sfxcore.toString(), "(['" + sfxEntryPoints.join('\', \'') + "'], function(System) {\n");

outputs.push("})");

return asp(fs.readFile)(path.resolve(__dirname, '../templates/sfx-' + opts.sfxFormat + '.js'))
})
// then include the sfx module format wrapper
.then(function(formatWrapper) {
outputs.push(formatWrapper.toString());
})
// then wrap with the runtime
.then(function() {
var usesBabelHelpersGlobal = modules.some(function(name) {
return tree[name].metadata.usesBabelHelpersGlobal;
});
if (opts.runtime && usesBabelHelpersGlobal)
return getModuleSource(loader, 'babel/external-helpers')
.then(function(source) {
outputs.unshift(source);
});
})
.then(function() {
var usesTraceurRuntimeGlobal = modules.some(function(name) {
return tree[name].metadata.usesTraceurRuntimeGlobal;
});
if (opts.runtime && usesTraceurRuntimeGlobal)
return getModuleSource(loader, 'traceur-runtime')
.then(function(source) {
// protect System global clobbering
outputs.unshift("(function(){ var curSystem = typeof System != 'undefined' ? System : undefined;\n" + source + "\nSystem = curSystem; })();");
});
})
.then(function() {
return outputs;
});
}

exports.stripMeta = stripMeta;
function stripMeta(output) {
// TODO
// strip meta syntax from individual output objects in source-map compliant way
// meta is any amount of comments followed by "blah";?
// any amount of meta lines can be present
// regular expressions at https://github.com/jspm/jspm-cli/blob/master/lib/build.js#L265
return output;
}

exports.attachCompilers = function(loader) {
Object.keys(compilerMap).forEach(function(compiler) {
var attach = require(compilerMap[compiler]).attach;
if (attach)
attach(loader);
});
}

};

function getModuleSource(loader, module) {

return loader.normalize(module)
.then(function(normalized) {
return loader.locate({ name: normalized, metadata: {} });
Expand Down

0 comments on commit 7a71fdb

Please sign in to comment.