allow to place runtime outside of the output path

This commit is contained in:
Tobias Koppers 2021-03-16 13:07:45 +01:00
parent 2abcede6cd
commit 7dc945f147
10 changed files with 123 additions and 10 deletions

View File

@ -55,7 +55,11 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
contentHashType: "javascript"
}
);
const rootOutputDir = getUndoPath(outputName, false);
const rootOutputDir = getUndoPath(
outputName,
this.compilation.outputOptions.path,
false
);
return Template.asString([
withBaseURI

View File

@ -55,7 +55,11 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule {
contentHashType: "javascript"
}
);
const rootOutputDir = getUndoPath(outputName, true);
const rootOutputDir = getUndoPath(
outputName,
this.compilation.outputOptions.path,
true
);
return Template.asString([
withBaseURI

View File

@ -20,7 +20,7 @@ class AutoPublicPathRuntimeModule extends RuntimeModule {
*/
generate() {
const { compilation } = this;
const { scriptType, importMetaName } = compilation.outputOptions;
const { scriptType, importMetaName, path } = compilation.outputOptions;
const chunkName = compilation.getPath(
JavascriptModulesPlugin.getChunkFilenameTemplate(
this.chunk,
@ -31,7 +31,7 @@ class AutoPublicPathRuntimeModule extends RuntimeModule {
contentHashType: "javascript"
}
);
const undoPath = getUndoPath(chunkName, false);
const undoPath = getUndoPath(chunkName, path, false);
return Template.asString([
"var scriptUrl;",

View File

@ -305,15 +305,33 @@ exports.parseResource = (realFn => {
/**
* @param {string} filename the filename which should be undone
* @param {string} outputPath the output path that is restored (only relevant when filename contains "..")
* @param {boolean} enforceRelative true returns ./ for empty paths
* @returns {string} repeated ../ to leave the directory of the provided filename to be back on root dir
* @returns {string} repeated ../ to leave the directory of the provided filename to be back on output dir
*/
exports.getUndoPath = (filename, enforceRelative) => {
exports.getUndoPath = (filename, outputPath, enforceRelative) => {
let depth = -1;
let append = "";
outputPath = outputPath.replace(/[\\/]$/, "");
for (const part of filename.split(/[/\\]+/)) {
if (part !== ".") {
depth += part === ".." ? -1 : 1;
if (part === "..") {
if (depth > -1) {
depth--;
} else {
const i = outputPath.lastIndexOf("/");
const j = outputPath.lastIndexOf("\\");
const pos = i < 0 ? j : j < 0 ? i : Math.max(i, j);
if (pos < 0) return outputPath + "/";
append = outputPath.slice(pos + 1) + "/" + append;
outputPath = outputPath.slice(0, pos);
}
} else if (part !== ".") {
depth++;
}
}
return depth > 0 ? "../".repeat(depth) : enforceRelative ? "./" : "";
return depth > 0
? `${"../".repeat(depth)}${append}`
: enforceRelative
? `./${append}`
: append;
};

View File

@ -59,7 +59,11 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
contentHashType: "javascript"
}
);
const rootOutputDir = getUndoPath(outputName, false);
const rootOutputDir = getUndoPath(
outputName,
this.compilation.outputOptions.path,
false
);
return Template.asString([
withBaseURI

View File

@ -0,0 +1 @@
export default 42;

View File

@ -0,0 +1,4 @@
it("should load on demand", () =>
import(/* webpackChunkName: "././../chunk/chunk/./../" */ "./chunk").then(r =>
expect(r).toEqual(expect.objectContaining({ default: 42 }))
));

View File

@ -0,0 +1,8 @@
module.exports = {
findBundle: function (i, options) {
return [
`../weird-names2-out/entry/entry-${options.target}.js`,
`../weird-names2-out/entry-${options.target}.js`
];
}
};

View File

@ -0,0 +1,32 @@
const entry = {
"././../weird-names2-out/entry/point/./../entry": "./index.js",
"..//weird-names2-out////entry": "./index.js"
};
/** @type {import("../../../../").Configuration[]} */
module.exports = [
{
target: "async-node",
entry,
output: {
filename: "[name]-async-node.js",
chunkFilename: "chunks/[name]-async-node.js"
}
},
{
target: "node",
entry,
output: {
filename: "[name]-node.js",
chunkFilename: "chunks/[name]-node.js"
}
},
{
target: "webworker",
entry,
output: {
filename: "[name]-webworker.js",
chunkFilename: "chunks/[name]-webworker.js"
}
}
];

View File

@ -51,4 +51,42 @@ describe("util/identifier", () => {
});
});
});
describe("getUndoPath", () => {
const cases = [
["file.js", ""],
["file.js", "./", true],
["dir/file.js", "../"],
["dir/file.js", "../", true],
["./file.js", ""],
[".dir/file.js", "../"],
["./dir/file.js", "../"],
["./dir/././file.js", "../"],
["./dir/../file.js", ""],
["./dir/../file.js", "./", true],
["../file.js", "d/"],
["../file.js", "./d/", true],
["../dir/file.js", "../d/"],
[".././../dir/file.js", "../c/d/"],
["./.././../dir/file.js", "../c/d/"],
["../dir/../file.js", "d/"],
["../dir/../file.js", "./d/", true]
];
for (const [filename, expected, enforceRelative] of cases) {
it(`should handle ${filename} correctly${
enforceRelative ? " (enforced relative path)" : ""
}`, () => {
for (const outputPath of [
"/a/b/c/d",
"C:\\a\\b\\c\\d",
"/a/b/c/d/",
"C:\\a\\b\\c\\d\\"
]) {
expect(
identifierUtil.getUndoPath(filename, outputPath, enforceRelative)
).toBe(expected);
}
});
}
});
});