fix: prevent asset conflicts between React and Grid.js versions

Add coexistence checks to all enqueue methods to prevent loading
both React and Grid.js assets simultaneously.

Changes:
- ReactAdmin.php: Only enqueue React assets when ?react=1
- Init.php: Skip Grid.js when React active on admin pages
- Form.php, Coupon.php, Access.php: Restore classic assets when ?react=0
- Customer.php, Product.php, License.php: Add coexistence checks

Now the toggle between Classic and React versions works correctly.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
dwindown
2026-04-18 17:02:14 +07:00
parent bd9cdac02e
commit e8fbfb14c1
74973 changed files with 6658406 additions and 71 deletions

View File

@@ -0,0 +1,96 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { find } = require("../util/SetHelpers");
const {
compareModulesByPostOrderIndexOrIdentifier,
compareModulesByPreOrderIndexOrIdentifier
} = require("../util/comparators");
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../ChunkGraph").ModuleComparator} ModuleComparator */
/**
* Defines the chunk module id range plugin options type used by this module.
* @typedef {object} ChunkModuleIdRangePluginOptions
* @property {string} name the chunk name
* @property {("index" | "index2" | "preOrderIndex" | "postOrderIndex")=} order order
* @property {number=} start start id
* @property {number=} end end id
*/
const PLUGIN_NAME = "ChunkModuleIdRangePlugin";
class ChunkModuleIdRangePlugin {
/**
* Creates an instance of ChunkModuleIdRangePlugin.
* @param {ChunkModuleIdRangePluginOptions} options options object
*/
constructor(options) {
/** @type {ChunkModuleIdRangePluginOptions} */
this.options = options;
}
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
const moduleGraph = compilation.moduleGraph;
compilation.hooks.moduleIds.tap(PLUGIN_NAME, (modules) => {
const chunkGraph = compilation.chunkGraph;
const chunk = find(
compilation.chunks,
(chunk) => chunk.name === this.options.name
);
if (!chunk) {
throw new Error(
`${PLUGIN_NAME}: Chunk with name '${this.options.name}"' was not found`
);
}
/** @type {Module[]} */
let chunkModules;
if (this.options.order) {
/** @type {ModuleComparator} */
let cmpFn;
switch (this.options.order) {
case "index":
case "preOrderIndex":
cmpFn = compareModulesByPreOrderIndexOrIdentifier(moduleGraph);
break;
case "index2":
case "postOrderIndex":
cmpFn = compareModulesByPostOrderIndexOrIdentifier(moduleGraph);
break;
default:
throw new Error(`${PLUGIN_NAME}: unexpected value of order`);
}
chunkModules = chunkGraph.getOrderedChunkModules(chunk, cmpFn);
} else {
chunkModules = [...modules]
.filter((m) => chunkGraph.isModuleInChunk(m, chunk))
.sort(compareModulesByPreOrderIndexOrIdentifier(moduleGraph));
}
let currentId = this.options.start || 0;
for (let i = 0; i < chunkModules.length; i++) {
const m = chunkModules[i];
if (m.needId && chunkGraph.getModuleId(m) === null) {
chunkGraph.setModuleId(m, currentId++);
}
if (this.options.end && currentId > this.options.end) break;
}
});
});
}
}
module.exports = ChunkModuleIdRangePlugin;

View File

@@ -0,0 +1,75 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Florent Cailhol @ooflorent
*/
"use strict";
const { compareChunksNatural } = require("../util/comparators");
const {
assignDeterministicIds,
getFullChunkName,
getUsedChunkIds
} = require("./IdHelpers");
/** @typedef {import("../Compiler")} Compiler */
/**
* Defines the deterministic chunk ids plugin options type used by this module.
* @typedef {object} DeterministicChunkIdsPluginOptions
* @property {string=} context context for ids
* @property {number=} maxLength maximum length of ids
*/
const PLUGIN_NAME = "DeterministicChunkIdsPlugin";
class DeterministicChunkIdsPlugin {
/**
* Creates an instance of DeterministicChunkIdsPlugin.
* @param {DeterministicChunkIdsPluginOptions=} options options
*/
constructor(options = {}) {
/** @type {DeterministicChunkIdsPluginOptions} */
this.options = options;
}
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
compilation.hooks.chunkIds.tap(PLUGIN_NAME, (chunks) => {
const chunkGraph = compilation.chunkGraph;
const context = this.options.context
? this.options.context
: compiler.context;
const maxLength = this.options.maxLength || 3;
const compareNatural = compareChunksNatural(chunkGraph);
const usedIds = getUsedChunkIds(compilation);
assignDeterministicIds(
[...chunks].filter((chunk) => chunk.id === null),
(chunk) =>
getFullChunkName(chunk, chunkGraph, context, compiler.root),
compareNatural,
(chunk, id) => {
const size = usedIds.size;
usedIds.add(`${id}`);
if (size === usedIds.size) return false;
chunk.id = id;
chunk.ids = [id];
return true;
},
[10 ** maxLength],
10,
usedIds.size
);
});
});
}
}
module.exports = DeterministicChunkIdsPlugin;

View File

