Skip to content

Commit

Permalink
Merge pull request #15585 from webpack/refactor/support-context-in-de…
Browse files Browse the repository at this point in the history
…pendency

support context in Dependency
  • Loading branch information
sokra committed Mar 28, 2022
2 parents 129477d + 5605e53 commit 2c200d1
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 12 deletions.
3 changes: 2 additions & 1 deletion lib/Compilation.js
Expand Up @@ -1436,7 +1436,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
* @returns {void}
*/
_processModuleDependencies(module, callback) {
/** @type {Array<{factory: ModuleFactory, dependencies: Dependency[], originModule: Module|null}>} */
/** @type {Array<{factory: ModuleFactory, dependencies: Dependency[], context: string|undefined, originModule: Module|null}>} */
const sortedDependencies = [];

/** @type {DependenciesBlock} */
Expand Down Expand Up @@ -1668,6 +1668,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
sortedDependencies.push({
factory: factoryCacheKey2,
dependencies: list,
context: dep.getContext(),
originModule: module
});
}
Expand Down
10 changes: 3 additions & 7 deletions lib/ContextModuleFactory.js
Expand Up @@ -292,7 +292,6 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
} = options;
if (!regExp || !resource) return callback(null, []);

let severalContexts = false;
const addDirectoryChecked = (ctx, directory, visited, callback) => {
fs.realpath(directory, (err, realPath) => {
if (err) return callback(err);
Expand Down Expand Up @@ -359,15 +358,13 @@ 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(
request + resourceQuery + resourceFragment,
`${obj.request}${resourceQuery}${resourceFragment}`,
obj.request,
typePrefix,
category,
referencedExports
referencedExports,
obj.context
);
dep.optional = true;
return dep;
Expand Down Expand Up @@ -414,7 +411,6 @@ module.exports = class ContextModuleFactory extends ModuleFactory {
if (typeof resource === "string") {
visitResource(resource, callback);
} else {
severalContexts = true;
asyncLib.map(resource, visitResource, (err, result) => {
if (err) return callback(err);

Expand Down
7 changes: 7 additions & 0 deletions lib/Dependency.js
Expand Up @@ -182,6 +182,13 @@ class Dependency {
this._loc = undefined;
}

/**
* @returns {string | undefined} a request context
*/
getContext() {
return undefined;
}

/**
* @returns {string | null} an identifier to merge equal requests
*/
Expand Down
34 changes: 33 additions & 1 deletion lib/dependencies/ContextElementDependency.js
Expand Up @@ -14,11 +14,27 @@ const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */

class ContextElementDependency extends ModuleDependency {
constructor(request, userRequest, typePrefix, category, referencedExports) {
/**
* @param {string} request request
* @param {string|undefined} userRequest user request
* @param {string} typePrefix type prefix
* @param {string} category category
* @param {string[][]=} referencedExports referenced exports
* @param {string=} context context
*/
constructor(
request,
userRequest,
typePrefix,
category,
referencedExports,
context
) {
super(request);
this.referencedExports = referencedExports;
this._typePrefix = typePrefix;
this._category = category;
this._context = context || undefined;

if (userRequest) {
this.userRequest = userRequest;
Expand All @@ -33,6 +49,20 @@ class ContextElementDependency extends ModuleDependency {
return "context element";
}

/**
* @returns {string | undefined} a request context
*/
getContext() {
return this._context;
}

/**
* @returns {string | null} an identifier to merge equal requests
*/
getResourceIdentifier() {
return `context${this._context || ""}|${super.getResourceIdentifier()}`;
}

get category() {
return this._category;
}
Expand All @@ -56,6 +86,7 @@ class ContextElementDependency extends ModuleDependency {
const { write } = context;
write(this._typePrefix);
write(this._category);
write(this._context);
write(this.referencedExports);
super.serialize(context);
}
Expand All @@ -64,6 +95,7 @@ class ContextElementDependency extends ModuleDependency {
const { read } = context;
this._typePrefix = read();
this._category = read();
this._context = read();
this.referencedExports = read();
super.deserialize(context);
}
Expand Down
5 changes: 3 additions & 2 deletions test/ContextModuleFactory.unittest.js
Expand Up @@ -148,9 +148,10 @@ describe("ContextModuleFactory", () => {
expect(res).not.toStrictEqual([]);
expect(Array.isArray(res)).toBe(true);
expect(res.map(r => r.request)).toEqual([
"/a/B/a?query#hash",
"/b/A/b?query#hash"
"./B/a?query#hash",
"./A/b?query#hash"
]);
expect(res.map(r => r.getContext())).toEqual(["/a", "/b"]);
expect(res.map(r => r.userRequest)).toEqual(["./B/a", "./A/b"]);
done();
}
Expand Down
19 changes: 19 additions & 0 deletions test/configCases/resolve/issue-15580/index.js
@@ -0,0 +1,19 @@
const locales = import.meta.webpackContext('./locales', {
recursive: false,
regExp: /(en|hu)\.json$/i,
});
const vuetify = import.meta.webpackContext('vuetify/lib/locale', {
recursive: false,
regExp: /(en|hu)\.json$/i,
});

it('should resolve "./locales"', () => {
expect(locales("./en.json")).toEqual({});
expect(() => locales("./hu.json")).toThrow();
});

it('should resolve "vuetify"', () => {
expect(vuetify("./en.json")).toEqual({});
expect(vuetify("./hu.json")).toEqual({});
expect(() => vuetify("./ru.json")).toThrow();
});
1 change: 1 addition & 0 deletions test/configCases/resolve/issue-15580/locales/en.json
@@ -0,0 +1 @@
{}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions test/configCases/resolve/issue-15580/webpack.config.js
@@ -0,0 +1,8 @@
const path = require("path");

/** @type {import("../../../../").Configuration} */
module.exports = {
resolve: {
modules: ["node_modules", path.resolve(__dirname, "./node_modules")]
}
};
3 changes: 2 additions & 1 deletion types.d.ts
Expand Up @@ -2462,7 +2462,7 @@ declare interface ContainerReferencePluginOptions {
shareScope?: string;
}
declare abstract class ContextElementDependency extends ModuleDependency {
referencedExports: any;
referencedExports?: string[][];
}
declare class ContextExclusionPlugin {
constructor(negativeMatcher: RegExp);
Expand Down Expand Up @@ -2645,6 +2645,7 @@ declare class Dependency {
endLine?: any,
endColumn?: any
): void;
getContext(): undefined | string;
getResourceIdentifier(): null | string;
couldAffectReferencingModule(): boolean | typeof TRANSITIVE;

Expand Down

0 comments on commit 2c200d1

Please sign in to comment.