Skip to content

Commit 38d3c87

Browse files
committed
support labeled modules fixes webpack#72
1 parent 3239dd7 commit 38d3c87

File tree

10 files changed

+188
-3
lines changed

10 files changed

+188
-3
lines changed

lib/NormalModule.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ function NormalModule(request, userRequest, rawRequest, loaders, resource, parse
1616
this.rawRequest = rawRequest;
1717
this.parser = parser;
1818
NormalModuleMixin.call(this, loaders, resource);
19+
this.meta = {};
1920
this.assets = {};
2021
this.built = false;
2122
}
@@ -93,10 +94,10 @@ NormalModule.prototype.source = function(dependencyTemplates, outputOptions, req
9394
var varEndCode = "";
9495
function emitFunction() {
9596
if(varNames.length == 0) return;
96-
97+
9798
varStartCode += "/* WEBPACK VAR INJECTION */(function(" + varNames.join(", ") + ") {";
9899
varEndCode = "}(" + varExpressions.map(function(e) {return e.source()}).join(", ") + "))" + varEndCode;
99-
100+
100101
varNames.length = 0;
101102
varExpressions.length = 0;
102103
}

lib/Parser.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ Parser.prototype.walkStatement = function walkStatement(statement) {
232232
}
233233
break;
234234
case "LabeledStatement":
235+
var result = this.applyPluginsBailResult("label " + statement.label.name, statement);
236+
if(result === true)
237+
break;
235238
this.walkStatement(statement.body);
236239
break;
237240
case "WithStatement":

lib/WebpackOptionsApply.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var NodeTargetPlugin = require("./node/NodeTargetPlugin");
2929

3030
var CommonJsPlugin = require("./dependencies/CommonJsPlugin");
3131
var AMDPlugin = require("./dependencies/AMDPlugin");
32+
var LabeledModulesPlugin = require("./dependencies/LabeledModulesPlugin");
3233
var RequireContextPlugin = require("./dependencies/RequireContextPlugin");
3334
var RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
3435
var RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");
@@ -113,7 +114,8 @@ WebpackOptionsApply.prototype.process = function(options, compiler) {
113114
new RequireEnsurePlugin(),
114115
new RequireContextPlugin(options.resolve.modulesDirectories, options.resolve.extensions),
115116
new AMDPlugin(options.amd || {}),
116-
new CommonJsPlugin()
117+
new CommonJsPlugin(),
118+
new LabeledModulesPlugin()
117119
);
118120
if(options.console)
119121
compiler.apply(new ConsolePlugin());
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Tobias Koppers @sokra
4+
*/
5+
var NullDependency = require("./NullDependency");
6+
7+
function LabeledExportsDependency(name, pos) {
8+
NullDependency.call(this);
9+
this.Class = LabeledExportsDependency;
10+
this.name = name;
11+
this.pos = pos;
12+
}
13+
module.exports = LabeledExportsDependency;
14+
15+
LabeledExportsDependency.prototype = Object.create(NullDependency.prototype);
16+
17+
LabeledExportsDependency.Template = function LabeledExportsDependencyTemplate() {};
18+
19+
LabeledExportsDependency.Template.prototype.apply = function(dep, source) {
20+
source.insert(dep.pos, "exports[" + JSON.stringify(dep.name) + "] = ");
21+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Tobias Koppers @sokra
4+
*/
5+
var ModuleDependency = require("./ModuleDependency");
6+
7+
function LabeledModuleDependency(request, range) {
8+
ModuleDependency.call(this, request);
9+
this.Class = LabeledModuleDependency;
10+
this.range = range;
11+
}
12+
module.exports = LabeledModuleDependency;
13+
14+
LabeledModuleDependency.prototype = Object.create(ModuleDependency.prototype);
15+
LabeledModuleDependency.prototype.type = "labeled require";
16+
17+
LabeledModuleDependency.Template = function LabeledModuleDependencyTemplate() {};
18+
19+
LabeledModuleDependency.Template.prototype.apply = function(dep, source, outputOptions, requestShortener) {
20+
var comment = "";
21+
if(outputOptions.pathinfo) comment = "/*! " + requestShortener.shorten(dep.request) + " */ ";
22+
if(dep.module && dep.module.meta && dep.module.meta.exports) {
23+
var content = "var __LABELED_MODULE_" + dep.module.id + " = require(" + comment + dep.module.id + ")";
24+
dep.module.meta.exports.forEach(function(e) {
25+
content += ", " + e + " = __LABELED_MODULE_" + dep.module.id + "." + e;
26+
});
27+
content += ";"
28+
} else if(dep.module) {
29+
var content = "(function webpackMissingModuleMetaInfo() { throw new Error(" + JSON.stringify("Module cannot be imported because no meta info about exports is availible \"" + dep.request + "\"") + "); }())";
30+
} else {
31+
var content = "(function webpackMissingModule() { throw new Error(" + JSON.stringify("Cannot find module \"" + dep.request + "\"") + "); }())";
32+
}
33+
source.replace(dep.range[0], dep.range[1]-1, content);
34+
};
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Tobias Koppers @sokra
4+
*/
5+
var AbstractPlugin = require("../AbstractPlugin");
6+
var ConstDependency = require("./ConstDependency");
7+
var LabeledModuleDependency = require("./LabeledModuleDependency");
8+
var LabeledExportsDependency = require("./LabeledExportsDependency");
9+
10+
module.exports = AbstractPlugin.create({
11+
"label require": function(stmt) {
12+
if(stmt.body.type != "ExpressionStatement") return;
13+
switch(stmt.body.expression.type) {
14+
case "Literal":
15+
var param = this.evaluateExpression(stmt.body.expression);
16+
return this.applyPluginsBailResult("label require:item", stmt, param);
17+
case "SequenceExpression":
18+
stmt.body.expressions.forEach(function(expression) {
19+
var param = this.evaluateExpression(stmt.body.expression);
20+
return this.applyPluginsBailResult("label require:item", stmt, param);
21+
}, this);
22+
return true;
23+
}
24+
},
25+
"label require:item": function(stmt, param) {
26+
if(param.isString()) {
27+
var dep = new LabeledModuleDependency(param.string, stmt.range);
28+
dep.loc = stmt.loc;
29+
dep.optional = !!this.scope.inTry;
30+
this.state.current.addDependency(dep);
31+
return true;
32+
}
33+
},
34+
"label exports": function(stmt) {
35+
switch(stmt.body.type) {
36+
case "VariableDeclaration":
37+
stmt.body.declarations.forEach(function(decl) {
38+
if(!decl.init) return;
39+
var dep = new LabeledExportsDependency(decl.id.name, decl.init.range[0]);
40+
dep.loc = stmt.loc;
41+
this.state.current.addDependency(dep);
42+
if(!this.state.module.meta.exports) this.state.module.meta.exports = [];
43+
this.state.module.meta.exports.push(decl.id.name);
44+
}, this);
45+
return true;
46+
case "FunctionDeclaration":
47+
var name = stmt.body.id.name;
48+
var dep = new LabeledExportsDependency(name, stmt.body.range[0]);
49+
dep.loc = stmt.loc;
50+
this.state.current.addDependency(dep);
51+
if(!this.state.module.meta.exports) this.state.module.meta.exports = [];
52+
this.state.module.meta.exports.push(name);
53+
return true;
54+
case "ExpressionStatement":
55+
if(stmt.body.expression.type == "Identifier") {
56+
var name = stmt.body.expression.name;
57+
var dep = new LabeledExportsDependency(name, stmt.body.expression.range[0]);
58+
dep.loc = stmt.loc;
59+
this.state.current.addDependency(dep);
60+
if(!this.state.module.meta.exports) this.state.module.meta.exports = [];
61+
this.state.module.meta.exports.push(name);
62+
return true;
63+
} else if(stmt.body.expression.type == "SequenceExpression") {
64+
stmt.body.expression.expressions.forEach(function(e) {
65+
if(e.type != "Identifier") return;
66+
var name = e.name;
67+
var dep = new LabeledExportsDependency(name, e.range[0]);
68+
dep.loc = stmt.loc;
69+
this.state.current.addDependency(dep);
70+
if(!this.state.module.meta.exports) this.state.module.meta.exports = [];
71+
this.state.module.meta.exports.push(name);
72+
}, this);
73+
return true;
74+
}
75+
};
76+
}
77+
});
78+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Tobias Koppers @sokra
4+
*/
5+
var LabeledModuleDependency = require("./LabeledModuleDependency");
6+
var LabeledExportsDependency = require("./LabeledExportsDependency");
7+
8+
var NullFactory = require("../NullFactory");
9+
10+
var LabeledModuleDependencyParserPlugin = require("./LabeledModuleDependencyParserPlugin");
11+
12+
function LabeledModulesPlugin() {
13+
}
14+
module.exports = LabeledModulesPlugin;
15+
16+
LabeledModulesPlugin.prototype.apply = function(compiler) {
17+
compiler.plugin("compilation", function(compilation, params) {
18+
var normalModuleFactory = params.normalModuleFactory;
19+
20+
compilation.dependencyFactories.set(LabeledModuleDependency, normalModuleFactory);
21+
compilation.dependencyTemplates.set(LabeledModuleDependency, new LabeledModuleDependency.Template());
22+
23+
compilation.dependencyFactories.set(LabeledExportsDependency, new NullFactory());
24+
compilation.dependencyTemplates.set(LabeledExportsDependency, new LabeledExportsDependency.Template());
25+
});
26+
compiler.parser.apply(new LabeledModuleDependencyParserPlugin());
27+
};

test/browsertest/lib/index.web.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,16 @@ describe("main", function() {
165165
require("../folder/typeof").should.be.eql("function");
166166
});
167167

168+
it("should parse and evaluate labeled modules", function() {
169+
var lbm = require("./labeledModuleA");
170+
lbm.should.have.property("x").be.eql("x");
171+
lbm.should.have.property("y").be.a("function");
172+
lbm.y().should.be.eql("y");
173+
lbm.should.have.property("z").be.eql("z");
174+
lbm.should.have.property("foo").be.a("function");
175+
lbm.foo().should.be.eql("foo");
176+
});
177+
168178
it("should not parse filtered stuff", function() {
169179
if(typeof require != "function") require("fail");
170180
if(typeof require !== "function") require("fail");
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
require: "./labeledModuleB";
2+
3+
exports: x, y, z;
4+
5+
exports: function foo(){ return "foo"; };
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
exports: var x = "x", y = function() { return "y"; };
2+
3+
var z = "z";
4+
exports: z;

0 commit comments

Comments
 (0)