@@ -0,0 +1,100 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Florent Cailhol @ooflorent
*/
"use strict";
const {
compareModulesByPreOrderIndexOrIdentifier
} = require("../util/comparators");
const {
assignDeterministicIds,
getFullModuleName,
getUsedModuleIdsAndModules
} = require("./IdHelpers");
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/**
* Defines the deterministic module ids plugin options type used by this module.
* @typedef {object} DeterministicModuleIdsPluginOptions
* @property {string=} context context relative to which module identifiers are computed
* @property {((module: Module) => boolean)=} test selector function for modules
* @property {number=} maxLength maximum id length in digits (used as starting point)
* @property {number=} salt hash salt for ids
* @property {boolean=} fixedLength do not increase the maxLength to find an optimal id space size
* @property {boolean=} failOnConflict throw an error when id conflicts occur (instead of rehashing)
*/
const PLUGIN_NAME = "DeterministicModuleIdsPlugin";
class DeterministicModuleIdsPlugin {
/**
* Creates an instance of DeterministicModuleIdsPlugin.
* @param {DeterministicModuleIdsPluginOptions=} options options
*/
constructor(options = {}) {
/** @type {DeterministicModuleIdsPluginOptions} */
this.options = options;
}
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
compilation.hooks.moduleIds.tap(PLUGIN_NAME, () => {
const chunkGraph = compilation.chunkGraph;
const context = this.options.context
? this.options.context
: compiler.context;
const maxLength = this.options.maxLength || 3;
const failOnConflict = this.options.failOnConflict || false;
const fixedLength = this.options.fixedLength || false;
const salt = this.options.salt || 0;
let conflicts = 0;
const [usedIds, modules] = getUsedModuleIdsAndModules(
compilation,
this.options.test
);
assignDeterministicIds(
modules,
(module) => getFullModuleName(module, context, compiler.root),
failOnConflict
? () => 0
: compareModulesByPreOrderIndexOrIdentifier(
compilation.moduleGraph
),
(module, id) => {
const size = usedIds.size;
usedIds.add(`${id}`);
if (size === usedIds.size) {
conflicts++;
return false;
}
chunkGraph.setModuleId(module, id);
return true;
},
[10 ** maxLength],
fixedLength ? 0 : 10,
usedIds.size,
salt
);
if (failOnConflict && conflicts) {
throw new Error(
`Assigning deterministic module ids has lead to ${conflicts} conflict${
conflicts > 1 ? "s" : ""
}.\nIncrease the 'maxLength' to increase the id space and make conflicts less likely (recommended when there are many conflicts or application is expected to grow), or add an 'salt' number to try another hash starting value in the same id space (recommended when there is only a single conflict).`
);
}
});
});
}
}
module.exports = DeterministicModuleIdsPlugin;

84
node_modules/webpack/lib/ids/HashedModuleIdsPlugin.js generated vendored Normal file
View File

@@ -0,0 +1,84 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { DEFAULTS } = require("../config/defaults");
const {
compareModulesByPreOrderIndexOrIdentifier
} = require("../util/comparators");
const createHash = require("../util/createHash");
const {
getFullModuleName,
getUsedModuleIdsAndModules
} = require("./IdHelpers");
/** @typedef {import("../../declarations/plugins/ids/HashedModuleIdsPlugin").HashedModuleIdsPluginOptions} HashedModuleIdsPluginOptions */
/** @typedef {import("../Compiler")} Compiler */
const PLUGIN_NAME = "HashedModuleIdsPlugin";
class HashedModuleIdsPlugin {
/**
* Creates an instance of HashedModuleIdsPlugin.
* @param {HashedModuleIdsPluginOptions=} options options object
*/
constructor(options = {}) {
/** @type {HashedModuleIdsPluginOptions} */
this.options = options;
}
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.validate.tap(PLUGIN_NAME, () => {
compiler.validate(
() => require("../../schemas/plugins/ids/HashedModuleIdsPlugin.json"),
this.options,
{
name: "Hashed Module Ids Plugin",
baseDataPath: "options"
},
(options) =>
require("../../schemas/plugins/ids/HashedModuleIdsPlugin.check")(
options
)
);
});
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
compilation.hooks.moduleIds.tap(PLUGIN_NAME, () => {
const chunkGraph = compilation.chunkGraph;
const context = this.options.context
? this.options.context
: compiler.context;
const [usedIds, modules] = getUsedModuleIdsAndModules(compilation);
const modulesInNaturalOrder = modules.sort(
compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
);
for (const module of modulesInNaturalOrder) {
const ident = getFullModuleName(module, context, compiler.root);
const hash = createHash(
this.options.hashFunction || DEFAULTS.HASH_FUNCTION
);
hash.update(ident || "");
const hashId = hash.digest(this.options.hashDigest || "base64");
let len = this.options.hashDigestLength || 4;
while (usedIds.has(hashId.slice(0, len))) {
/** @type {number} */ (len)++;
}
const moduleId = hashId.slice(0, len);
chunkGraph.setModuleId(module, moduleId);
usedIds.add(moduleId);
}
});
});
}
}
module.exports = HashedModuleIdsPlugin;

512
node_modules/webpack/lib/ids/IdHelpers.js generated vendored Normal file
View File

