mirror of https://github.com/webpack/webpack.git
support undo path
This commit is contained in:
parent
705fb23728
commit
49009486df
|
|
@ -23,6 +23,7 @@ const PublicPathRuntimeModule = require("./runtime/PublicPathRuntimeModule");
|
|||
const SystemContextRuntimeModule = require("./runtime/SystemContextRuntimeModule");
|
||||
const ShareRuntimeModule = require("./sharing/ShareRuntimeModule");
|
||||
const StringXor = require("./util/StringXor");
|
||||
const { getUndoPath } = require("./util/identifier");
|
||||
|
||||
/** @typedef {import("./Chunk")} Chunk */
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
|
|
@ -158,16 +159,24 @@ class RuntimePlugin {
|
|||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.publicPath)
|
||||
.tap("RuntimePlugin", (chunk, runtimeRequirements) => {
|
||||
const {
|
||||
importFunctionName,
|
||||
publicPath,
|
||||
scriptType
|
||||
} = compilation.outputOptions;
|
||||
const module = new PublicPathRuntimeModule(
|
||||
publicPath,
|
||||
scriptType,
|
||||
importFunctionName
|
||||
);
|
||||
const { outputOptions } = compilation;
|
||||
const { publicPath } = outputOptions;
|
||||
let undoPath;
|
||||
|
||||
if (publicPath === "auto") {
|
||||
const chunkName = compilation.getPath(
|
||||
JavascriptModulesPlugin.getChunkFilenameTemplate(
|
||||
chunk,
|
||||
outputOptions
|
||||
),
|
||||
{
|
||||
chunk
|
||||
}
|
||||
);
|
||||
undoPath = getUndoPath(chunkName, false);
|
||||
}
|
||||
|
||||
const module = new PublicPathRuntimeModule(outputOptions, undoPath);
|
||||
|
||||
if (
|
||||
typeof publicPath !== "string" ||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,11 @@ class RuntimeTemplate {
|
|||
return this.outputOptions.environment.module;
|
||||
}
|
||||
|
||||
supportTemplateLiteral() {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
returningFunction(returnValue, args = "") {
|
||||
return this.supportsArrowFunction()
|
||||
? `(${args}) => ${returnValue}`
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ const RuntimeGlobals = require("../RuntimeGlobals");
|
|||
const RuntimeModule = require("../RuntimeModule");
|
||||
const Template = require("../Template");
|
||||
|
||||
/** @typedef {import("../../declarations/WebpackOptions").PublicPath} PublicPath */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").ScriptType} ScriptType */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").Output} OutputOptions */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").PublicPath} PublicPathOptions */
|
||||
/** @typedef {import("../Compilation")} Compilation */
|
||||
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
|
||||
|
||||
class PublicPathRuntimeModule extends RuntimeModule {
|
||||
/**
|
||||
|
|
@ -24,15 +25,16 @@ class PublicPathRuntimeModule extends RuntimeModule {
|
|||
return [RuntimeGlobals.global];
|
||||
}
|
||||
/**
|
||||
* @param {PublicPath} publicPath public path
|
||||
* @param {ScriptType} scriptType script type
|
||||
* @param {string} importName import name
|
||||
* @param {OutputOptions} outputOptions output options
|
||||
* @param {string=} undoPath undo path
|
||||
*/
|
||||
constructor(publicPath, scriptType, importName) {
|
||||
constructor(outputOptions, undoPath) {
|
||||
super("publicPath");
|
||||
const { publicPath, scriptType, importFunctionName } = outputOptions;
|
||||
this.publicPath = publicPath;
|
||||
this.scriptType = scriptType;
|
||||
this.importName = importName;
|
||||
this.importName = importFunctionName;
|
||||
this.undoPath = undoPath;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -43,7 +45,10 @@ class PublicPathRuntimeModule extends RuntimeModule {
|
|||
const { runtimeTemplate } = compilation;
|
||||
if (publicPath === "auto") {
|
||||
if (scriptType === "module") {
|
||||
return `${RuntimeGlobals.publicPath} = ${importName}.meta.url.replace(/[^\\/]+$/, "")`;
|
||||
return `${RuntimeGlobals.publicPath} = ${this.applyUndoPath(
|
||||
`${importName}.meta.url.replace(/[^\\/]+$/, "")`,
|
||||
runtimeTemplate
|
||||
)};`;
|
||||
}
|
||||
|
||||
return `${RuntimeGlobals.publicPath} = ${runtimeTemplate.iife(
|
||||
|
|
@ -51,7 +56,10 @@ class PublicPathRuntimeModule extends RuntimeModule {
|
|||
Template.indent([
|
||||
`if ("document" in ${RuntimeGlobals.global} && "currentScript" in ${RuntimeGlobals.global}.document) `,
|
||||
Template.indent(
|
||||
`return ${RuntimeGlobals.global}.document.currentScript.src.replace(/[^\\/]+$/, "");`
|
||||
`return ${this.applyUndoPath(
|
||||
`${RuntimeGlobals.global}.document.currentScript.src.replace(/[^\\/]+$/, "")`,
|
||||
runtimeTemplate
|
||||
)};`
|
||||
),
|
||||
" else ",
|
||||
Template.indent(`return ${this.definePath("")};`)
|
||||
|
|
@ -63,7 +71,7 @@ class PublicPathRuntimeModule extends RuntimeModule {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {PublicPath} publicPath public path
|
||||
* @param {PublicPathOptions} publicPath public path
|
||||
* @returns {string} runtime code
|
||||
*/
|
||||
definePath(publicPath) {
|
||||
|
|
@ -73,6 +81,22 @@ class PublicPathRuntimeModule extends RuntimeModule {
|
|||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} code code
|
||||
* @param {RuntimeTemplate} runtimeTemplate runtime template
|
||||
* @returns {string} generated code
|
||||
*/
|
||||
applyUndoPath(code, runtimeTemplate) {
|
||||
const { undoPath } = this;
|
||||
if (!undoPath) return code;
|
||||
|
||||
if (runtimeTemplate.supportTemplateLiteral()) {
|
||||
return `\`$\{${code}}${undoPath}\``;
|
||||
}
|
||||
|
||||
return `${code} + "${undoPath}"`;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PublicPathRuntimeModule;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const checkArrayExpectation = require("./checkArrayExpectation");
|
|||
const createLazyTestEnv = require("./helpers/createLazyTestEnv");
|
||||
const deprecationTracking = require("./helpers/deprecationTracking");
|
||||
const FakeDocument = require("./helpers/FakeDocument");
|
||||
const CurrentScript = require("./helpers/CurrentScript");
|
||||
|
||||
const webpack = require("..");
|
||||
const prepareOptions = require("./helpers/prepareOptions");
|
||||
|
|
@ -222,12 +223,13 @@ const describeCases = config => {
|
|||
const bundlePath = testConfig.findBundle(i, optionsArr[i]);
|
||||
if (bundlePath) {
|
||||
filesCount++;
|
||||
const document = new FakeDocument();
|
||||
const globalContext = {
|
||||
console: console,
|
||||
expect: expect,
|
||||
setTimeout: setTimeout,
|
||||
clearTimeout: clearTimeout,
|
||||
document: new FakeDocument(),
|
||||
document,
|
||||
location: {
|
||||
href: "https://test.cases/path/index.html",
|
||||
origin: "https://test.cases",
|
||||
|
|
@ -243,6 +245,7 @@ const describeCases = config => {
|
|||
if (Array.isArray(module) || /^\.\.?\//.test(module)) {
|
||||
let content;
|
||||
let p;
|
||||
let subPath = "";
|
||||
if (Array.isArray(module)) {
|
||||
p = path.join(currentDirectory, ".array-require.js");
|
||||
content = `module.exports = (${module
|
||||
|
|
@ -253,6 +256,26 @@ const describeCases = config => {
|
|||
} else {
|
||||
p = path.join(currentDirectory, module);
|
||||
content = fs.readFileSync(p, "utf-8");
|
||||
const lastSlash = module.lastIndexOf("/");
|
||||
let firstSlash = module.indexOf("/");
|
||||
|
||||
if (lastSlash !== -1 && firstSlash !== lastSlash) {
|
||||
if (firstSlash !== -1) {
|
||||
let next = module.indexOf("/", firstSlash + 1);
|
||||
let dir = module.slice(firstSlash + 1, next);
|
||||
|
||||
while (dir === ".") {
|
||||
firstSlash = next;
|
||||
next = module.indexOf("/", firstSlash + 1);
|
||||
dir = module.slice(firstSlash + 1, next);
|
||||
}
|
||||
}
|
||||
|
||||
subPath = module.slice(
|
||||
firstSlash + 1,
|
||||
lastSlash + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
if (p in requireCache) {
|
||||
return requireCache[p].exports;
|
||||
|
|
@ -262,6 +285,9 @@ const describeCases = config => {
|
|||
};
|
||||
requireCache[p] = m;
|
||||
let runInNewContext = false;
|
||||
let oldCurrentScript = document.currentScript;
|
||||
document.currentScript = new CurrentScript(subPath);
|
||||
|
||||
const moduleScope = {
|
||||
require: _require.bind(
|
||||
null,
|
||||
|
|
@ -357,6 +383,10 @@ const describeCases = config => {
|
|||
? vm.runInNewContext(code, globalContext, p)
|
||||
: vm.runInThisContext(code, p);
|
||||
fn.call(m.exports, moduleScope);
|
||||
|
||||
//restore state
|
||||
document.currentScript = oldCurrentScript;
|
||||
|
||||
return m.exports;
|
||||
} else if (
|
||||
testConfig.modules &&
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
import asset from "./asset.jpg";
|
||||
|
||||
it("should define public path", () => {
|
||||
expect(asset).toBe("https://test.cases/path/inner1/inner2/../../asset.jpg");
|
||||
});
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
module.exports = {
|
||||
findBundle: function() {
|
||||
return [
|
||||
"./inner1/inner2/a.js",
|
||||
"./b.js"
|
||||
];
|
||||
}
|
||||
};
|
||||
|
|
@ -2,7 +2,16 @@
|
|||
module.exports = {
|
||||
mode: "none",
|
||||
target: "web",
|
||||
entry() {
|
||||
return {
|
||||
a: "./a",
|
||||
b: "./b"
|
||||
};
|
||||
},
|
||||
output: {
|
||||
filename: data => {
|
||||
return data.chunk.name === "a" ? `inner1/inner2/[name].js` : "[name].js";
|
||||
},
|
||||
assetModuleFilename: "[name][ext]"
|
||||
},
|
||||
module: {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
class CurrentScript {
|
||||
constructor(path = "", type = "text/javascript") {
|
||||
this.src = `https://test.cases/path/${path}index.js`;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CurrentScript;
|
||||
|
|
@ -2,10 +2,6 @@ module.exports = class FakeDocument {
|
|||
constructor() {
|
||||
this.head = this.createElement("head");
|
||||
this.baseURI = "https://test.cases/path/index.html";
|
||||
this.currentScript = {
|
||||
src: "https://test.cases/path/index.js",
|
||||
type: "text/javascript"
|
||||
};
|
||||
this._elementsByTagName = new Map([["head", [this.head]]]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7774,6 +7774,7 @@ declare abstract class RuntimeTemplate {
|
|||
supportsBigIntLiteral(): boolean;
|
||||
supportsDynamicImport(): boolean;
|
||||
supportsEcmaScriptModuleSyntax(): boolean;
|
||||
supportTemplateLiteral(): boolean;
|
||||
returningFunction(returnValue?: any, args?: string): string;
|
||||
basicFunction(args?: any, body?: any): string;
|
||||
destructureArray(items?: any, value?: any): string;
|
||||
|
|
|
|||
Loading…
Reference in New Issue