Skip to content

Commit

Permalink
Merge pull request #15423 from webpack/fix/issue-15409
Browse files Browse the repository at this point in the history
Fix resolving with yield
  • Loading branch information
sokra committed Mar 3, 2022
2 parents cbfea76 + 0fe4470 commit 870fcad
Show file tree
Hide file tree
Showing 30 changed files with 490 additions and 222 deletions.
116 changes: 90 additions & 26 deletions lib/ContextModule.js
Expand Up @@ -61,7 +61,7 @@ const makeSerializable = require("./util/makeSerializable");

/**
* @typedef {Object} ContextModuleOptionsExtras
* @property {string} resource
* @property {false|string|string[]} resource
* @property {string=} resourceQuery
* @property {string=} resourceFragment
* @property {TODO} resolveOptions
Expand Down Expand Up @@ -92,23 +92,36 @@ class ContextModule extends Module {
* @param {ContextModuleOptions} options options object
*/
constructor(resolveDependencies, options) {
const parsed = parseResource(options ? options.resource : "");
const resource = parsed.path;
const resourceQuery = (options && options.resourceQuery) || parsed.query;
const resourceFragment =
(options && options.resourceFragment) || parsed.fragment;

super("javascript/dynamic", resource);
if (!options || typeof options.resource === "string") {
const parsed = parseResource(
options ? /** @type {string} */ (options.resource) : ""
);
const resource = parsed.path;
const resourceQuery = (options && options.resourceQuery) || parsed.query;
const resourceFragment =
(options && options.resourceFragment) || parsed.fragment;

super("javascript/dynamic", resource);
/** @type {ContextModuleOptions} */
this.options = {
...options,
resource,
resourceQuery,
resourceFragment
};
} else {
super("javascript/dynamic");
/** @type {ContextModuleOptions} */
this.options = {
...options,
resource: options.resource,
resourceQuery: options.resourceQuery || "",
resourceFragment: options.resourceFragment || ""
};
}

// Info from Factory
this.resolveDependencies = resolveDependencies;
/** @type {ContextModuleOptions} */
this.options = {
...options,
resource,
resourceQuery,
resourceFragment
};
if (options && options.resolveOptions !== undefined) {
this.resolveOptions = options.resolveOptions;
}
Expand Down Expand Up @@ -155,7 +168,12 @@ class ContextModule extends Module {
}

_createIdentifier() {
let identifier = this.context;
let identifier =
this.context ||
(typeof this.options.resource === "string" ||
this.options.resource === false
? `${this.options.resource}`
: this.options.resource.join("|"));
if (this.options.resourceQuery) {
identifier += `|${this.options.resourceQuery}`;
}
Expand Down Expand Up @@ -220,7 +238,19 @@ class ContextModule extends Module {
* @returns {string} a user readable identifier of the module
*/
readableIdentifier(requestShortener) {
let identifier = requestShortener.shorten(this.context) + "/";
let identifier;
if (this.context) {
identifier = requestShortener.shorten(this.context) + "/";
} else if (
typeof this.options.resource === "string" ||
this.options.resource === false
) {
identifier = requestShortener.shorten(`${this.options.resource}`) + "/";
} else {
identifier = this.options.resource
.map(r => requestShortener.shorten(r) + "/")
.join(" ");
}
if (this.options.resourceQuery) {
identifier += ` ${this.options.resourceQuery}`;
}
Expand Down Expand Up @@ -270,11 +300,30 @@ class ContextModule extends Module {
* @returns {string | null} an identifier for library inclusion
*/
libIdent(options) {
let identifier = contextify(
options.context,
this.context,
options.associatedObjectForCache
);
let identifier;

if (this.context) {
identifier = contextify(
options.context,
this.context,
options.associatedObjectForCache
);
} else if (typeof this.options.resource === "string") {
identifier = contextify(
options.context,
this.options.resource,
options.associatedObjectForCache
);
} else if (this.options.resource === false) {
identifier = "false";
} else {
identifier = this.options.resource
.map(res =>
contextify(options.context, res, options.associatedObjectForCache)
)
.join(" ");
}

if (this.layer) identifier = `(${this.layer})/${identifier}`;
if (this.options.mode) {
identifier += ` ${this.options.mode}`;
Expand Down Expand Up @@ -323,8 +372,9 @@ class ContextModule extends Module {
// build if enforced
if (this._forceBuild) return callback(null, true);

// always build when we have no snapshot
if (!this.buildInfo.snapshot) return callback(null, true);
// always build when we have no snapshot and context
if (!this.buildInfo.snapshot)
return callback(null, Boolean(this.context || this.options.resource));

fileSystemInfo.checkSnapshotValid(this.buildInfo.snapshot, (err, valid) => {
callback(err, !valid);
Expand Down Expand Up @@ -439,10 +489,16 @@ class ContextModule extends Module {
);
return;
}
if (!this.context && !this.options.resource) return callback();

compilation.fileSystemInfo.createSnapshot(
startTime,
null,
[this.context],
this.context
? [this.context]
: typeof this.options.resource === "string"
? [this.options.resource]
: /** @type {string[]} */ (this.options.resource),
null,
SNAPSHOT_OPTIONS,
(err, snapshot) => {
Expand All @@ -466,7 +522,15 @@ class ContextModule extends Module {
missingDependencies,
buildDependencies
) {
contextDependencies.add(this.context);
if (this.context) {
contextDependencies.add(this.context);
} else if (typeof this.options.resource === "string") {
contextDependencies.add(this.options.resource);
} else if (this.options.resource === false) {
return;
} else {
for (const res of this.options.resource) contextDependencies.add(res);
}
}

/**
Expand Down
86 changes: 65 additions & 21 deletions lib/ContextModuleFactory.js
Expand Up @@ -167,18 +167,22 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
asyncLib.parallel(
[
callback => {
const results = [];
const yield_ = obj => results.push(obj);

contextResolver.resolve(
{},
context,
resource,
{
fileDependencies,
missingDependencies,
contextDependencies
contextDependencies,
yield: yield_
},
(err, result) => {
err => {
if (err) return callback(err);
callback(null, result);
callback(null, results);
}
);
},
Expand Down Expand Up @@ -213,15 +217,25 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
contextDependencies
});
}

let [contextResult, loaderResult] = result;
if (contextResult.length > 1) {
const first = contextResult[0];
contextResult = contextResult.filter(r => r.path);
if (contextResult.length === 0) contextResult.push(first);
}
this.hooks.afterResolve.callAsync(
{
addon:
loadersPrefix +
result[1].join("!") +
(result[1].length > 0 ? "!" : ""),
resource: result[0],
loaderResult.join("!") +
(loaderResult.length > 0 ? "!" : ""),
resource:
contextResult.length > 1
? contextResult.map(r => r.path)
: contextResult[0].path,
resolveDependencies: this.resolveDependencies.bind(this),
resourceQuery: contextResult[0].query,
resourceFragment: contextResult[0].fragment,
...beforeResolveResult
},
(err, result) => {
Expand Down Expand Up @@ -278,26 +292,28 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
} = options;
if (!regExp || !resource) return callback(null, []);

const addDirectoryChecked = (directory, visited, callback) => {
let severalContexts = false;
const addDirectoryChecked = (ctx, directory, visited, callback) => {
fs.realpath(directory, (err, realPath) => {
if (err) return callback(err);
if (visited.has(realPath)) return callback(null, []);
let recursionStack;
addDirectory(
ctx,
directory,
(dir, callback) => {
(_, dir, callback) => {
if (recursionStack === undefined) {
recursionStack = new Set(visited);
recursionStack.add(realPath);
}
addDirectoryChecked(dir, recursionStack, callback);
addDirectoryChecked(ctx, dir, recursionStack, callback);
},
callback
);
});
};

const addDirectory = (directory, addSubDirectory, callback) => {
const addDirectory = (ctx, directory, addSubDirectory, callback) => {
fs.readdir(directory, (err, files) => {
if (err) return callback(err);
const processedFiles = cmf.hooks.contextModuleFiles.call(
Expand All @@ -324,16 +340,15 @@ module.exports = class ContextModuleFactory extends ModuleFactory {

if (stat.isDirectory()) {
if (!recursive) return callback();
addSubDirectory(subResource, callback);
addSubDirectory(ctx, subResource, callback);
} else if (
stat.isFile() &&
(!include || subResource.match(include))
) {
const obj = {
context: resource,
context: ctx,
request:
"." +
subResource.substr(resource.length).replace(/\\/g, "/")
"." + subResource.substr(ctx.length).replace(/\\/g, "/")
};

this.hooks.alternativeRequests.callAsync(
Expand All @@ -344,8 +359,11 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
alternatives = alternatives
.filter(obj => regExp.test(obj.request))
.map(obj => {
const request = severalContexts
? join(fs, obj.context, obj.request)
: obj.request;
const dep = new ContextElementDependency(
obj.request + resourceQuery + resourceFragment,
request + resourceQuery + resourceFragment,
obj.request,
typePrefix,
category,
Expand Down Expand Up @@ -382,12 +400,38 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
});
};

if (typeof fs.realpath === "function") {
addDirectoryChecked(resource, new Set(), callback);
const addSubDirectory = (ctx, dir, callback) =>
addDirectory(ctx, dir, addSubDirectory, callback);

const visitResource = (resource, callback) => {
if (typeof fs.realpath === "function") {
addDirectoryChecked(resource, resource, new Set(), callback);
} else {
addDirectory(resource, resource, addSubDirectory, callback);
}
};

if (typeof resource === "string") {
visitResource(resource, callback);
} else {
const addSubDirectory = (dir, callback) =>
addDirectory(dir, addSubDirectory, callback);
addDirectory(resource, addSubDirectory, callback);
severalContexts = true;
asyncLib.map(resource, visitResource, (err, result) => {
if (err) return callback(err);

// result dependencies should have unique userRequest
// ordered by resolve result
const temp = new Set();
const res = [];
for (let i = 0; i < result.length; i++) {
const inner = result[i];
for (const el of inner) {
if (temp.has(el.userRequest)) continue;
res.push(el);
temp.add(el.userRequest);
}
}
callback(null, res);
});
}
}
};

0 comments on commit 870fcad

Please sign in to comment.