@@ -0,0 +1,512 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const createHash = require("../util/createHash");
const { makePathsRelative } = require("../util/identifier");
const numberHash = require("../util/numberHash");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../util/Hash").HashFunction} HashFunction */
/** @typedef {import("../util/identifier").AssociatedObjectForCache} AssociatedObjectForCache */
/** @typedef {import("../Module").BuildMeta} BuildMeta */
/**
* Returns hash.
* @param {string} str string to hash
* @param {number} len max length of the hash
* @param {HashFunction} hashFunction hash function to use
* @returns {string} hash
*/
const getHash = (str, len, hashFunction) => {
const hash = createHash(hashFunction);
hash.update(str);
const digest = hash.digest("hex");
return digest.slice(0, len);
};
/**
* Returns string prefixed by an underscore if it is a number.
* @param {string} str the string
* @returns {string} string prefixed by an underscore if it is a number
*/
const avoidNumber = (str) => {
// max length of a number is 21 chars, bigger numbers a written as "...e+xx"
if (str.length > 21) return str;
const firstChar = str.charCodeAt(0);
// skip everything that doesn't look like a number
// charCodes: "-": 45, "1": 49, "9": 57
if (firstChar < 49) {
if (firstChar !== 45) return str;
} else if (firstChar > 57) {
return str;
}
if (str === String(Number(str))) {
return `_${str}`;
}
return str;
};
/**
* Returns id representation.
* @param {string} request the request
* @returns {string} id representation
*/
const requestToId = (request) =>
request.replace(/^(\.\.?\/)+/, "").replace(/(^[.-]|[^a-z0-9_-])+/gi, "_");
/**
* Shorten long string.
* @param {string} string the string
* @param {string} delimiter separator for string and hash
* @param {HashFunction} hashFunction hash function to use
* @returns {string} string with limited max length to 100 chars
*/
const shortenLongString = (string, delimiter, hashFunction) => {
if (string.length < 100) return string;
return (
string.slice(0, 100 - 6 - delimiter.length) +
delimiter +
getHash(string, 6, hashFunction)
);
};
/**
* Gets short module name.
* @param {Module} module the module
* @param {string} context context directory
* @param {AssociatedObjectForCache=} associatedObjectForCache an object to which the cache will be attached
* @returns {string} short module name
*/
const getShortModuleName = (module, context, associatedObjectForCache) => {
const libIdent = module.libIdent({ context, associatedObjectForCache });
if (libIdent) return avoidNumber(libIdent);
const nameForCondition = module.nameForCondition();
if (nameForCondition) {
return avoidNumber(
makePathsRelative(context, nameForCondition, associatedObjectForCache)
);
}
return "";
};
/**
* Gets long module name.
* @param {string} shortName the short name
* @param {Module} module the module
* @param {string} context context directory
* @param {HashFunction} hashFunction hash function to use
* @param {AssociatedObjectForCache=} associatedObjectForCache an object to which the cache will be attached
* @returns {string} long module name
*/
const getLongModuleName = (
shortName,
module,
context,
hashFunction,
associatedObjectForCache
) => {
const fullName = getFullModuleName(module, context, associatedObjectForCache);
return `${shortName}?${getHash(fullName, 4, hashFunction)}`;
};
/**
* Gets full module name.
* @param {Module} module the module
* @param {string} context context directory
* @param {AssociatedObjectForCache=} associatedObjectForCache an object to which the cache will be attached
* @returns {string} full module name
*/
const getFullModuleName = (module, context, associatedObjectForCache) =>
makePathsRelative(context, module.identifier(), associatedObjectForCache);
/**
* Gets short chunk name.
* @param {Chunk} chunk the chunk
* @param {ChunkGraph} chunkGraph the chunk graph
* @param {string} context context directory
* @param {string} delimiter delimiter for names
* @param {HashFunction} hashFunction hash function to use
* @param {AssociatedObjectForCache=} associatedObjectForCache an object to which the cache will be attached
* @returns {string} short chunk name
*/
const getShortChunkName = (
chunk,
chunkGraph,
context,
delimiter,
hashFunction,
associatedObjectForCache
) => {
const modules = chunkGraph.getChunkRootModules(chunk);
const shortModuleNames = modules.map((m) =>
requestToId(getShortModuleName(m, context, associatedObjectForCache))
);
chunk.idNameHints.sort();
const chunkName = [...chunk.idNameHints, ...shortModuleNames]
.filter(Boolean)
.join(delimiter);
return shortenLongString(chunkName, delimiter, hashFunction);
};
/**
* Gets long chunk name.
* @param {Chunk} chunk the chunk
* @param {ChunkGraph} chunkGraph the chunk graph
* @param {string} context context directory
* @param {string} delimiter delimiter for names
* @param {HashFunction} hashFunction hash function to use
* @param {AssociatedObjectForCache=} associatedObjectForCache an object to which the cache will be attached
* @returns {string} short chunk name
*/
const getLongChunkName = (
chunk,
chunkGraph,
context,
delimiter,
hashFunction,
associatedObjectForCache
) => {
const modules = chunkGraph.getChunkRootModules(chunk);
const shortModuleNames = modules.map((m) =>
requestToId(getShortModuleName(m, context, associatedObjectForCache))
);
const longModuleNames = modules.map((m) =>
requestToId(
getLongModuleName("", m, context, hashFunction, associatedObjectForCache)
)
);
chunk.idNameHints.sort();
const chunkName = [
...chunk.idNameHints,
...shortModuleNames,
...longModuleNames
]
.filter(Boolean)
.join(delimiter);
return shortenLongString(chunkName, delimiter, hashFunction);
};
/**
* Gets full chunk name.
* @param {Chunk} chunk the chunk
* @param {ChunkGraph} chunkGraph the chunk graph
* @param {string} context context directory
* @param {AssociatedObjectForCache=} associatedObjectForCache an object to which the cache will be attached
* @returns {string} full chunk name
*/
const getFullChunkName = (
chunk,
chunkGraph,
context,
associatedObjectForCache
) => {
if (chunk.name) return chunk.name;
const modules = chunkGraph.getChunkRootModules(chunk);
const fullModuleNames = modules.map((m) =>
makePathsRelative(context, m.identifier(), associatedObjectForCache)
);
return fullModuleNames.join();
};
/**
* Adds to map of items.
* @template K
* @template V
* @param {Map<K, V[]>} map a map from key to values
* @param {K} key key
* @param {V} value value
* @returns {void}
*/
const addToMapOfItems = (map, key, value) => {
let array = map.get(key);
if (array === undefined) {
array = [];
map.set(key, array);
}
array.push(value);
};
/** @typedef {Set<string>} UsedModuleIds */
/**
* Gets used module ids and modules.
* @param {Compilation} compilation the compilation
* @param {((module: Module) => boolean)=} filter filter modules
* @returns {[UsedModuleIds, Module[]]} used module ids as strings and modules without id matching the filter
*/
const getUsedModuleIdsAndModules = (compilation, filter) => {
const chunkGraph = compilation.chunkGraph;
/** @type {Module[]} */
const modules = [];
/** @type {UsedModuleIds} */
const usedIds = new Set();
if (compilation.usedModuleIds) {
for (const id of compilation.usedModuleIds) {
usedIds.add(String(id));
}
}
for (const module of compilation.modules) {
if (!module.needId) continue;
const moduleId = chunkGraph.getModuleId(module);
if (moduleId !== null) {
usedIds.add(String(moduleId));
} else if (
(!filter || filter(module)) &&
(chunkGraph.getNumberOfModuleChunks(module) !== 0 ||
// CSS modules need IDs even when not in chunks, for generating CSS class names(i.e. [id]-[local])
/** @type {BuildMeta} */ (module.buildMeta).isCSSModule)
) {
modules.push(module);
}
}
return [usedIds, modules];
};
/** @typedef {Set<string>} UsedChunkIds */
/**
* Gets used chunk ids.
* @param {Compilation} compilation the compilation
* @returns {UsedChunkIds} used chunk ids as strings
*/
const getUsedChunkIds = (compilation) => {
/** @type {UsedChunkIds} */
const usedIds = new Set();
if (compilation.usedChunkIds) {
for (const id of compilation.usedChunkIds) {
usedIds.add(String(id));
}
}
for (const chunk of compilation.chunks) {
const chunkId = chunk.id;
if (chunkId !== null) {
usedIds.add(String(chunkId));
}
}
return usedIds;
};
/**
* Returns list of items without a name.
* @template T
* @param {Iterable<T>} items list of items to be named
* @param {(item: T) => string} getShortName get a short name for an item
* @param {(item: T, name: string) => string} getLongName get a long name for an item
* @param {(a: T, b: T) => -1 | 0 | 1} comparator order of items
* @param {Set<string>} usedIds already used ids, will not be assigned
* @param {(item: T, name: string) => void} assignName assign a name to an item
* @returns {T[]} list of items without a name
*/
const assignNames = (
items,
getShortName,
getLongName,
comparator,
usedIds,
assignName
) => {
/**
* Defines the map to item type used by this module.
* @template T
* @typedef {Map<string, T[]>} MapToItem
*/
/** @type {MapToItem<T>} */
const nameToItems = new Map();
for (const item of items) {
const name = getShortName(item);
addToMapOfItems(nameToItems, name, item);
}
/** @type {MapToItem<T>} */
const nameToItems2 = new Map();
for (const [name, items] of nameToItems) {
if (items.length > 1 || !name) {
for (const item of items) {
const longName = getLongName(item, name);
addToMapOfItems(nameToItems2, longName, item);
}
} else {
addToMapOfItems(nameToItems2, name, items[0]);
}
}
/** @type {T[]} */
const unnamedItems = [];
for (const [name, items] of nameToItems2) {
if (!name) {
for (const item of items) {
unnamedItems.push(item);
}
} else if (items.length === 1 && !usedIds.has(name)) {
assignName(items[0], name);
usedIds.add(name);
} else {
items.sort(comparator);
let i = 0;
for (const item of items) {
while (nameToItems2.has(name + i) && usedIds.has(name + i)) i++;
assignName(item, name + i);
usedIds.add(name + i);
i++;
}
}
}
unnamedItems.sort(comparator);
return unnamedItems;
};
/**
* Assign deterministic ids.
* @template T
* @param {T[]} items list of items to be named
* @param {(item: T) => string} getName get a name for an item
* @param {(a: T, n: T) => -1 | 0 | 1} comparator order of items
* @param {(item: T, id: number) => boolean} assignId assign an id to an item
* @param {number[]} ranges usable ranges for ids
* @param {number} expandFactor factor to create more ranges
* @param {number} extraSpace extra space to allocate, i. e. when some ids are already used
* @param {number} salt salting number to initialize hashing
* @returns {void}
*/
const assignDeterministicIds = (
items,
getName,
comparator,
assignId,
ranges = [10],
expandFactor = 10,
extraSpace = 0,
salt = 0
) => {
items.sort(comparator);
// max 5% fill rate
const optimalRange = Math.min(
items.length * 20 + extraSpace,
Number.MAX_SAFE_INTEGER
);
let i = 0;
let range = ranges[i];
while (range < optimalRange) {
i++;
if (i < ranges.length) {
range = Math.min(ranges[i], Number.MAX_SAFE_INTEGER);
} else if (expandFactor) {
range = Math.min(range * expandFactor, Number.MAX_SAFE_INTEGER);
} else {
break;
}
}
for (const item of items) {
const ident = getName(item);
/** @type {number} */
let id;
let i = salt;
do {
id = numberHash(ident + i++, range);
} while (!assignId(item, id));
}
};
/**
* Assign ascending module ids.
* @param {UsedModuleIds} usedIds used ids
* @param {Iterable<Module>} modules the modules
* @param {Compilation} compilation the compilation
* @returns {void}
*/
const assignAscendingModuleIds = (usedIds, modules, compilation) => {
const chunkGraph = compilation.chunkGraph;
let nextId = 0;
/** @type {(mod: Module) => void} */
let assignId;
if (usedIds.size > 0) {
/**
* Processes the provided module.
* @param {Module} module the module
*/
assignId = (module) => {
if (chunkGraph.getModuleId(module) === null) {
while (usedIds.has(String(nextId))) nextId++;
chunkGraph.setModuleId(module, nextId++);
}
};
} else {
/**
* Processes the provided module.
* @param {Module} module the module
*/
assignId = (module) => {
if (chunkGraph.getModuleId(module) === null) {
chunkGraph.setModuleId(module, nextId++);
}
};
}
for (const module of modules) {
assignId(module);
}
};
/**
* Assign ascending chunk ids.
* @param {Iterable<Chunk>} chunks the chunks
* @param {Compilation} compilation the compilation
* @returns {void}
*/
const assignAscendingChunkIds = (chunks, compilation) => {
const usedIds = getUsedChunkIds(compilation);
let nextId = 0;
if (usedIds.size > 0) {
for (const chunk of chunks) {
if (chunk.id === null) {
while (usedIds.has(String(nextId))) nextId++;
chunk.id = nextId;
chunk.ids = [nextId];
nextId++;
}
}
} else {
for (const chunk of chunks) {
if (chunk.id === null) {
chunk.id = nextId;
chunk.ids = [nextId];
nextId++;
}
}
}
};
module.exports.assignAscendingChunkIds = assignAscendingChunkIds;
module.exports.assignAscendingModuleIds = assignAscendingModuleIds;
module.exports.assignDeterministicIds = assignDeterministicIds;
module.exports.assignNames = assignNames;
module.exports.getFullChunkName = getFullChunkName;
module.exports.getFullModuleName = getFullModuleName;
module.exports.getLongChunkName = getLongChunkName;
module.exports.getLongModuleName = getLongModuleName;
module.exports.getShortChunkName = getShortChunkName;
module.exports.getShortModuleName = getShortModuleName;
module.exports.getUsedChunkIds = getUsedChunkIds;
module.exports.getUsedModuleIdsAndModules = getUsedModuleIdsAndModules;
module.exports.requestToId = requestToId;

