support labeled modules fixes #72

This commit is contained in:
Tobias Koppers 2013-02-26 12:36:34 +01:00
parent 3239dd76af
commit 38d3c877dd
10 changed files with 188 additions and 3 deletions

View File

@ -16,6 +16,7 @@ function NormalModule(request, userRequest, rawRequest, loaders, resource, parse
this.rawRequest = rawRequest;
this.parser = parser;
NormalModuleMixin.call(this, loaders, resource);
this.meta = {};
this.assets = {};
this.built = false;
}
@ -93,10 +94,10 @@ NormalModule.prototype.source = function(dependencyTemplates, outputOptions, req
var varEndCode = "";
function emitFunction() {
if(varNames.length == 0) return;
varStartCode += "/* WEBPACK VAR INJECTION */(function(" + varNames.join(", ") + ") {";
varEndCode = "}(" + varExpressions.map(function(e) {return e.source()}).join(", ") + "))" + varEndCode;
varNames.length = 0;
varExpressions.length = 0;
}

View File

@ -232,6 +232,9 @@ Parser.prototype.walkStatement = function walkStatement(statement) {
}
break;
case "LabeledStatement":
var result = this.applyPluginsBailResult("label " + statement.label.name, statement);
if(result === true)
break;
this.walkStatement(statement.body);
break;
case "WithStatement":

View File

@ -29,6 +29,7 @@ var NodeTargetPlugin = require("./node/NodeTargetPlugin");
var CommonJsPlugin = require("./dependencies/CommonJsPlugin");
var AMDPlugin = require("./dependencies/AMDPlugin");
var LabeledModulesPlugin = require("./dependencies/LabeledModulesPlugin");
var RequireContextPlugin = require("./dependencies/RequireContextPlugin");
var RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
var RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");
@ -113,7 +114,8 @@ WebpackOptionsApply.prototype.process = function(options, compiler) {
new RequireEnsurePlugin(),
new RequireContextPlugin(options.resolve.modulesDirectories, options.resolve.extensions),
new AMDPlugin(options.amd || {}),
new CommonJsPlugin()
new CommonJsPlugin(),
new LabeledModulesPlugin()
);
if(options.console)
compiler.apply(new ConsolePlugin());

View File

@ -0,0 +1,21 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var NullDependency = require("./NullDependency");
function LabeledExportsDependency(name, pos) {
NullDependency.call(this);
this.Class = LabeledExportsDependency;
this.name = name;
this.pos = pos;
}
module.exports = LabeledExportsDependency;
LabeledExportsDependency.prototype = Object.create(NullDependency.prototype);
LabeledExportsDependency.Template = function LabeledExportsDependencyTemplate() {};
LabeledExportsDependency.Template.prototype.apply = function(dep, source) {
source.insert(dep.pos, "exports[" + JSON.stringify(dep.name) + "] = ");
}

View File

@ -0,0 +1,34 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var ModuleDependency = require("./ModuleDependency");
function LabeledModuleDependency(request, range) {
ModuleDependency.call(this, request);
this.Class = LabeledModuleDependency;
this.range = range;
}
module.exports = LabeledModuleDependency;
LabeledModuleDependency.prototype = Object.create(ModuleDependency.prototype);
LabeledModuleDependency.prototype.type = "labeled require";
LabeledModuleDependency.Template = function LabeledModuleDependencyTemplate() {};
LabeledModuleDependency.Template.prototype.apply = function(dep, source, outputOptions, requestShortener) {
var comment = "";
if(outputOptions.pathinfo) comment = "/*! " + requestShortener.shorten(dep.request) + " */ ";
if(dep.module && dep.module.meta && dep.module.meta.exports) {
var content = "var __LABELED_MODULE_" + dep.module.id + " = require(" + comment + dep.module.id + ")";
dep.module.meta.exports.forEach(function(e) {
content += ", " + e + " = __LABELED_MODULE_" + dep.module.id + "." + e;
});
content += ";"
} else if(dep.module) {
var content = "(function webpackMissingModuleMetaInfo() { throw new Error(" + JSON.stringify("Module cannot be imported because no meta info about exports is availible \"" + dep.request + "\"") + "); }())";
} else {
var content = "(function webpackMissingModule() { throw new Error(" + JSON.stringify("Cannot find module \"" + dep.request + "\"") + "); }())";
}
source.replace(dep.range[0], dep.range[1]-1, content);
};

View File

@ -0,0 +1,78 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var AbstractPlugin = require("../AbstractPlugin");
var ConstDependency = require("./ConstDependency");
var LabeledModuleDependency = require("./LabeledModuleDependency");
var LabeledExportsDependency = require("./LabeledExportsDependency");
module.exports = AbstractPlugin.create({
"label require": function(stmt) {
if(stmt.body.type != "ExpressionStatement") return;
switch(stmt.body.expression.type) {
case "Literal":
var param = this.evaluateExpression(stmt.body.expression);
return this.applyPluginsBailResult("label require:item", stmt, param);
case "SequenceExpression":
stmt.body.expressions.forEach(function(expression) {
var param = this.evaluateExpression(stmt.body.expression);
return this.applyPluginsBailResult("label require:item", stmt, param);
}, this);
return true;
}
},
"label require:item": function(stmt, param) {
if(param.isString()) {
var dep = new LabeledModuleDependency(param.string, stmt.range);
dep.loc = stmt.loc;
dep.optional = !!this.scope.inTry;
this.state.current.addDependency(dep);
return true;
}
},
"label exports": function(stmt) {
switch(stmt.body.type) {
case "VariableDeclaration":
stmt.body.declarations.forEach(function(decl) {
if(!decl.init) return;
var dep = new LabeledExportsDependency(decl.id.name, decl.init.range[0]);
dep.loc = stmt.loc;
this.state.current.addDependency(dep);
if(!this.state.module.meta.exports) this.state.module.meta.exports = [];
this.state.module.meta.exports.push(decl.id.name);
}, this);
return true;
case "FunctionDeclaration":
var name = stmt.body.id.name;
var dep = new LabeledExportsDependency(name, stmt.body.range[0]);
dep.loc = stmt.loc;
this.state.current.addDependency(dep);
if(!this.state.module.meta.exports) this.state.module.meta.exports = [];
this.state.module.meta.exports.push(name);
return true;
case "ExpressionStatement":
if(stmt.body.expression.type == "Identifier") {
var name = stmt.body.expression.name;
var dep = new LabeledExportsDependency(name, stmt.body.expression.range[0]);
dep.loc = stmt.loc;
this.state.current.addDependency(dep);
if(!this.state.module.meta.exports) this.state.module.meta.exports = [];
this.state.module.meta.exports.push(name);
return true;
} else if(stmt.body.expression.type == "SequenceExpression") {
stmt.body.expression.expressions.forEach(function(e) {
if(e.type != "Identifier") return;
var name = e.name;
var dep = new LabeledExportsDependency(name, e.range[0]);
dep.loc = stmt.loc;
this.state.current.addDependency(dep);
if(!this.state.module.meta.exports) this.state.module.meta.exports = [];
this.state.module.meta.exports.push(name);
}, this);
return true;
}
};
}
});

View File

@ -0,0 +1,27 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var LabeledModuleDependency = require("./LabeledModuleDependency");
var LabeledExportsDependency = require("./LabeledExportsDependency");
var NullFactory = require("../NullFactory");
var LabeledModuleDependencyParserPlugin = require("./LabeledModuleDependencyParserPlugin");
function LabeledModulesPlugin() {
}
module.exports = LabeledModulesPlugin;
LabeledModulesPlugin.prototype.apply = function(compiler) {
compiler.plugin("compilation", function(compilation, params) {
var normalModuleFactory = params.normalModuleFactory;
compilation.dependencyFactories.set(LabeledModuleDependency, normalModuleFactory);
compilation.dependencyTemplates.set(LabeledModuleDependency, new LabeledModuleDependency.Template());
compilation.dependencyFactories.set(LabeledExportsDependency, new NullFactory());
compilation.dependencyTemplates.set(LabeledExportsDependency, new LabeledExportsDependency.Template());
});
compiler.parser.apply(new LabeledModuleDependencyParserPlugin());
};

View File

@ -165,6 +165,16 @@ describe("main", function() {
require("../folder/typeof").should.be.eql("function");
});
it("should parse and evaluate labeled modules", function() {
var lbm = require("./labeledModuleA");
lbm.should.have.property("x").be.eql("x");
lbm.should.have.property("y").be.a("function");
lbm.y().should.be.eql("y");
lbm.should.have.property("z").be.eql("z");
lbm.should.have.property("foo").be.a("function");
lbm.foo().should.be.eql("foo");
});
it("should not parse filtered stuff", function() {
if(typeof require != "function") require("fail");
if(typeof require !== "function") require("fail");

View File

@ -0,0 +1,5 @@
require: "./labeledModuleB";
exports: x, y, z;
exports: function foo(){ return "foo"; };

View File

@ -0,0 +1,4 @@
exports: var x = "x", y = function() { return "y"; };
var z = "z";
exports: z;