Skip to content

Commit 8544f01

Browse files
committed
Merge branch 'main' into fix/issues-15214
2 parents a905ea3 + 89c92bf commit 8544f01

22 files changed

Lines changed: 1072 additions & 876 deletions

File tree

lib/ContextModule.js

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const makeSerializable = require("./util/makeSerializable");
6161

6262
/**
6363
* @typedef {Object} ContextModuleOptionsExtras
64-
* @property {string} resource
64+
* @property {string|string[]} resource
6565
* @property {string=} resourceQuery
6666
* @property {string=} resourceFragment
6767
* @property {TODO} resolveOptions
@@ -92,23 +92,36 @@ class ContextModule extends Module {
9292
* @param {ContextModuleOptions} options options object
9393
*/
9494
constructor(resolveDependencies, options) {
95-
const parsed = parseResource(options ? options.resource : "");
96-
const resource = parsed.path;
97-
const resourceQuery = (options && options.resourceQuery) || parsed.query;
98-
const resourceFragment =
99-
(options && options.resourceFragment) || parsed.fragment;
100-
101-
super("javascript/dynamic", resource);
95+
if (!options || typeof options.resource === "string") {
96+
const parsed = parseResource(
97+
options ? /** @type {string} */ (options.resource) : ""
98+
);
99+
const resource = parsed.path;
100+
const resourceQuery = (options && options.resourceQuery) || parsed.query;
101+
const resourceFragment =
102+
(options && options.resourceFragment) || parsed.fragment;
103+
104+
super("javascript/dynamic", resource);
105+
/** @type {ContextModuleOptions} */
106+
this.options = {
107+
...options,
108+
resource,
109+
resourceQuery,
110+
resourceFragment
111+
};
112+
} else {
113+
super("javascript/dynamic");
114+
/** @type {ContextModuleOptions} */
115+
this.options = {
116+
...options,
117+
resource: options.resource,
118+
resourceQuery: options.resourceQuery || "",
119+
resourceFragment: options.resourceFragment || ""
120+
};
121+
}
102122

103123
// Info from Factory
104124
this.resolveDependencies = resolveDependencies;
105-
/** @type {ContextModuleOptions} */
106-
this.options = {
107-
...options,
108-
resource,
109-
resourceQuery,
110-
resourceFragment
111-
};
112125
if (options && options.resolveOptions !== undefined) {
113126
this.resolveOptions = options.resolveOptions;
114127
}
@@ -155,7 +168,11 @@ class ContextModule extends Module {
155168
}
156169

157170
_createIdentifier() {
158-
let identifier = this.context;
171+
let identifier =
172+
this.context ||
173+
(typeof this.options.resource === "string"
174+
? this.options.resource
175+
: this.options.resource.join("|"));
159176
if (this.options.resourceQuery) {
160177
identifier += `|${this.options.resourceQuery}`;
161178
}
@@ -220,7 +237,16 @@ class ContextModule extends Module {
220237
* @returns {string} a user readable identifier of the module
221238
*/
222239
readableIdentifier(requestShortener) {
223-
let identifier = requestShortener.shorten(this.context) + "/";
240+
let identifier;
241+
if (this.context) {
242+
identifier = requestShortener.shorten(this.context) + "/";
243+
} else if (typeof this.options.resource === "string") {
244+
identifier = requestShortener.shorten(this.options.resource) + "/";
245+
} else {
246+
identifier = this.options.resource
247+
.map(r => requestShortener.shorten(r) + "/")
248+
.join(" ");
249+
}
224250
if (this.options.resourceQuery) {
225251
identifier += ` ${this.options.resourceQuery}`;
226252
}
@@ -270,11 +296,30 @@ class ContextModule extends Module {
270296
* @returns {string | null} an identifier for library inclusion
271297
*/
272298
libIdent(options) {
273-
let identifier = contextify(
274-
options.context,
275-
this.context,
276-
options.associatedObjectForCache
277-
);
299+
let identifier;
300+
301+
if (this.context) {
302+
identifier = contextify(
303+
options.context,
304+
this.context,
305+
options.associatedObjectForCache
306+
);
307+
} else if (typeof this.options.resource === "string") {
308+
identifier = contextify(
309+
options.context,
310+
this.options.resource,
311+
options.associatedObjectForCache
312+
);
313+
} else {
314+
const arr = [];
315+
for (const res of this.options.resource) {
316+
arr.push(
317+
contextify(options.context, res, options.associatedObjectForCache)
318+
);
319+
}
320+
identifier = arr.join(" ");
321+
}
322+
278323
if (this.layer) identifier = `(${this.layer})/${identifier}`;
279324
if (this.options.mode) {
280325
identifier += ` ${this.options.mode}`;
@@ -442,7 +487,11 @@ class ContextModule extends Module {
442487
compilation.fileSystemInfo.createSnapshot(
443488
startTime,
444489
null,
445-
[this.context],
490+
this.context
491+
? [this.context]
492+
: typeof this.options.resource === "string"
493+
? [this.options.resource]
494+
: this.options.resource,
446495
null,
447496
SNAPSHOT_OPTIONS,
448497
(err, snapshot) => {
@@ -466,7 +515,13 @@ class ContextModule extends Module {
466515
missingDependencies,
467516
buildDependencies
468517
) {
469-
contextDependencies.add(this.context);
518+
if (this.context) {
519+
contextDependencies.add(this.context);
520+
} else if (typeof this.options.resource === "string") {
521+
contextDependencies.add(this.options.resource);
522+
} else {
523+
for (const res of this.options.resource) contextDependencies.add(res);
524+
}
470525
}
471526

472527
/**

lib/ContextModuleFactory.js

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -167,18 +167,22 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
167167
asyncLib.parallel(
168168
[
169169
callback => {
170+
const results = [];
171+
const yield_ = obj => results.push(obj);
172+
170173
contextResolver.resolve(
171174
{},
172175
context,
173176
resource,
174177
{
175178
fileDependencies,
176179
missingDependencies,
177-
contextDependencies
180+
contextDependencies,
181+
yield: yield_
178182
},
179-
(err, result) => {
183+
err => {
180184
if (err) return callback(err);
181-
callback(null, result);
185+
callback(null, results);
182186
}
183187
);
184188
},
@@ -213,15 +217,20 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
213217
contextDependencies
214218
});
215219
}
216-
220+
const [contextResult, loaderResult] = result;
217221
this.hooks.afterResolve.callAsync(
218222
{
219223
addon:
220224
loadersPrefix +
221-
result[1].join("!") +
222-
(result[1].length > 0 ? "!" : ""),
223-
resource: result[0],
225+
loaderResult.join("!") +
226+
(loaderResult.length > 0 ? "!" : ""),
227+
resource:
228+
contextResult.length > 1
229+
? contextResult.map(r => r.path)
230+
: contextResult[0].path,
224231
resolveDependencies: this.resolveDependencies.bind(this),
232+
resourceQuery: contextResult[0].query,
233+
resourceFragment: contextResult[0].fragment,
225234
...beforeResolveResult
226235
},
227236
(err, result) => {
@@ -278,26 +287,28 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
278287
} = options;
279288
if (!regExp || !resource) return callback(null, []);
280289

281-
const addDirectoryChecked = (directory, visited, callback) => {
290+
let severalContexts = false;
291+
const addDirectoryChecked = (ctx, directory, visited, callback) => {
282292
fs.realpath(directory, (err, realPath) => {
283293
if (err) return callback(err);
284294
if (visited.has(realPath)) return callback(null, []);
285295
let recursionStack;
286296
addDirectory(
297+
ctx,
287298
directory,
288-
(dir, callback) => {
299+
(_, dir, callback) => {
289300
if (recursionStack === undefined) {
290301
recursionStack = new Set(visited);
291302
recursionStack.add(realPath);
292303
}
293-
addDirectoryChecked(dir, recursionStack, callback);
304+
addDirectoryChecked(ctx, dir, recursionStack, callback);
294305
},
295306
callback
296307
);
297308
});
298309
};
299310

300-
const addDirectory = (directory, addSubDirectory, callback) => {
311+
const addDirectory = (ctx, directory, addSubDirectory, callback) => {
301312
fs.readdir(directory, (err, files) => {
302313
if (err) return callback(err);
303314
const processedFiles = cmf.hooks.contextModuleFiles.call(
@@ -324,16 +335,15 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
324335

325336
if (stat.isDirectory()) {
326337
if (!recursive) return callback();
327-
addSubDirectory(subResource, callback);
338+
addSubDirectory(ctx, subResource, callback);
328339
} else if (
329340
stat.isFile() &&
330341
(!include || subResource.match(include))
331342
) {
332343
const obj = {
333-
context: resource,
344+
context: ctx,
334345
request:
335-
"." +
336-
subResource.substr(resource.length).replace(/\\/g, "/")
346+
"." + subResource.substr(ctx.length).replace(/\\/g, "/")
337347
};
338348

339349
this.hooks.alternativeRequests.callAsync(
@@ -344,8 +354,11 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
344354
alternatives = alternatives
345355
.filter(obj => regExp.test(obj.request))
346356
.map(obj => {
357+
const request = severalContexts
358+
? join(fs, obj.context, obj.request)
359+
: obj.request;
347360
const dep = new ContextElementDependency(
348-
obj.request + resourceQuery + resourceFragment,
361+
request + resourceQuery + resourceFragment,
349362
obj.request,
350363
typePrefix,
351364
category,
@@ -382,12 +395,38 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
382395
});
383396
};
384397

385-
if (typeof fs.realpath === "function") {
386-
addDirectoryChecked(resource, new Set(), callback);
398+
const addSubDirectory = (ctx, dir, callback) =>
399+
addDirectory(ctx, dir, addSubDirectory, callback);
400+
401+
const visitResource = (resource, callback) => {
402+
if (typeof fs.realpath === "function") {
403+
addDirectoryChecked(resource, resource, new Set(), callback);
404+
} else {
405+
addDirectory(resource, resource, addSubDirectory, callback);
406+
}
407+
};
408+
409+
if (typeof resource === "string") {
410+
visitResource(resource, callback);
387411
} else {
388-
const addSubDirectory = (dir, callback) =>
389-
addDirectory(dir, addSubDirectory, callback);
390-
addDirectory(resource, addSubDirectory, callback);
412+
severalContexts = true;
413+
asyncLib.map(resource, visitResource, (err, result) => {
414+
if (err) return callback(err);
415+
416+
// result dependencies should have unique userRequest
417+
// ordered by resolve result
418+
const temp = new Set();
419+
const res = [];
420+
for (let i = 0; i < result.length; i++) {
421+
const inner = result[i];
422+
for (const el of inner) {
423+
if (temp.has(el.userRequest)) continue;
424+
res.push(el);
425+
temp.add(el.userRequest);
426+
}
427+
}
428+
callback(null, res);
429+
});
391430
}
392431
}
393432
};

0 commit comments

Comments
 (0)