94
node_modules/webpack/lib/ids/NamedChunkIdsPlugin.js generated vendored Normal file
View File

@@ -0,0 +1,94 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { compareChunksNatural } = require("../util/comparators");
const {
assignAscendingChunkIds,
assignNames,
getLongChunkName,
getShortChunkName,
getUsedChunkIds
} = require("./IdHelpers");
/** @typedef {import("../Compiler")} Compiler */
/**
* Defines the named chunk ids plugin options type used by this module.
* @typedef {object} NamedChunkIdsPluginOptions
* @property {string=} context context
* @property {string=} delimiter delimiter
*/
const PLUGIN_NAME = "NamedChunkIdsPlugin";
class NamedChunkIdsPlugin {
/**
* Creates an instance of NamedChunkIdsPlugin.
* @param {NamedChunkIdsPluginOptions=} options options
*/
constructor(options = {}) {
/** @type {NamedChunkIdsPluginOptions} */
this.options = options;
}
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
const hashFunction = compilation.outputOptions.hashFunction;
compilation.hooks.chunkIds.tap(PLUGIN_NAME, (chunks) => {
const chunkGraph = compilation.chunkGraph;
const context = this.options.context
? this.options.context
: compiler.context;
const delimiter = this.options.delimiter || "-";
const unnamedChunks = assignNames(
[...chunks].filter((chunk) => {
if (chunk.name) {
chunk.id = chunk.name;
chunk.ids = [chunk.name];
}
return chunk.id === null;
}),
(chunk) =>
getShortChunkName(
chunk,
chunkGraph,
context,
delimiter,
hashFunction,
compiler.root
),
(chunk) =>
getLongChunkName(
chunk,
chunkGraph,
context,
delimiter,
hashFunction,
compiler.root
),
compareChunksNatural(chunkGraph),
getUsedChunkIds(compilation),
(chunk, name) => {
chunk.id = name;
chunk.ids = [name];
}
);
if (unnamedChunks.length > 0) {
assignAscendingChunkIds(unnamedChunks, compilation);
}
});
});
}
}
module.exports = NamedChunkIdsPlugin;

