Merge pull request #9933 from webpack/bugfix/missing-managed-items
fix problem with snapshotting managed items
This commit is contained in:
commit
408a4ae77e
|
@ -692,57 +692,112 @@ class Compilation {
|
|||
}
|
||||
/** @type {LogEntry[] | undefined} */
|
||||
let logEntries;
|
||||
return new Logger((type, args) => {
|
||||
if (typeof name === "function") {
|
||||
name = name();
|
||||
if (!name) {
|
||||
throw new TypeError(
|
||||
"Compilation.getLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
let trace;
|
||||
switch (type) {
|
||||
case LogType.warn:
|
||||
case LogType.error:
|
||||
case LogType.trace:
|
||||
trace = ErrorHelpers.cutOffLoaderExecution(new Error("Trace").stack)
|
||||
.split("\n")
|
||||
.slice(3);
|
||||
break;
|
||||
}
|
||||
/** @type {LogEntry} */
|
||||
const logEntry = {
|
||||
time: Date.now(),
|
||||
type,
|
||||
args,
|
||||
trace
|
||||
};
|
||||
if (this.hooks.log.call(name, logEntry) === undefined) {
|
||||
if (logEntry.type === LogType.profileEnd) {
|
||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||
if (typeof console.profileEnd === "function") {
|
||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||
console.profileEnd(`[${name}] ${logEntry.args[0]}`);
|
||||
return new Logger(
|
||||
(type, args) => {
|
||||
if (typeof name === "function") {
|
||||
name = name();
|
||||
if (!name) {
|
||||
throw new TypeError(
|
||||
"Compilation.getLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
if (logEntries === undefined) {
|
||||
logEntries = this.logging.get(name);
|
||||
let trace;
|
||||
switch (type) {
|
||||
case LogType.warn:
|
||||
case LogType.error:
|
||||
case LogType.trace:
|
||||
trace = ErrorHelpers.cutOffLoaderExecution(new Error("Trace").stack)
|
||||
.split("\n")
|
||||
.slice(3);
|
||||
break;
|
||||
}
|
||||
/** @type {LogEntry} */
|
||||
const logEntry = {
|
||||
time: Date.now(),
|
||||
type,
|
||||
args,
|
||||
trace
|
||||
};
|
||||
if (this.hooks.log.call(name, logEntry) === undefined) {
|
||||
if (logEntry.type === LogType.profileEnd) {
|
||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||
if (typeof console.profileEnd === "function") {
|
||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||
console.profileEnd(`[${name}] ${logEntry.args[0]}`);
|
||||
}
|
||||
}
|
||||
if (logEntries === undefined) {
|
||||
logEntries = [];
|
||||
this.logging.set(name, logEntries);
|
||||
logEntries = this.logging.get(name);
|
||||
if (logEntries === undefined) {
|
||||
logEntries = [];
|
||||
this.logging.set(name, logEntries);
|
||||
}
|
||||
}
|
||||
logEntries.push(logEntry);
|
||||
if (logEntry.type === LogType.profile) {
|
||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||
if (typeof console.profile === "function") {
|
||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||
console.profile(`[${name}] ${logEntry.args[0]}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
logEntries.push(logEntry);
|
||||
if (logEntry.type === LogType.profile) {
|
||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||
if (typeof console.profile === "function") {
|
||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||
console.profile(`[${name}] ${logEntry.args[0]}`);
|
||||
},
|
||||
childName => {
|
||||
if (typeof name === "function") {
|
||||
if (typeof childName === "function") {
|
||||
return this.getLogger(() => {
|
||||
if (typeof name === "function") {
|
||||
name = name();
|
||||
if (!name) {
|
||||
throw new TypeError(
|
||||
"Compilation.getLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
if (typeof childName === "function") {
|
||||
childName = childName();
|
||||
if (!childName) {
|
||||
throw new TypeError(
|
||||
"Logger.getChildLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
return `${name}/${childName}`;
|
||||
});
|
||||
} else {
|
||||
return this.getLogger(() => {
|
||||
if (typeof name === "function") {
|
||||
name = name();
|
||||
if (!name) {
|
||||
throw new TypeError(
|
||||
"Compilation.getLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
return `${name}/${childName}`;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (typeof childName === "function") {
|
||||
return this.getLogger(() => {
|
||||
if (typeof childName === "function") {
|
||||
childName = childName();
|
||||
if (!childName) {
|
||||
throw new TypeError(
|
||||
"Logger.getChildLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
return `${name}/${childName}`;
|
||||
});
|
||||
} else {
|
||||
return this.getLogger(`${name}/${childName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -232,21 +232,76 @@ class Compiler {
|
|||
"Compiler.getInfrastructureLogger(name) called without a name"
|
||||
);
|
||||
}
|
||||
return new Logger((type, args) => {
|
||||
if (typeof name === "function") {
|
||||
name = name();
|
||||
if (!name) {
|
||||
throw new TypeError(
|
||||
"Compiler.getInfrastructureLogger(name) called with a function not returning a name"
|
||||
);
|
||||
return new Logger(
|
||||
(type, args) => {
|
||||
if (typeof name === "function") {
|
||||
name = name();
|
||||
if (!name) {
|
||||
throw new TypeError(
|
||||
"Compiler.getInfrastructureLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
if (this.hooks.infrastructureLog.call(name, type, args) === undefined) {
|
||||
if (this.infrastructureLogger !== undefined) {
|
||||
this.infrastructureLogger(name, type, args);
|
||||
}
|
||||
}
|
||||
},
|
||||
childName => {
|
||||
if (typeof name === "function") {
|
||||
if (typeof childName === "function") {
|
||||
return this.getInfrastructureLogger(() => {
|
||||
if (typeof name === "function") {
|
||||
name = name();
|
||||
if (!name) {
|
||||
throw new TypeError(
|
||||
"Compiler.getInfrastructureLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
if (typeof childName === "function") {
|
||||
childName = childName();
|
||||
if (!childName) {
|
||||
throw new TypeError(
|
||||
"Logger.getChildLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
return `${name}/${childName}`;
|
||||
});
|
||||
} else {
|
||||
return this.getInfrastructureLogger(() => {
|
||||
if (typeof name === "function") {
|
||||
name = name();
|
||||
if (!name) {
|
||||
throw new TypeError(
|
||||
"Compiler.getInfrastructureLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
return `${name}/${childName}`;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (typeof childName === "function") {
|
||||
return this.getInfrastructureLogger(() => {
|
||||
if (typeof childName === "function") {
|
||||
childName = childName();
|
||||
if (!childName) {
|
||||
throw new TypeError(
|
||||
"Logger.getChildLogger(name) called with a function not returning a name"
|
||||
);
|
||||
}
|
||||
}
|
||||
return `${name}/${childName}`;
|
||||
});
|
||||
} else {
|
||||
return this.getInfrastructureLogger(`${name}/${childName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.hooks.infrastructureLog.call(name, type, args) === undefined) {
|
||||
if (this.infrastructureLogger !== undefined) {
|
||||
this.infrastructureLogger(name, type, args);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,8 @@ const resolveContext = resolve.create({
|
|||
|
||||
let FS_ACCURACY = 2000;
|
||||
|
||||
const EMPTY_SET = new Set();
|
||||
|
||||
const RBDT_RESOLVE = 0;
|
||||
const RBDT_RESOLVE_DIRECTORY = 1;
|
||||
const RBDT_RESOLVE_FILE = 2;
|
||||
|
@ -41,11 +43,11 @@ const INVALID = Symbol("invalid");
|
|||
/**
|
||||
* @typedef {Object} Snapshot
|
||||
* @property {number=} startTime
|
||||
* @property {Map<string, FileSystemInfoEntry | "error">=} fileTimestamps
|
||||
* @property {Map<string, FileSystemInfoEntry | "ignore" | "error">=} fileTimestamps
|
||||
* @property {Map<string, string | "error">=} fileHashes
|
||||
* @property {Map<string, FileSystemInfoEntry | "error">=} contextTimestamps
|
||||
* @property {Map<string, FileSystemInfoEntry | "ignore" | "error">=} contextTimestamps
|
||||
* @property {Map<string, string | "error">=} contextHashes
|
||||
* @property {Map<string, FileSystemInfoEntry | "error">=} missingTimestamps
|
||||
* @property {Map<string, FileSystemInfoEntry | "ignore" | "error">=} missingTimestamps
|
||||
* @property {Map<string, string | "error">=} managedItemInfo
|
||||
*/
|
||||
|
||||
|
@ -143,6 +145,7 @@ const getManagedItem = (managedPath, path) => {
|
|||
if (slashes !== 0) return null;
|
||||
// if (path.slice(i + 1, i + 13) === "node_modules")
|
||||
if (
|
||||
path.length >= i + 13 &&
|
||||
path.charCodeAt(i + 1) === 110 &&
|
||||
path.charCodeAt(i + 2) === 111 &&
|
||||
path.charCodeAt(i + 3) === 100 &&
|
||||
|
@ -156,6 +159,12 @@ const getManagedItem = (managedPath, path) => {
|
|||
path.charCodeAt(i + 11) === 101 &&
|
||||
path.charCodeAt(i + 12) === 115
|
||||
) {
|
||||
// if this is the end of the path
|
||||
if (path.length === i + 13) {
|
||||
// return the node_modules directory
|
||||
// it's special
|
||||
return path;
|
||||
}
|
||||
const c = path.charCodeAt(i + 13);
|
||||
// if next symbol is slash or backslash
|
||||
if (c === 47 || c === 92) {
|
||||
|
@ -184,11 +193,11 @@ class FileSystemInfo {
|
|||
this._loggedPaths = logger ? new Set() : undefined;
|
||||
/** @type {WeakMap<Snapshot, boolean | (function(WebpackError=, boolean=): void)[]>} */
|
||||
this._snapshotCache = new WeakMap();
|
||||
/** @type {Map<string, FileSystemInfoEntry | null>} */
|
||||
/** @type {Map<string, FileSystemInfoEntry | "ignore" | null>} */
|
||||
this._fileTimestamps = new Map();
|
||||
/** @type {Map<string, string>} */
|
||||
this._fileHashes = new Map();
|
||||
/** @type {Map<string, FileSystemInfoEntry | null>} */
|
||||
/** @type {Map<string, FileSystemInfoEntry | "ignore" | null>} */
|
||||
this._contextTimestamps = new Map();
|
||||
/** @type {Map<string, string>} */
|
||||
this._contextHashes = new Map();
|
||||
|
@ -219,6 +228,11 @@ class FileSystemInfo {
|
|||
parallelism: 10,
|
||||
processor: this._getManagedItemInfo.bind(this)
|
||||
});
|
||||
this.managedItemDirectoryQueue = new AsyncQueue({
|
||||
name: "managed item directory info",
|
||||
parallelism: 10,
|
||||
processor: this._getManagedItemDirectoryInfo.bind(this)
|
||||
});
|
||||
this.managedPaths = Array.from(managedPaths);
|
||||
this.managedPathsWithSlash = this.managedPaths.map(p =>
|
||||
join(fs, p, "_").slice(0, -1)
|
||||
|
@ -241,7 +255,7 @@ class FileSystemInfo {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {Map<string, FileSystemInfoEntry | null>} map timestamps
|
||||
* @param {Map<string, FileSystemInfoEntry | "ignore" | null>} map timestamps
|
||||
* @returns {void}
|
||||
*/
|
||||
addFileTimestamps(map) {
|
||||
|
@ -251,7 +265,7 @@ class FileSystemInfo {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {Map<string, FileSystemInfoEntry | null>} map timestamps
|
||||
* @param {Map<string, FileSystemInfoEntry | "ignore" | null>} map timestamps
|
||||
* @returns {void}
|
||||
*/
|
||||
addContextTimestamps(map) {
|
||||
|
@ -262,7 +276,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {string} path file path
|
||||
* @param {function(WebpackError=, FileSystemInfoEntry=): void} callback callback function
|
||||
* @param {function(WebpackError=, (FileSystemInfoEntry | "ignore")=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
getFileTimestamp(path, callback) {
|
||||
|
@ -273,7 +287,7 @@ class FileSystemInfo {
|
|||
|
||||
/**
|
||||
* @param {string} path context path
|
||||
* @param {function(WebpackError=, FileSystemInfoEntry=): void} callback callback function
|
||||
* @param {function(WebpackError=, (FileSystemInfoEntry | "ignore")=): void} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
getContextTimestamp(path, callback) {
|
||||
|
@ -643,15 +657,15 @@ class FileSystemInfo {
|
|||
* @returns {void}
|
||||
*/
|
||||
createSnapshot(startTime, files, directories, missing, options, callback) {
|
||||
/** @type {Map<string, FileSystemInfoEntry | "error">} */
|
||||
/** @type {Map<string, FileSystemInfoEntry | "ignore" | "error">} */
|
||||
const fileTimestamps = new Map();
|
||||
/** @type {Map<string, string | "error">} */
|
||||
const fileHashes = new Map();
|
||||
/** @type {Map<string, FileSystemInfoEntry | "error">} */
|
||||
/** @type {Map<string, FileSystemInfoEntry | "ignore" | "error">} */
|
||||
const contextTimestamps = new Map();
|
||||
/** @type {Map<string, string | "error">} */
|
||||
const contextHashes = new Map();
|
||||
/** @type {Map<string, FileSystemInfoEntry | "error">} */
|
||||
/** @type {Map<string, FileSystemInfoEntry | "ignore" | "error">} */
|
||||
const missingTimestamps = new Map();
|
||||
/** @type {Map<string, string | "error">} */
|
||||
const managedItemInfo = new Map();
|
||||
|
@ -699,6 +713,11 @@ class FileSystemInfo {
|
|||
jobs++;
|
||||
this.fileHashQueue.add(path, (err, entry) => {
|
||||
if (err) {
|
||||
if (this.logger) {
|
||||
this.logger.debug(
|
||||
`Error snapshotting file hash of ${path}: ${err}`
|
||||
);
|
||||
}
|
||||
fileHashes.set(path, "error");
|
||||
} else {
|
||||
fileHashes.set(path, entry);
|
||||
|
@ -730,6 +749,11 @@ class FileSystemInfo {
|
|||
jobs++;
|
||||
this.fileTimestampQueue.add(path, (err, entry) => {
|
||||
if (err) {
|
||||
if (this.logger) {
|
||||
this.logger.debug(
|
||||
`Error snapshotting file timestamp of ${path}: ${err}`
|
||||
);
|
||||
}
|
||||
fileTimestamps.set(path, "error");
|
||||
} else {
|
||||
fileTimestamps.set(path, entry);
|
||||
|
@ -764,6 +788,11 @@ class FileSystemInfo {
|
|||
jobs++;
|
||||
this.contextHashQueue.add(path, (err, entry) => {
|
||||
if (err) {
|
||||
if (this.logger) {
|
||||
this.logger.debug(
|
||||
`Error snapshotting context hash of ${path}: ${err}`
|
||||
);
|
||||
}
|
||||
contextHashes.set(path, "error");
|
||||
} else {
|
||||
contextHashes.set(path, entry);
|
||||
|
@ -795,6 +824,11 @@ class FileSystemInfo {
|
|||
jobs++;
|
||||
this.contextTimestampQueue.add(path, (err, entry) => {
|
||||
if (err) {
|
||||
if (this.logger) {
|
||||
this.logger.debug(
|
||||
`Error snapshotting context timestamp of ${path}: ${err}`
|
||||
);
|
||||
}
|
||||
contextTimestamps.set(path, "error");
|
||||
} else {
|
||||
contextTimestamps.set(path, entry);
|
||||
|
@ -828,6 +862,11 @@ class FileSystemInfo {
|
|||
jobs++;
|
||||
this.fileTimestampQueue.add(path, (err, entry) => {
|
||||
if (err) {
|
||||
if (this.logger) {
|
||||
this.logger.debug(
|
||||
`Error snapshotting missing timestamp of ${path}: ${err}`
|
||||
);
|
||||
}
|
||||
missingTimestamps.set(path, "error");
|
||||
} else {
|
||||
missingTimestamps.set(path, entry);
|
||||
|
@ -840,11 +879,16 @@ class FileSystemInfo {
|
|||
for (const path of managedItems) {
|
||||
const cache = this._managedItems.get(path);
|
||||
if (cache !== undefined) {
|
||||
managedItemInfo.set(path, cache || "error");
|
||||
managedItemInfo.set(path, cache);
|
||||
} else {
|
||||
jobs++;
|
||||
this.managedItemQueue.add(path, (err, entry) => {
|
||||
if (err || !entry) {
|
||||
if (err) {
|
||||
if (this.logger) {
|
||||
this.logger.debug(
|
||||
`Error snapshotting managed item ${path}: ${err}`
|
||||
);
|
||||
}
|
||||
managedItemInfo.set(path, "error");
|
||||
} else {
|
||||
managedItemInfo.set(path, entry);
|
||||
|
@ -964,7 +1008,7 @@ class FileSystemInfo {
|
|||
// If there was an error while snapshotting (i. e. EBUSY)
|
||||
// we can't compare further data and assume it's invalid
|
||||
if (this._remainingLogs > 0) {
|
||||
this._log(path, `there was an error during snapshotting`);
|
||||
this._log(path, `there was an error during snapshotting hash`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -979,8 +1023,8 @@ class FileSystemInfo {
|
|||
};
|
||||
/**
|
||||
* @param {string} path file path
|
||||
* @param {FileSystemInfoEntry} current current entry
|
||||
* @param {FileSystemInfoEntry | "error"} snap entry from snapshot
|
||||
* @param {FileSystemInfoEntry | "ignore"} current current entry
|
||||
* @param {FileSystemInfoEntry | "ignore" | "error"} snap entry from snapshot
|
||||
* @returns {boolean} true, if ok
|
||||
*/
|
||||
const checkExistance = (path, current, snap) => {
|
||||
|
@ -988,10 +1032,12 @@ class FileSystemInfo {
|
|||
// If there was an error while snapshotting (i. e. EBUSY)
|
||||
// we can't compare further data and assume it's invalid
|
||||
if (this._remainingLogs > 0) {
|
||||
this._log(path, `there was an error during snapshotting`);
|
||||
this._log(path, `there was an error during snapshotting existance`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (current === "ignore") return true;
|
||||
if (snap === "ignore") return true;
|
||||
if (!current !== !snap) {
|
||||
// If existance of item differs
|
||||
// it's invalid
|
||||
|
@ -1007,8 +1053,8 @@ class FileSystemInfo {
|
|||
};
|
||||
/**
|
||||
* @param {string} path file path
|
||||
* @param {FileSystemInfoEntry} current current entry
|
||||
* @param {FileSystemInfoEntry | "error"} snap entry from snapshot
|
||||
* @param {FileSystemInfoEntry | "ignore"} current current entry
|
||||
* @param {FileSystemInfoEntry | "ignore" | "error"} snap entry from snapshot
|
||||
* @returns {boolean} true, if ok
|
||||
*/
|
||||
const checkFile = (path, current, snap) => {
|
||||
|
@ -1016,10 +1062,15 @@ class FileSystemInfo {
|
|||
// If there was an error while snapshotting (i. e. EBUSY)
|
||||
// we can't compare further data and assume it's invalid
|
||||
if (this._remainingLogs > 0) {
|
||||
this._log(path, `there was an error during snapshotting`);
|
||||
this._log(
|
||||
path,
|
||||
`there was an error during snapshotting file timestamp`
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (current === "ignore") return true;
|
||||
if (snap === "ignore") return true;
|
||||
if (current && current.safeTime > startTime) {
|
||||
// If a change happened after starting reading the item
|
||||
// this may no longer be valid
|
||||
|
@ -1292,7 +1343,7 @@ class FileSystemInfo {
|
|||
const managedItem = getManagedItem(managedPath, child);
|
||||
if (managedItem) {
|
||||
// construct timestampHash from managed info
|
||||
return this.managedItemQueue.add(child, (err, info) => {
|
||||
return this.managedItemQueue.add(managedItem, (err, info) => {
|
||||
if (err) return callback(err);
|
||||
return callback(null, {
|
||||
safeTime: 0,
|
||||
|
@ -1386,7 +1437,7 @@ class FileSystemInfo {
|
|||
const managedItem = getManagedItem(managedPath, child);
|
||||
if (managedItem) {
|
||||
// construct hash from managed info
|
||||
return this.managedItemQueue.add(child, (err, info) => {
|
||||
return this.managedItemQueue.add(managedItem, (err, info) => {
|
||||
if (err) return callback(err);
|
||||
callback(null, info || "");
|
||||
});
|
||||
|
@ -1427,33 +1478,74 @@ class FileSystemInfo {
|
|||
});
|
||||
}
|
||||
|
||||
_getManagedItemInfo(path, callback) {
|
||||
const packageJsonPath = join(this.fs, path, "package.json");
|
||||
this.fs.readFile(packageJsonPath, (err, content) => {
|
||||
_getManagedItemDirectoryInfo(path, callback) {
|
||||
this.fs.readdir(path, (err, elements) => {
|
||||
if (err) {
|
||||
if (err.code === "ENOENT" || err.code === "ENOTDIR") {
|
||||
// no package.json or path is not a directory
|
||||
this._managedItems.set(path, null);
|
||||
return callback(null, null);
|
||||
return callback(null, EMPTY_SET);
|
||||
}
|
||||
return callback(err);
|
||||
}
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(content.toString("utf-8"));
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
const set = new Set(
|
||||
elements.map(element => join(this.fs, path, element))
|
||||
);
|
||||
callback(null, set);
|
||||
});
|
||||
}
|
||||
|
||||
_getManagedItemInfo(path, callback) {
|
||||
const dir = dirname(this.fs, path);
|
||||
this.managedItemDirectoryQueue.add(dir, (err, elements) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
const info = `${data.name || ""}@${data.version || ""}`;
|
||||
this._managedItems.set(path, info);
|
||||
callback(null, info);
|
||||
if (!elements.has(path)) {
|
||||
// file or directory doesn't exist
|
||||
this._managedItems.set(path, "missing");
|
||||
return callback(null, "missing");
|
||||
}
|
||||
// something exists
|
||||
// it may be a file or directory
|
||||
if (
|
||||
path.endsWith("node_modules") &&
|
||||
(path.endsWith("/node_modules") || path.endsWith("\\node_modules"))
|
||||
) {
|
||||
// we are only interested in existance of this special directory
|
||||
this._managedItems.set(path, "exists");
|
||||
return callback(null, "exists");
|
||||
}
|
||||
|
||||
// we assume it's a directory, as files shouldn't occur in managed paths
|
||||
const packageJsonPath = join(this.fs, path, "package.json");
|
||||
this.fs.readFile(packageJsonPath, (err, content) => {
|
||||
if (err) {
|
||||
if (err.code === "ENOENT" || err.code === "ENOTDIR") {
|
||||
// no package.json or path is not a directory
|
||||
this.logger.warn(
|
||||
`Managed item ${path} isn't a directory or doesn't contain a package.json`
|
||||
);
|
||||
this._managedItems.set(path, "error");
|
||||
return callback(null, "error");
|
||||
}
|
||||
return callback(err);
|
||||
}
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(content.toString("utf-8"));
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
const info = `${data.name || ""}@${data.version || ""}`;
|
||||
this._managedItems.set(path, info);
|
||||
callback(null, info);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getDeprecatedFileTimestamps() {
|
||||
const map = new Map();
|
||||
for (const [path, info] of this._fileTimestamps) {
|
||||
if (info) map.set(path, info.safeTime);
|
||||
if (info) map.set(path, typeof info === "object" ? info.safeTime : null);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
@ -1461,7 +1553,7 @@ class FileSystemInfo {
|
|||
getDeprecatedContextTimestamps() {
|
||||
const map = new Map();
|
||||
for (const [path, info] of this._contextTimestamps) {
|
||||
if (info) map.set(path, info.safeTime);
|
||||
if (info) map.set(path, typeof info === "object" ? info.safeTime : null);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ const schema = require("../schemas/plugins/WatchIgnorePlugin.json");
|
|||
/** @typedef {import("../declarations/plugins/WatchIgnorePlugin").WatchIgnorePluginOptions} WatchIgnorePluginOptions */
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
|
||||
const IGNORE_TIME_ENTRY = "ignore";
|
||||
|
||||
class IgnoringWatchFileSystem {
|
||||
constructor(wfs, paths) {
|
||||
this.wfs = wfs;
|
||||
|
@ -37,11 +39,11 @@ class IgnoringWatchFileSystem {
|
|||
(err, fileTimestamps, dirTimestamps, removedFiles) => {
|
||||
if (err) return callback(err);
|
||||
for (const path of ignoredFiles) {
|
||||
fileTimestamps.set(path, 1);
|
||||
fileTimestamps.set(path, IGNORE_TIME_ENTRY);
|
||||
}
|
||||
|
||||
for (const path of ignoredDirs) {
|
||||
dirTimestamps.set(path, 1);
|
||||
dirTimestamps.set(path, IGNORE_TIME_ENTRY);
|
||||
}
|
||||
|
||||
callback(err, fileTimestamps, dirTimestamps, removedFiles);
|
||||
|
@ -55,14 +57,14 @@ class IgnoringWatchFileSystem {
|
|||
getContextInfoEntries: () => {
|
||||
const dirTimestamps = watcher.getContextInfoEntries();
|
||||
for (const path of ignoredDirs) {
|
||||
dirTimestamps.set(path, 1);
|
||||
dirTimestamps.set(path, IGNORE_TIME_ENTRY);
|
||||
}
|
||||
return dirTimestamps;
|
||||
},
|
||||
getFileTimeInfoEntries: () => {
|
||||
const fileTimestamps = watcher.getFileTimeInfoEntries();
|
||||
for (const path of ignoredFiles) {
|
||||
fileTimestamps.set(path, 1);
|
||||
fileTimestamps.set(path, IGNORE_TIME_ENTRY);
|
||||
}
|
||||
return fileTimestamps;
|
||||
}
|
||||
|
|
|
@ -288,7 +288,8 @@ class PackFileCacheStrategy {
|
|||
this.fileSerializer = createFileSerializer(fs);
|
||||
this.fileSystemInfo = new FileSystemInfo(fs, {
|
||||
managedPaths,
|
||||
immutablePaths
|
||||
immutablePaths,
|
||||
logger: logger.getChildLogger("webpack.FileSystemInfo")
|
||||
});
|
||||
this.context = context;
|
||||
this.cacheLocation = cacheLocation;
|
||||
|
|
|
@ -40,9 +40,11 @@ const TIMERS_SYMBOL = Symbol("webpack logger times");
|
|||
class WebpackLogger {
|
||||
/**
|
||||
* @param {function(LogTypeEnum, any[]=): void} log log function
|
||||
* @param {function(string | function(): string): WebpackLogger} getChildLogger function to create child logger
|
||||
*/
|
||||
constructor(log) {
|
||||
constructor(log, getChildLogger) {
|
||||
this[LOG_SYMBOL] = log;
|
||||
this.getChildLogger = getChildLogger;
|
||||
}
|
||||
|
||||
error(...args) {
|
||||
|
|
|
@ -22,11 +22,14 @@ let currentDefaultLogger = createConsoleLogger(currentDefaultLoggerOptions);
|
|||
* @returns {Logger} a logger
|
||||
*/
|
||||
exports.getLogger = name => {
|
||||
return new Logger((type, args) => {
|
||||
if (exports.hooks.log.call(name, type, args) === undefined) {
|
||||
currentDefaultLogger(name, type, args);
|
||||
}
|
||||
});
|
||||
return new Logger(
|
||||
(type, args) => {
|
||||
if (exports.hooks.log.call(name, type, args) === undefined) {
|
||||
currentDefaultLogger(name, type, args);
|
||||
}
|
||||
},
|
||||
childName => exports.getLogger(`${name}/${childName}`)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"@webassemblyjs/wasm-parser": "1.8.5",
|
||||
"acorn": "^7.0.0",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "5.0.0-beta.3",
|
||||
"enhanced-resolve": "5.0.0-beta.4",
|
||||
"eslint-scope": "^5.0.0",
|
||||
"events": "^3.0.0",
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
|
|
|
@ -6,7 +6,6 @@ describe("TestCases", () => {
|
|||
name: "cache pack",
|
||||
cache: {
|
||||
type: "filesystem",
|
||||
store: "pack",
|
||||
managedPaths: [path.resolve(__dirname, "../node_modules")]
|
||||
},
|
||||
optimization: {
|
||||
|
|
|
@ -24,6 +24,8 @@ function copyDiff(src, dest, initial) {
|
|||
var content = fs.readFileSync(srcFile);
|
||||
if (/^DELETE\s*$/.test(content.toString("utf-8"))) {
|
||||
fs.unlinkSync(destFile);
|
||||
} else if (/^DELETE_DIRECTORY\s*$/.test(content.toString("utf-8"))) {
|
||||
rimraf.sync(destFile);
|
||||
} else {
|
||||
fs.writeFileSync(destFile, content);
|
||||
if (initial) {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import { foo, bar } from "foo";
|
||||
|
||||
it("should have the correct values", () => {
|
||||
expect(foo).toBe("foo");
|
||||
expect(bar).toBe("bar");
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
export const bar = "bar";
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "bar",
|
||||
"version": "0"
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export const foo = "foo";
|
||||
export { bar } from "bar";
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "foo",
|
||||
"version": "0"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import { foo, bar } from "foo";
|
||||
|
||||
it("should invalidate resolving if inner node_modules appears", () => {
|
||||
expect(foo).toBe("foo");
|
||||
expect(bar).toBe("inner-bar");
|
||||
});
|
1
test/watchCases/cache/managedPath/1/node_modules/foo/node_modules/bar/index.js
generated
vendored
Normal file
1
test/watchCases/cache/managedPath/1/node_modules/foo/node_modules/bar/index.js
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
export const bar = "inner-bar";
|
4
test/watchCases/cache/managedPath/1/node_modules/foo/node_modules/bar/package.json
generated
vendored
Normal file
4
test/watchCases/cache/managedPath/1/node_modules/foo/node_modules/bar/package.json
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "bar",
|
||||
"version": "1"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import { foo, bar } from "foo";
|
||||
|
||||
it("should not invalidate managed item if package version stays equal", () => {
|
||||
expect(foo).toBe("foo");
|
||||
expect(bar).toBe("inner-bar");
|
||||
});
|
1
test/watchCases/cache/managedPath/2/node_modules/foo/node_modules/bar/index.js
generated
vendored
Normal file
1
test/watchCases/cache/managedPath/2/node_modules/foo/node_modules/bar/index.js
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
export const bar = "undetected-bar";
|
|
@ -0,0 +1,6 @@
|
|||
import { foo, bar } from "foo";
|
||||
|
||||
it("should invalidate when directory gets deleted", () => {
|
||||
expect(foo).toBe("foo");
|
||||
expect(bar).toBe("bar");
|
||||
});
|
1
test/watchCases/cache/managedPath/3/node_modules/foo/node_modules/bar
generated
vendored
Normal file
1
test/watchCases/cache/managedPath/3/node_modules/foo/node_modules/bar
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
DELETE_DIRECTORY
|
|
@ -0,0 +1,17 @@
|
|||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
mode: "development",
|
||||
cache: {
|
||||
type: "memory",
|
||||
managedPaths: [
|
||||
path.resolve(
|
||||
__dirname,
|
||||
"../../../js/watch-src/cache/managedPath/node_modules"
|
||||
)
|
||||
]
|
||||
},
|
||||
module: {
|
||||
unsafeCache: false
|
||||
}
|
||||
};
|
|
@ -1767,10 +1767,10 @@ end-of-stream@^1.1.0:
|
|||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
enhanced-resolve@5.0.0-beta.3:
|
||||
version "5.0.0-beta.3"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.0.0-beta.3.tgz#1f5b24d223db90a2e86235c365e337fcbf28a68b"
|
||||
integrity sha512-SMjrP/h0qau9mj6L+dY0I350vTnHUDNm3hjV2QRzqhfaa6UYAkDoLfuRWPqAErKDejveFPyGLiQx1A8a5uR5hQ==
|
||||
enhanced-resolve@5.0.0-beta.4:
|
||||
version "5.0.0-beta.4"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.0.0-beta.4.tgz#a14a799c098c2c43ec2cd0b718b14a2eadec7301"
|
||||
integrity sha512-5/C1ZLbPbiFKM9WnF2LKvwresdLoKb0Py6r9XAt9gojZ6wnJb1ay2OzLY+T0DX5KSrimvTufAGISysArUlRpdQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
tapable "^2.0.0-beta.8"
|
||||
|
|
Loading…
Reference in New Issue