mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			174 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| /*
 | |
| 	MIT License http://www.opensource.org/licenses/mit-license.php
 | |
| 	Author Tobias Koppers @sokra
 | |
| */
 | |
| var resolve = require("./resolve");
 | |
| var fs = require("fs");
 | |
| var path = require("path");
 | |
| 
 | |
| /**
 | |
|  * execLoaders
 | |
|  * @param context {string}			the context from which this request is coming
 | |
|  * @param request {string}			the compile request string
 | |
|  * @param loaders {string[]}		the absolute filenames of the loaders
 | |
|  * @param filenames {string[]}		the filenames of "contents"
 | |
|  * @param contents {Buffer[]}		read contents
 | |
|  * @param options {object}			the options of the module system
 | |
|  * @param callback {function}		(err, resultingJavascriptCode)
 | |
|  */
 | |
| module.exports = function(context, request, loaders, filenames, contents, cacheEntry, options, callback) {
 | |
| 	var loaderFunctions, cacheable = true;
 | |
| 	if(loaders.length === 0) {
 | |
| 		// if no loaders are used, the file content is the resulting code
 | |
| 		var result = contents[0].toString("utf-8");
 | |
| 		if(cacheEntry)
 | |
| 			cacheEntry.save(result);
 | |
| 		callback(null, result);
 | |
| 	} else {
 | |
| 		// try to load all loaders
 | |
| 		// TODO this doesn't reload the loader if it has changed
 | |
| 		// TODO to support watch mode better, fix that
 | |
| 		loaderFunctions = [];
 | |
| 		try {
 | |
| 			loaders.forEach(function(name) {
 | |
| 				var loader = require(name);
 | |
| 				loaderFunctions.push(loader);
 | |
| 			});
 | |
| 		} catch(e) {
 | |
| 			callback(e);
 | |
| 			return;
 | |
| 		}
 | |
| 		// iterate over the loaders, asynchron
 | |
| 		contents.unshift(null);
 | |
| 		nextLoader.apply(null, contents);
 | |
| 	}
 | |
| 	function nextLoader(/* err, paramBuffer1, paramBuffer2, ...*/) {
 | |
| 		var args = Array.prototype.slice.apply(arguments);
 | |
| 		var err = args.shift();
 | |
| 		if(err) {
 | |
| 			// a loader emitted an error
 | |
| 			callback(err);
 | |
| 			return;
 | |
| 		}
 | |
| 		// if loaders are remaining
 | |
| 		if(loaderFunctions.length > 0) {
 | |
| 			var loaderCacheable = false;
 | |
| 			var async = false;
 | |
| 			var done = false;
 | |
| 			try {
 | |
| 				// prepare the loader "this" context
 | |
| 				// see "Loader Specification" in wiki
 | |
| 				var loaderContext = {
 | |
| 					context: context,
 | |
| 					request: request,
 | |
| 					filenames: filenames,
 | |
| 					exec: function(code, filename) {
 | |
| 						var Module = require("module");
 | |
| 						var m = new Module("exec in " + request, module);
 | |
| 						m.filename = filenames[0];
 | |
| 						m.paths = Module._nodeModulePaths(path.dirname(filenames[0]));
 | |
| 						m._compile(code, filename);
 | |
| 						return m.exports;
 | |
| 					},
 | |
| 					resolve: function(context, path, cb) {
 | |
| 						resolve(context, "!"+path, options.resolve, cb);
 | |
| 					},
 | |
| 					cacheable: function(value) {
 | |
| 						if(value === undefined) value = true;
 | |
| 						loaderCacheable = value;
 | |
| 					},
 | |
| 					dependency: function(filename) {
 | |
| 						options.events.emit("dependency", filename);
 | |
| 						if(cacheEntry)
 | |
| 							cacheEntry.add(filename);
 | |
| 					},
 | |
| 					clearDependencies: function(filename) {
 | |
| 						if(cacheEntry)
 | |
| 							cacheEntry.clear();
 | |
| 					},
 | |
| 					async: function() {
 | |
| 						async = true;
 | |
| 						return loaderContext.callback;
 | |
| 					},
 | |
| 					callback: function(err) {
 | |
| 						async = true;
 | |
| 						if(done) {
 | |
| 							// loader is already "done", so we cannot use the callback function
 | |
| 							// for better debugging we print the error on the console
 | |
| 							if(err && err.stack) console.error(err.stack);
 | |
| 							else if(err) console.error(err);
 | |
| 							else console.error(new Error("loader returned multiple times").stack);
 | |
| 							return;
 | |
| 						}
 | |
| 						done = true;
 | |
| 						contents = [err];
 | |
| 						for(var i = 0; i < arguments.length; i++) {
 | |
| 							var arg = arguments[i];
 | |
| 							if(arg instanceof Buffer)
 | |
| 								contents.push(arg);
 | |
| 							else if(typeof arg === "string")
 | |
| 								contents.push(new Buffer(arg, "utf-8"));
 | |
| 						}
 | |
| 						loaderFinished.apply(null, arguments);
 | |
| 					},
 | |
| 					web: true,
 | |
| 					debug: options.debug,
 | |
| 					minimize: options.minimize,
 | |
| 					values: undefined,
 | |
| 					options: options,
 | |
| 					buffers: args
 | |
| 				};
 | |
| 
 | |
| 				// add additional loader context params or functions
 | |
| 				if(options.loader) for(var key in options.loader)
 | |
| 					loaderContext[key] = options.loader[key];
 | |
| 
 | |
| 				// convert all parameters to strings if they are Buffers
 | |
| 				var params = [];
 | |
| 				args.forEach(function(arg) {
 | |
| 					if(arg instanceof Buffer)
 | |
| 						params.push(arg.toString("utf-8"));
 | |
| 					else
 | |
| 						params.push(arg);
 | |
| 				});
 | |
| 
 | |
| 				// exec to loader
 | |
| 				var retVal = loaderFunctions.pop().apply(loaderContext, params);
 | |
| 
 | |
| 				// if it isn't asynchron, use the return value
 | |
| 				if(!async) {
 | |
| 					done = true;
 | |
| 					if(retVal instanceof Buffer)
 | |
| 						retVal = retVal;
 | |
| 					else if(typeof retVal === "string")
 | |
| 						retVal = new Buffer(retVal, "utf-8");
 | |
| 					loaderFinished(retVal === undefined ? new Error("loader did not return a value") : null, retVal);
 | |
| 				}
 | |
| 
 | |
| 				function loaderFinished() {
 | |
| 					if(!loaderCacheable)
 | |
| 						cacheable = false;
 | |
| 
 | |
| 					nextLoader.apply(null, arguments);
 | |
| 				}
 | |
| 			} catch(e) {
 | |
| 				// ups. loader throwed an exeception
 | |
| 				if(!done) {
 | |
| 					done = true;
 | |
| 					callback("Loader throwed exeception: " + (typeof e === "object" && e.stack ? e.stack : e));
 | |
| 				} else {
 | |
| 					// loader is already "done", so we cannot use the callback function
 | |
| 					// for better debugging we print the error on the console
 | |
| 					if(typeof e === "object" && e.stack) console.error(e.stack);
 | |
| 					else console.error(e);
 | |
| 				}
 | |
| 				return;
 | |
| 			}
 | |
| 		} else {
 | |
| 			var result = args[0].toString("utf-8");
 | |
| 			if(cacheEntry && cacheable)
 | |
| 				cacheEntry.save(result);
 | |
| 			callback(null, result);
 | |
| 		}
 | |
| 	}
 | |
| } |