70
node_modules/webpack/lib/ids/NamedModuleIdsPlugin.js generated vendored Normal file
View File

@@ -0,0 +1,70 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { compareModulesByIdentifier } = require("../util/comparators");
const {
assignAscendingModuleIds,
assignNames,
getLongModuleName,
getShortModuleName,
getUsedModuleIdsAndModules
} = require("./IdHelpers");
/** @typedef {import("../Compiler")} Compiler */
/**
* Defines the named module ids plugin options type used by this module.
* @typedef {object} NamedModuleIdsPluginOptions
* @property {string=} context context
*/
const PLUGIN_NAME = "NamedModuleIdsPlugin";
class NamedModuleIdsPlugin {
/**
* Creates an instance of NamedModuleIdsPlugin.
* @param {NamedModuleIdsPluginOptions=} options options
*/
constructor(options = {}) {
/** @type {NamedModuleIdsPluginOptions} */
this.options = options;
}
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
const { root } = compiler;
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
const hashFunction = compilation.outputOptions.hashFunction;
compilation.hooks.moduleIds.tap(PLUGIN_NAME, () => {
const chunkGraph = compilation.chunkGraph;
const context = this.options.context
? this.options.context
: compiler.context;
const [usedIds, modules] = getUsedModuleIdsAndModules(compilation);
const unnamedModules = assignNames(
modules,
(m) => getShortModuleName(m, context, root),
(m, shortName) =>
getLongModuleName(shortName, m, context, hashFunction, root),
compareModulesByIdentifier,
usedIds,
(m, name) => chunkGraph.setModuleId(m, name)
);
if (unnamedModules.length > 0) {
assignAscendingModuleIds(usedIds, unnamedModules, compilation);
}
});
});
}
}
module.exports = NamedModuleIdsPlugin;

