fix resolving context for redirects

This commit is contained in:
Tobias Koppers 2021-08-05 18:47:24 +02:00
parent 30ebedd4dd
commit 9bf6797416
4 changed files with 44 additions and 23 deletions

View File

@ -221,6 +221,7 @@ class NormalModule extends Module {
* @param {LoaderItem[]} options.loaders list of loaders
* @param {string} options.resource path + query of the real resource
* @param {Record<string, any>=} options.resourceResolveData resource resolve data
* @param {string} options.context context directory for resolving
* @param {string | undefined} options.matchResource path + query of the matched resource (virtual)
* @param {Parser} options.parser the parser used
* @param {object} options.parserOptions the options of the parser used
@ -237,6 +238,7 @@ class NormalModule extends Module {
loaders,
resource,
resourceResolveData,
context,
matchResource,
parser,
parserOptions,
@ -244,7 +246,7 @@ class NormalModule extends Module {
generatorOptions,
resolveOptions
}) {
super(type, getContext(resource), layer);
super(type, context || getContext(resource), layer);
// Info from Factory
/** @type {string} */
@ -355,6 +357,7 @@ class NormalModule extends Module {
this.generator = m.generator;
this.generatorOptions = m.generatorOptions;
this.resource = m.resource;
this.context = m.context;
this.matchResource = m.matchResource;
this.loaders = m.loaders;
}
@ -1315,6 +1318,7 @@ class NormalModule extends Module {
type: "",
// will be filled by updateCacheModule
resource: "",
context: "",
request: null,
userRequest: null,
rawRequest: null,

View File

@ -5,6 +5,7 @@
"use strict";
const { getContext } = require("loader-runner");
const asyncLib = require("neo-async");
const {
AsyncSeriesBailHook,
@ -60,6 +61,7 @@ const { parseResource } = require("./util/identifier");
* @property {string} path
* @property {string} query
* @property {string} fragment
* @property {string=} context
*/
/** @typedef {ResourceData & { data: Record<string, any> }} ResourceDataWithData */
@ -572,6 +574,8 @@ class NormalModuleFactory extends ModuleFactory {
rawRequest: request,
loaders: allLoaders,
resource: resourceData.resource,
context:
resourceData.context || getContext(resourceData.resource),
matchResource: matchResourceData
? matchResourceData.resource
: undefined,
@ -687,7 +691,8 @@ class NormalModuleFactory extends ModuleFactory {
data: {},
path: undefined,
query: undefined,
fragment: undefined
fragment: undefined,
context: undefined
};
this.hooks.resolveForScheme
.for(scheme)
@ -704,7 +709,8 @@ class NormalModuleFactory extends ModuleFactory {
data: {},
path: undefined,
query: undefined,
fragment: undefined
fragment: undefined,
context: undefined
};
this.hooks.resolveInScheme
.for(contextScheme)
@ -914,7 +920,7 @@ ${hints.join("\n\n")}`;
null,
`Did you mean '${resource}'?
BREAKING CHANGE: The request '${unresolvedResource}' failed to resolve only because it was resolved as fully specified
(probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.`
);

View File

@ -886,20 +886,31 @@ Run build with un-frozen lockfile to automatically fix lockfile.`
}
);
const respondWithUrlModule = (url, resourceData, callback) => {
getInfo(url.href, (err, result) => {
if (err) return callback(err);
resourceData.resource = url.href;
resourceData.path = url.origin + url.pathname;
resourceData.query = url.search;
resourceData.fragment = url.hash;
resourceData.context = new URL(
".",
result.entry.resolved
).href.slice(0, -1);
resourceData.data.mimetype = result.entry.contentType;
callback(null, true);
});
};
normalModuleFactory.hooks.resolveForScheme
.for(scheme)
.tapAsync(
"HttpUriPlugin",
(resourceData, resolveData, callback) => {
getInfo(resourceData.resource, (err, result) => {
if (err) return callback(err);
const url = new URL(resourceData.resource);
resourceData.path = url.origin + url.pathname;
resourceData.query = url.search;
resourceData.fragment = url.hash;
resourceData.data.mimetype = result.entry.contentType;
callback(null, true);
});
respondWithUrlModule(
new URL(resourceData.resource),
resourceData,
callback
);
}
);
normalModuleFactory.hooks.resolveInScheme
@ -912,16 +923,11 @@ Run build with un-frozen lockfile to automatically fix lockfile.`
) {
return callback();
}
const url = new URL(resourceData.resource, data.context + "/");
getInfo(url.href, (err, result) => {
if (err) return callback(err);
resourceData.resource = url.href;
resourceData.path = url.origin + url.pathname;
resourceData.query = url.search;
resourceData.fragment = url.hash;
resourceData.data.mimetype = result.entry.contentType;
callback(null, true);
});
respondWithUrlModule(
new URL(resourceData.resource, data.context + "/"),
resourceData,
callback
);
});
const hooks = NormalModule.getCompilationHooks(compilation);
hooks.readResourceForScheme

5
types.d.ts vendored
View File

@ -7187,6 +7187,10 @@ declare class NormalModule extends Module {
* resource resolve data
*/
resourceResolveData?: Record<string, any>;
/**
* context directory for resolving
*/
context: string;
/**
* path + query of the matched resource (virtual)
*/
@ -9344,6 +9348,7 @@ declare interface ResourceDataWithData {
path: string;
query: string;
fragment: string;
context?: string;
data: Record<string, any>;
}
type Rule = string | RegExp;