webpack
Advanced tools
Comparing version 0.4.4 to 0.4.5
@@ -129,16 +129,17 @@ /* | ||
// read file content | ||
fs.readFile(filename, function(err, content) { | ||
if(err) { | ||
callback(err); | ||
return; | ||
} | ||
if(options.cache) { | ||
options.cache.get(filenameWithLoaders, function(err, source) { | ||
if(err) return readFile(); | ||
processJs(null, source); | ||
}); | ||
} else | ||
readFile(); | ||
// exec the loaders | ||
execLoaders(context, filenameWithLoaders, loaders, [filename], [content], options, processJs); | ||
// Read the file and process it with loaders | ||
function readFile() { | ||
var cacheEntry = options.cache && options.cache.create(filenameWithLoaders); | ||
// process the finished javascript code | ||
// for inclusion into the result | ||
// (static code analysis for requires and other stuff) | ||
function processJs(err, source) { | ||
// read file content | ||
if(cacheEntry) cacheEntry.add(filename); | ||
fs.readFile(filename, function(err, content) { | ||
if(err) { | ||
@@ -148,110 +149,123 @@ callback(err); | ||
} | ||
var deps; | ||
try { | ||
deps = parse(source, options.parse); | ||
} catch(e) { | ||
callback("File \"" + filenameWithLoaders + "\" parsing failed: " + e); | ||
return; | ||
} | ||
modu.requires = deps.requires || []; | ||
modu.asyncs = deps.asyncs || []; | ||
modu.contexts = deps.contexts || []; | ||
modu.source = source; | ||
var requires = {}, directRequire = {}; | ||
var contexts = [], directContexts = {}; | ||
function add(r) { | ||
requires[r.name] = requires[r.name] || []; | ||
requires[r.name].push(r); | ||
// exec the loaders | ||
execLoaders(context, filenameWithLoaders, loaders, [filename], [content], cacheEntry, options, processJs); | ||
}); | ||
} | ||
// process the finished javascript code | ||
// for inclusion into the result | ||
// (static code analysis for requires and other stuff) | ||
function processJs(err, source) { | ||
if(err) { | ||
callback(err); | ||
return; | ||
} | ||
var deps; | ||
try { | ||
deps = parse(source, options.parse); | ||
} catch(e) { | ||
callback("File \"" + filenameWithLoaders + "\" parsing failed: " + e); | ||
return; | ||
} | ||
modu.requires = deps.requires || []; | ||
modu.asyncs = deps.asyncs || []; | ||
modu.contexts = deps.contexts || []; | ||
modu.source = source; | ||
var requires = {}, directRequire = {}; | ||
var contexts = [], directContexts = {}; | ||
function add(r) { | ||
requires[r.name] = requires[r.name] || []; | ||
requires[r.name].push(r); | ||
} | ||
function addContext(m) { | ||
return function(c) { | ||
contexts.push({context: c, module: m}); | ||
} | ||
function addContext(m) { | ||
return function(c) { | ||
contexts.push({context: c, module: m}); | ||
} | ||
} | ||
if(modu.requires) { | ||
modu.requires.forEach(add); | ||
modu.requires.forEach(function(r) { | ||
directRequire[r.name] = true; | ||
}); | ||
} | ||
if(modu.contexts) { | ||
modu.contexts.forEach(addContext(modu)); | ||
modu.contexts.forEach(function(c) { | ||
directContexts[c.name] = true; | ||
}); | ||
} | ||
if(modu.asyncs) | ||
modu.asyncs.forEach(function addAsync(c) { | ||
if(c.requires) | ||
c.requires.forEach(add); | ||
if(c.asyncs) | ||
c.asyncs.forEach(addAsync); | ||
if(c.contexts) | ||
c.contexts.forEach(addContext(c)); | ||
}); | ||
requiresNames = Object.keys(requires); | ||
var count = requiresNames.length + contexts.length + 1; | ||
var errors = []; | ||
if(requiresNames.length) | ||
requiresNames.forEach(function(moduleName) { | ||
var reason = { | ||
type: directRequire[moduleName] ? "require" : "async require", | ||
count: requires[moduleName].length, | ||
filename: filename | ||
}; | ||
} | ||
if(modu.requires) { | ||
modu.requires.forEach(add); | ||
modu.requires.forEach(function(r) { | ||
directRequire[r.name] = true; | ||
}); | ||
} | ||
if(modu.contexts) { | ||
modu.contexts.forEach(addContext(modu)); | ||
modu.contexts.forEach(function(c) { | ||
directContexts[c.name] = true; | ||
}); | ||
} | ||
if(modu.asyncs) | ||
modu.asyncs.forEach(function addAsync(c) { | ||
if(c.requires) | ||
c.requires.forEach(add); | ||
if(c.asyncs) | ||
c.asyncs.forEach(addAsync); | ||
if(c.contexts) | ||
c.contexts.forEach(addContext(c)); | ||
}); | ||
requiresNames = Object.keys(requires); | ||
var count = requiresNames.length + contexts.length + 1; | ||
var errors = []; | ||
if(requiresNames.length) | ||
requiresNames.forEach(function(moduleName) { | ||
var reason = { | ||
type: directRequire[moduleName] ? "require" : "async require", | ||
count: requires[moduleName].length, | ||
filename: filename | ||
}; | ||
// create or get the module for each require | ||
addModule(depTree, path.dirname(filename), moduleName, options, reason, function(err, moduleId) { | ||
if(err) { | ||
depTree.errors.push("Cannot find module '" + moduleName + "'\n " + err + | ||
"\n @ " + filename + " (line " + requires[moduleName][0].line + ", column " + requires[moduleName][0].column + ")"); | ||
} else { | ||
requires[moduleName].forEach(function(requireItem) { | ||
requireItem.id = moduleId; | ||
}); | ||
} | ||
endOne(); | ||
}); | ||
// create or get the module for each require | ||
addModule(depTree, path.dirname(filename), moduleName, options, reason, function(err, moduleId) { | ||
if(err) { | ||
depTree.errors.push("Cannot find module '" + moduleName + "'\n " + err + | ||
"\n @ " + filename + " (line " + requires[moduleName][0].line + ", column " + requires[moduleName][0].column + ")"); | ||
} else { | ||
requires[moduleName].forEach(function(requireItem) { | ||
requireItem.id = moduleId; | ||
}); | ||
} | ||
endOne(); | ||
}); | ||
if(contexts) { | ||
contexts.forEach(function(contextObj) { | ||
var context = contextObj.context; | ||
var module = contextObj.module; | ||
var reason = { | ||
type: directContexts[context.name] ? "context" : "async context", | ||
filename: filename | ||
}; | ||
}); | ||
if(contexts) { | ||
contexts.forEach(function(contextObj) { | ||
var context = contextObj.context; | ||
var module = contextObj.module; | ||
var reason = { | ||
type: directContexts[context.name] ? "context" : "async context", | ||
filename: filename | ||
}; | ||
// create of get the context module for each require.context | ||
addContextModule(depTree, path.dirname(filename), context.name, options, reason, function(err, contextModuleId) { | ||
if(err) { | ||
depTree.errors.push("Cannot find context '"+context.name+"'\n " + err + | ||
"\n @ " + filename + " (line " + context.line + ", column " + context.column + ")"); | ||
} else { | ||
context.id = contextModuleId; | ||
module.requires.push({id: context.id}); | ||
} | ||
endOne(); | ||
}); | ||
if(context.warn) { | ||
depTree.warnings.push(filename + " (line " + context.line + ", column " + context.column + "): " + | ||
"implicit use of require.context(\".\") is not recommended."); | ||
// create of get the context module for each require.context | ||
addContextModule(depTree, path.dirname(filename), context.name, options, reason, function(err, contextModuleId) { | ||
if(err) { | ||
depTree.errors.push("Cannot find context '"+context.name+"'\n " + err + | ||
"\n @ " + filename + " (line " + context.line + ", column " + context.column + ")"); | ||
} else { | ||
context.id = contextModuleId; | ||
module.requires.push({id: context.id}); | ||
} | ||
endOne(); | ||
}); | ||
} | ||
endOne(); | ||
function endOne() { | ||
count--; | ||
assert(count >= 0); | ||
if(count === 0) { | ||
if(errors.length) { | ||
callback(errors.join("\n")); | ||
} else { | ||
callback(null, modu.id); | ||
} | ||
if(context.warn) { | ||
depTree.warnings.push(filename + " (line " + context.line + ", column " + context.column + "): " + | ||
"implicit use of require.context(\".\") is not recommended."); | ||
} | ||
}); | ||
} | ||
endOne(); | ||
function endOne() { | ||
count--; | ||
assert(count >= 0); | ||
if(count === 0) { | ||
if(errors.length) { | ||
callback(errors.join("\n")); | ||
} else { | ||
callback(null, modu.id); | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
@@ -258,0 +272,0 @@ } |
@@ -19,11 +19,15 @@ /* | ||
*/ | ||
module.exports = function(context, request, loaders, filenames, contents, options, callback) { | ||
if(loaders.length === 0) | ||
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 | ||
callback(null, contents[0].toString("utf-8")); | ||
else { | ||
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 | ||
var loaderFunctions = []; | ||
loaderFunctions = []; | ||
try { | ||
@@ -39,111 +43,133 @@ loaders.forEach(function(name) { | ||
// iterate over the loaders, asynchron | ||
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 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); | ||
}, | ||
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")); | ||
} | ||
nextLoader.apply(null, arguments); | ||
}, | ||
web: true, | ||
debug: options.debug, | ||
minimize: options.minimize, | ||
values: undefined, | ||
options: options, | ||
buffers: args | ||
}; | ||
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) { | ||
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]; | ||
// 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); | ||
}); | ||
// 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); | ||
// 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"); | ||
nextLoader(retVal === undefined ? new Error("loader did not return a value") : null, retVal); | ||
} | ||
} 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; | ||
// 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); | ||
} | ||
} else { | ||
callback(null, args[0].toString("utf-8")); | ||
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); | ||
} | ||
contents.unshift(null); | ||
nextLoader.apply(null, contents); | ||
} | ||
} |
@@ -6,4 +6,5 @@ /* | ||
var buildDeps = require("./buildDeps"); | ||
var writeChunk = require("./writeChunk"); | ||
var Cache = require("./Cache"); | ||
var path = require("path"); | ||
var writeChunk = require("./writeChunk"); | ||
var fs = require("fs"); | ||
@@ -139,2 +140,5 @@ | ||
}); | ||
if(!options.cache) | ||
options.cache = new Cache(options.cacheOptions); | ||
} | ||
@@ -185,3 +189,3 @@ | ||
options.resolve.loaders.push({test: /\.css$/, loader: "style!css"}); | ||
options.resolve.loaders.push({test: /\.less$/, loader: "style!css!val!less"}); | ||
options.resolve.loaders.push({test: /\.less$/, loader: "style!css!val/cacheable!less"}); | ||
@@ -188,0 +192,0 @@ options.loader = options.loader || {}; |
{ | ||
"name": "webpack", | ||
"version": "0.4.4", | ||
"version": "0.4.5", | ||
"author": "Tobias Koppers @sokra", | ||
@@ -5,0 +5,0 @@ "description": "Packs CommonJs Modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loading of js, json, jade, coffee, css, ... out of the box and more with custom loaders.", |
331233
103
9338
51