35
node_modules/webpack/lib/ids/NaturalChunkIdsPlugin.js generated vendored Normal file
View File

@@ -0,0 +1,35 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { compareChunksNatural } = require("../util/comparators");
const { assignAscendingChunkIds } = require("./IdHelpers");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */
const PLUGIN_NAME = "NaturalChunkIdsPlugin";
class NaturalChunkIdsPlugin {
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
compilation.hooks.chunkIds.tap(PLUGIN_NAME, (chunks) => {
const chunkGraph = compilation.chunkGraph;
const compareNatural = compareChunksNatural(chunkGraph);
/** @type {Chunk[]} */
const chunksInNaturalOrder = [...chunks].sort(compareNatural);
assignAscendingChunkIds(chunksInNaturalOrder, compilation);
});
});
}
}
module.exports = NaturalChunkIdsPlugin;

40
node_modules/webpack/lib/ids/NaturalModuleIdsPlugin.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Florent Cailhol @ooflorent
*/
"use strict";
const {
compareModulesByPreOrderIndexOrIdentifier
} = require("../util/comparators");
const {
assignAscendingModuleIds,
getUsedModuleIdsAndModules
} = require("./IdHelpers");
/** @typedef {import("../Compiler")} Compiler */
const PLUGIN_NAME = "NaturalModuleIdsPlugin";
class NaturalModuleIdsPlugin {
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
compilation.hooks.moduleIds.tap(PLUGIN_NAME, () => {
const [usedIds, modulesInNaturalOrder] =
getUsedModuleIdsAndModules(compilation);
modulesInNaturalOrder.sort(
compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
);
assignAscendingModuleIds(usedIds, modulesInNaturalOrder, compilation);
});
});
}
}
module.exports = NaturalModuleIdsPlugin;

View File

@@ -0,0 +1,91 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { compareChunksNatural } = require("../util/comparators");
const { assignAscendingChunkIds } = require("./IdHelpers");
/** @typedef {import("../../declarations/plugins/ids/OccurrenceChunkIdsPlugin").OccurrenceChunkIdsPluginOptions} OccurrenceChunkIdsPluginOptions */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */
const PLUGIN_NAME = "OccurrenceChunkIdsPlugin";
class OccurrenceChunkIdsPlugin {
/**
* Creates an instance of OccurrenceChunkIdsPlugin.
* @param {OccurrenceChunkIdsPluginOptions=} options options object
*/
constructor(options = {}) {
/** @type {OccurrenceChunkIdsPluginOptions} */
this.options = options;
}
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.validate.tap(PLUGIN_NAME, () => {
compiler.validate(
() =>
require("../../schemas/plugins/ids/OccurrenceChunkIdsPlugin.json"),
this.options,
{
name: "Occurrence Order Chunk Ids Plugin",
baseDataPath: "options"
},
(options) =>
require("../../schemas/plugins/ids/OccurrenceChunkIdsPlugin.check")(
options
)
);
});
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
compilation.hooks.chunkIds.tap(PLUGIN_NAME, (chunks) => {
const chunkGraph = compilation.chunkGraph;
/** @type {Map<Chunk, number>} */
const occursInInitialChunksMap = new Map();
const compareNatural = compareChunksNatural(chunkGraph);
for (const c of chunks) {
let occurs = 0;
for (const chunkGroup of c.groupsIterable) {
for (const parent of chunkGroup.parentsIterable) {
if (parent.isInitial()) occurs++;
}
}
occursInInitialChunksMap.set(c, occurs);
}
/** @type {Chunk[]} */
const chunksInOccurrenceOrder = [...chunks].sort((a, b) => {
if (this.options.prioritiseInitial) {
const aEntryOccurs =
/** @type {number} */
(occursInInitialChunksMap.get(a));
const bEntryOccurs =
/** @type {number} */
(occursInInitialChunksMap.get(b));
if (aEntryOccurs > bEntryOccurs) return -1;
if (aEntryOccurs < bEntryOccurs) return 1;
}
const aOccurs = a.getNumberOfGroups();
const bOccurs = b.getNumberOfGroups();
if (aOccurs > bOccurs) return -1;
if (aOccurs < bOccurs) return 1;
return compareNatural(a, b);
});
assignAscendingChunkIds(chunksInOccurrenceOrder, compilation);
});
});
}
}
module.exports = OccurrenceChunkIdsPlugin;

