Skip to content

Commit 4d631a0

Browse files
committed
added AMD support
1 parent 4101a8d commit 4d631a0

File tree

7 files changed

+162
-7
lines changed

7 files changed

+162
-7
lines changed

lib/buildDeps.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ function addModule(depTree, context, modu, options, reason, finalCallback) {
217217
var requires = {}, directRequire = {};
218218
var contexts = [], directContexts = {};
219219
function add(r) {
220+
if(!r.name) return;
220221
requires[r.name] = requires[r.name] || [];
221222
requires[r.name].push(r);
222223
}
@@ -228,6 +229,7 @@ function addModule(depTree, context, modu, options, reason, finalCallback) {
228229
if(modu.requires) {
229230
modu.requires.forEach(add);
230231
modu.requires.forEach(function(r) {
232+
if(!r.name) return;
231233
directRequire[r.name] = true;
232234
});
233235
}

lib/parse.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,92 @@ function walkExpression(context, expression) {
189189
break;
190190
case "CallExpression":
191191
var noCallee = false;
192+
function processAmdArray(params, elements) {
193+
params.forEach(function(param, idx) {
194+
if(param.conditional) {
195+
context.requires = context.requires || [];
196+
param.conditional.forEach(function(paramItem) {
197+
context.requires.push({
198+
name: paramItem.value,
199+
expressionRange: paramItem.range,
200+
line: elements[idx].loc.start.line,
201+
column: elements[idx].loc.start.column
202+
});
203+
});
204+
} else if(param.code) {
205+
// make context
206+
var pos = param.value.indexOf("/");
207+
context.contexts = context.contexts || [];
208+
if(pos === -1) {
209+
var newContext = {
210+
name: ".",
211+
valueRange: elements[idx].range,
212+
line: elements[idx].loc.start.line,
213+
column: elements[idx].loc.start.column
214+
};
215+
context.contexts.push(newContext);
216+
} else {
217+
var match = /\/[^\/]*$/.exec(param.value);
218+
var dirname = param.value.substring(0, match.index);
219+
var remainder = "." + param.value.substring(match.index);
220+
var newContext = {
221+
name: dirname,
222+
replace: [param.range, remainder],
223+
valueRange: elements[idx].range,
224+
line: elements[idx].loc.start.line,
225+
column: elements[idx].loc.start.column
226+
};
227+
context.contexts.push(newContext);
228+
}
229+
} else {
230+
// normal require
231+
context.requires = context.requires || [];
232+
context.requires.push({
233+
name: param.value,
234+
expressionRange: elements[idx].range,
235+
line: elements[idx].loc.start.line,
236+
column: elements[idx].loc.start.column
237+
});
238+
}
239+
});
240+
}
241+
// AMD require
242+
if(context.overwrite.indexOf("require") === -1 &&
243+
expression.callee && expression.arguments &&
244+
expression.arguments.length == 2 &&
245+
expression.callee.type === "Identifier" &&
246+
expression.callee.name === "require") {
247+
var params = parseCalculatedStringArray(expression.arguments[0]);
248+
var elements = expression.arguments[0].type == "ArrayExpression" ?
249+
expression.arguments[0].elements : [expression.arguments[0]];
250+
processAmdArray(params, elements);
251+
context.requires = context.requires || [];
252+
context.requires.push({
253+
amdRequireRange: expression.callee.range,
254+
line: expression.callee.loc.start.line,
255+
column: expression.callee.loc.start.column
256+
});
257+
noCallee = true;
258+
}
259+
// AMD define
260+
if(context.overwrite.indexOf("define") === -1 &&
261+
expression.callee && expression.arguments &&
262+
expression.arguments.length == 3 &&
263+
expression.callee.type === "Identifier" &&
264+
expression.callee.name === "define") {
265+
var params = parseCalculatedStringArray(expression.arguments[1]);
266+
var elements = expression.arguments[1].type == "ArrayExpression" ?
267+
expression.arguments[1].elements : [expression.arguments[1]];
268+
processAmdArray(params, elements);
269+
context.requires = context.requires || [];
270+
context.requires.push({
271+
amdDefineRange: expression.callee.range,
272+
line: expression.callee.loc.start.line,
273+
column: expression.callee.loc.start.column
274+
});
275+
noCallee = true;
276+
}
277+
// CommonJS
192278
if(context.overwrite.indexOf("require") === -1 &&
193279
expression.callee && expression.arguments &&
194280
expression.arguments.length == 1 &&
@@ -245,6 +331,7 @@ function walkExpression(context, expression) {
245331
}
246332
noCallee = true;
247333
}
334+
// require.ensure
248335
if(context.overwrite.indexOf("require") === -1 &&
249336
expression.callee && expression.arguments &&
250337
expression.arguments.length >= 1 &&
@@ -286,6 +373,7 @@ function walkExpression(context, expression) {
286373
context = newContext;
287374
noCallee = true;
288375
}
376+
// (non-standard) require.context
289377
if(context.overwrite.indexOf("require") === -1 &&
290378
expression.callee && expression.arguments &&
291379
expression.arguments.length == 1 &&
@@ -306,6 +394,7 @@ function walkExpression(context, expression) {
306394
context.contexts.push(newContext);
307395
noCallee = true;
308396
}
397+
// CommonJS: require.resolve
309398
if(context.overwrite.indexOf("require") === -1 &&
310399
expression.callee && expression.arguments &&
311400
expression.arguments.length == 1 &&
@@ -472,6 +561,19 @@ function parseStringArray(expression) {
472561
return [parseString(expression)];
473562
}
474563

564+
function parseCalculatedStringArray(expression) {
565+
switch(expression.type) {
566+
case "ArrayExpression":
567+
var arr = [];
568+
if(expression.elements)
569+
expression.elements.forEach(function(expr) {
570+
arr.push(parseCalculatedString(expr));
571+
});
572+
return arr;
573+
}
574+
return [parseCalculatedString(expression)];
575+
}
576+
475577
module.exports = function parse(source, options) {
476578
var ast = esprima.parse(source, {range: true, loc: true, raw: true});
477579
if(!ast || typeof ast != "object")

lib/webpack.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,15 @@ function webpack(context, moduleName, options, callback) {
306306
buffer.push(template);
307307

308308
// write extra info into object
309-
buffer.push("/******/({a:");
310-
buffer.push(JSON.stringify(options.outputPostfix.replace(HASH_REGEXP, hash)));
311-
buffer.push(",b:");
312-
buffer.push(JSON.stringify(options.outputJsonpFunction));
313-
buffer.push(",c:");
309+
buffer.push("/******/({");
310+
if(chunkIds.length > 1) {
311+
buffer.push("a:");
312+
buffer.push(JSON.stringify(options.outputPostfix.replace(HASH_REGEXP, hash)));
313+
buffer.push(",b:");
314+
buffer.push(JSON.stringify(options.outputJsonpFunction));
315+
buffer.push(",");
316+
}
317+
buffer.push("c:");
314318
buffer.push(JSON.stringify(options.publicPrefix.replace(HASH_REGEXP, hash)));
315319
buffer.push(",\n");
316320
} else { // lazy loaded chunk

lib/writeSource.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,19 @@ module.exports = function(module, options, toRealId, toRealChuckId) {
6969
}
7070
}
7171
}
72+
if(requireItem.amdRequireRange) {
73+
replaces.push({
74+
from: requireItem.amdRequireRange[0],
75+
to: requireItem.amdRequireRange[1],
76+
value: "(function(modules, fn) { return fn.apply(null, modules) })"
77+
});
78+
} else if(requireItem.amdDefineRange) {
79+
replaces.push({
80+
from: requireItem.amdDefineRange[0],
81+
to: requireItem.amdDefineRange[1],
82+
value: "(function(name, modules, fn) { return module.exports = fn.apply(null, modules) })"
83+
});
84+
}
7285
}
7386
function genContextReplaces(contextItem) {
7487
var postfix = "";
@@ -87,6 +100,23 @@ module.exports = function(module, options, toRealId, toRealChuckId) {
87100
to: contextItem.replace[0][1],
88101
value: JSON.stringify(contextItem.replace[1])
89102
});
103+
} else if(contextItem.valueRange) {
104+
replaces.push({
105+
from: contextItem.valueRange[0],
106+
to: contextItem.valueRange[0]-1,
107+
value: "require(" + prefix + (((contextItem.id && toRealId(contextItem.id)) || JSON.stringify("context: " + contextItem.name || "context failed")) + "") + ")("
108+
});
109+
replaces.push({
110+
from: contextItem.valueRange[1]+1,
111+
to: contextItem.valueRange[1],
112+
value: ")"
113+
});
114+
if(contextItem.replace)
115+
replaces.push({
116+
from: contextItem.replace[0][0],
117+
to: contextItem.replace[0][1],
118+
value: JSON.stringify(contextItem.replace[1])
119+
});
90120
} else {
91121
replaces.push({
92122
from: contextItem.expressionRange[0],
@@ -125,7 +155,7 @@ module.exports = function(module, options, toRealId, toRealChuckId) {
125155
replaces.push({
126156
from: asyncItem.nameRange[0],
127157
to: asyncItem.nameRange[1],
128-
value: "/* "+ asyncItem.name.replace(/\/\*/, "* nice try /") + " */0"
158+
value: "/* "+ asyncItem.name.replace(/\*\//g, "* nice try /") + " */0"
129159
});
130160
}
131161
if(asyncItem.propertyRange) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "webpack",
3-
"version": "0.4.25",
3+
"version": "0.5.0",
44
"author": "Tobias Koppers @sokra",
55
"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.",
66
"dependencies": {

test/browsertest/lib/index.web.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,5 +157,19 @@ delete require.cache[singlarId];
157157
window.test(require("./singluar2") !== singlarObj, "require.cache can be deleted");
158158

159159

160+
// AMD
161+
var template = "tmpl";
162+
var amdLoaded = false;
163+
require(["./circular", "../templates/" + template, true ? "./circular" : "./circular"], function(circular, testTemplate, circular2) {
164+
window.test(circular === 1, "AMD-style requires should work");
165+
window.test(circular2 === 1, "AMD-style requires should work with conditionals");
166+
window.test(testTemplate === "test template", "AMD-style requires should work with context");
167+
amdLoaded = true;
168+
});
169+
window.test(amdLoaded, "AMD-style require should work (sync)");
170+
171+
172+
173+
160174
// Tests from node.js
161175
require("bundle!../nodetests");

test/browsertest/test.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
span {
2727
background: red;
2828
}
29+
p {
30+
margin: 0;
31+
}
2932
</style>
3033
</head>
3134

0 commit comments

Comments
 (0)