View File

@@ -0,0 +1,175 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const {
compareModulesByPreOrderIndexOrIdentifier
} = require("../util/comparators");
const {
assignAscendingModuleIds,
getUsedModuleIdsAndModules
} = require("./IdHelpers");
/** @typedef {import("../../declarations/plugins/ids/OccurrenceModuleIdsPlugin").OccurrenceModuleIdsPluginOptions} OccurrenceModuleIdsPluginOptions */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
const PLUGIN_NAME = "OccurrenceModuleIdsPlugin";
class OccurrenceModuleIdsPlugin {
/**
* Creates an instance of OccurrenceModuleIdsPlugin.
* @param {OccurrenceModuleIdsPluginOptions=} options options object
*/
constructor(options = {}) {
/** @type {OccurrenceModuleIdsPluginOptions} */
this.options = options;
}
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.validate.tap(PLUGIN_NAME, () => {
compiler.validate(
() =>
require("../../schemas/plugins/ids/OccurrenceModuleIdsPlugin.json"),
this.options,
{
name: "Occurrence Order Module Ids Plugin",
baseDataPath: "options"
},
(options) =>
require("../../schemas/plugins/ids/OccurrenceModuleIdsPlugin.check")(
options
)
);
});
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
const moduleGraph = compilation.moduleGraph;
compilation.hooks.moduleIds.tap(PLUGIN_NAME, () => {
const chunkGraph = compilation.chunkGraph;
const [usedIds, modulesInOccurrenceOrder] =
getUsedModuleIdsAndModules(compilation);
/** @type {Map<Module, number>} */
const occursInInitialChunksMap = new Map();
/** @type {Map<Module, number>} */
const occursInAllChunksMap = new Map();
/** @type {Map<Module, number>} */
const initialChunkChunkMap = new Map();
/** @type {Map<Module, number>} */
const entryCountMap = new Map();
for (const m of modulesInOccurrenceOrder) {
let initial = 0;
let entry = 0;
for (const c of chunkGraph.getModuleChunksIterable(m)) {
if (c.canBeInitial()) initial++;
if (chunkGraph.isEntryModuleInChunk(m, c)) entry++;
}
initialChunkChunkMap.set(m, initial);
entryCountMap.set(m, entry);
}
/**
* Count occurs in entry.
* @param {Module} module module
* @returns {number} count of occurs
*/
const countOccursInEntry = (module) => {
let sum = 0;
for (const [
originModule,
connections
] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
if (!originModule) continue;
if (!connections.some((c) => c.isTargetActive(undefined))) continue;
sum += initialChunkChunkMap.get(originModule) || 0;
}
return sum;
};
/**
* Returns count of occurs.
* @param {Module} module module
* @returns {number} count of occurs
*/
const countOccurs = (module) => {
let sum = 0;
for (const [
originModule,
connections
] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
if (!originModule) continue;
const chunkModules =
chunkGraph.getNumberOfModuleChunks(originModule);
for (const c of connections) {
if (!c.isTargetActive(undefined)) continue;
if (!c.dependency) continue;
const factor = c.dependency.getNumberOfIdOccurrences();
if (factor === 0) continue;
sum += factor * chunkModules;
}
}
return sum;
};
if (this.options.prioritiseInitial) {
for (const m of modulesInOccurrenceOrder) {
const result =
countOccursInEntry(m) +
/** @type {number} */ (initialChunkChunkMap.get(m)) +
/** @type {number} */ (entryCountMap.get(m));
occursInInitialChunksMap.set(m, result);
}
}
for (const m of modulesInOccurrenceOrder) {
const result =
countOccurs(m) +
chunkGraph.getNumberOfModuleChunks(m) +
/** @type {number} */ (entryCountMap.get(m));
occursInAllChunksMap.set(m, result);
}
const naturalCompare = compareModulesByPreOrderIndexOrIdentifier(
compilation.moduleGraph
);
modulesInOccurrenceOrder.sort((a, b) => {
if (this.options.prioritiseInitial) {
const aEntryOccurs =
/** @type {number} */
(occursInInitialChunksMap.get(a));
const bEntryOccurs =
/** @type {number} */
(occursInInitialChunksMap.get(b));
if (aEntryOccurs > bEntryOccurs) return -1;
if (aEntryOccurs < bEntryOccurs) return 1;
}
const aOccurs = /** @type {number} */ (occursInAllChunksMap.get(a));
const bOccurs = /** @type {number} */ (occursInAllChunksMap.get(b));
if (aOccurs > bOccurs) return -1;
if (aOccurs < bOccurs) return 1;
return naturalCompare(a, b);
});
assignAscendingModuleIds(
usedIds,
modulesInOccurrenceOrder,
compilation
);
});
});
}
}
module.exports = OccurrenceModuleIdsPlugin;

163
node_modules/webpack/lib/ids/SyncModuleIdsPlugin.js generated vendored Normal file
View File

@@ -0,0 +1,163 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { WebpackError } = require("..");
const { getUsedModuleIdsAndModules } = require("./IdHelpers");
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../Module").ModuleId} ModuleId */
/** @typedef {import("../util/fs").IntermediateFileSystem} IntermediateFileSystem */
/** @typedef {{ [key: string]: ModuleId }} JSONContent */
const plugin = "SyncModuleIdsPlugin";
/**
* Represents the sync module ids plugin runtime component.
* @typedef {object} SyncModuleIdsPluginOptions
* @property {string} path path to file
* @property {string=} context context for module names
* @property {((module: Module) => boolean)=} test selector for modules
* @property {"read" | "create" | "merge" | "update"=} mode operation mode (defaults to merge)
*/
class SyncModuleIdsPlugin {
/**
* Creates an instance of SyncModuleIdsPlugin.
* @param {SyncModuleIdsPluginOptions} options options
*/
constructor(options) {
/** @type {SyncModuleIdsPluginOptions} */
this.options = options;
}
/**
* Applies the plugin by registering its hooks on the compiler.
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
/** @type {Map<string, ModuleId>} */
let data;
let dataChanged = false;
const readAndWrite =
!this.options.mode ||
this.options.mode === "merge" ||
this.options.mode === "update";
const needRead = readAndWrite || this.options.mode === "read";
const needWrite = readAndWrite || this.options.mode === "create";
const needPrune = this.options.mode === "update";
if (needRead) {
compiler.hooks.readRecords.tapAsync(plugin, (callback) => {
const fs =
/** @type {IntermediateFileSystem} */
(compiler.intermediateFileSystem);
fs.readFile(this.options.path, (err, buffer) => {
if (err) {
if (err.code !== "ENOENT") {
return callback(err);
}
return callback();
}
/** @type {JSONContent} */
const json = JSON.parse(/** @type {Buffer} */ (buffer).toString());
/** @type {Map<string, string | number | null>} */
data = new Map();
for (const key of Object.keys(json)) {
data.set(key, json[key]);
}
dataChanged = false;
return callback();
});
});
}
if (needWrite) {
compiler.hooks.emitRecords.tapAsync(plugin, (callback) => {
if (!data || !dataChanged) return callback();
/** @type {JSONContent} */
const json = {};
const sorted = [...data].sort(([a], [b]) => (a < b ? -1 : 1));
for (const [key, value] of sorted) {
json[key] = value;
}
const fs =
/** @type {IntermediateFileSystem} */
(compiler.intermediateFileSystem);
fs.writeFile(this.options.path, JSON.stringify(json), callback);
});
}
compiler.hooks.thisCompilation.tap(plugin, (compilation) => {
const associatedObjectForCache = compiler.root;
const context = this.options.context || compiler.context;
const test = this.options.test || (() => true);
if (needRead) {
compilation.hooks.reviveModules.tap(plugin, (_1, _2) => {
if (!data) return;
const { chunkGraph } = compilation;
const [usedIds, modules] = getUsedModuleIdsAndModules(
compilation,
test
);
for (const module of modules) {
const name = module.libIdent({
context,
associatedObjectForCache
});
if (!name) continue;
const id = data.get(name);
const idAsString = `${id}`;
if (usedIds.has(idAsString)) {
const err = new WebpackError(
`SyncModuleIdsPlugin: Unable to restore id '${id}' from '${this.options.path}' as it's already used.`
);
err.module = module;
compilation.errors.push(err);
}
chunkGraph.setModuleId(module, /** @type {ModuleId} */ (id));
usedIds.add(idAsString);
}
});
}
if (needWrite) {
compilation.hooks.recordModules.tap(plugin, (modules) => {
const { chunkGraph } = compilation;
let oldData = data;
if (!oldData) {
oldData = data = new Map();
} else if (needPrune) {
data = new Map();
}
for (const module of modules) {
if (test(module)) {
const name = module.libIdent({
context,
associatedObjectForCache
});
if (!name) continue;
const id = chunkGraph.getModuleId(module);
if (id === null) continue;
const oldId = oldData.get(name);
if (oldId !== id) {
dataChanged = true;
} else if (data === oldData) {
continue;
}
data.set(name, id);
}
}
if (data.size !== oldData.size) dataChanged = true;
});
}
});
}
}
module.exports = SyncModuleIdsPlugin;