mirror of https://github.com/webpack/webpack.git
				
				
				
			
						commit
						c17dfde7a8
					
				|  | @ -75,6 +75,16 @@ export type ExternalItem = | |||
|  * via the `definition` "ArrayOfStringValues". | ||||
|  */ | ||||
| export type ArrayOfStringValues = string[]; | ||||
| /** | ||||
|  * This interface was referenced by `WebpackOptions`'s JSON-Schema | ||||
|  * via the `definition` "FilterTypes". | ||||
|  */ | ||||
| export type FilterTypes = FilterItemTypes | FilterItemTypes[]; | ||||
| /** | ||||
|  * This interface was referenced by `WebpackOptions`'s JSON-Schema | ||||
|  * via the `definition` "FilterItemTypes". | ||||
|  */ | ||||
| export type FilterItemTypes = RegExp | string | ((value: string) => boolean); | ||||
| /** | ||||
|  * One or multiple rule conditions | ||||
|  * | ||||
|  | @ -256,16 +266,6 @@ export type OptimizationSplitChunksSizes = | |||
| 			 */ | ||||
| 			[k: string]: number; | ||||
| 	  }; | ||||
| /** | ||||
|  * This interface was referenced by `WebpackOptions`'s JSON-Schema | ||||
|  * via the `definition` "FilterTypes". | ||||
|  */ | ||||
| export type FilterTypes = FilterItemTypes | FilterItemTypes[]; | ||||
| /** | ||||
|  * This interface was referenced by `WebpackOptions`'s JSON-Schema | ||||
|  * via the `definition` "FilterItemTypes". | ||||
|  */ | ||||
| export type FilterItemTypes = RegExp | string | Function; | ||||
| 
 | ||||
| export interface WebpackOptions { | ||||
| 	/** | ||||
|  | @ -314,6 +314,19 @@ export interface WebpackOptions { | |||
| 	 * Specify dependencies that shouldn't be resolved by webpack, but should become dependencies of the resulting bundle. The kind of the dependency depends on `output.libraryTarget`. | ||||
| 	 */ | ||||
| 	externals?: Externals; | ||||
| 	/** | ||||
| 	 * Options for infrastructure level logging | ||||
| 	 */ | ||||
| 	infrastructureLogging?: { | ||||
| 		/** | ||||
| 		 * Enable debug logging for specific loggers | ||||
| 		 */ | ||||
| 		debug?: FilterTypes | boolean; | ||||
| 		/** | ||||
| 		 * Log level | ||||
| 		 */ | ||||
| 		level?: "none" | "error" | "warn" | "info" | "log" | "verbose"; | ||||
| 	}; | ||||
| 	/** | ||||
| 	 * Custom values available in the loader context. | ||||
| 	 */ | ||||
|  | @ -1435,6 +1448,18 @@ export interface StatsOptions { | |||
| 	 * add the hash of the compilation | ||||
| 	 */ | ||||
| 	hash?: boolean; | ||||
| 	/** | ||||
| 	 * add logging output | ||||
| 	 */ | ||||
| 	logging?: boolean | ("none" | "error" | "warn" | "info" | "log" | "verbose"); | ||||
| 	/** | ||||
| 	 * Include debug logging of specified loggers (i. e. for plugins or loaders). Filters can be Strings, RegExps or Functions | ||||
| 	 */ | ||||
| 	loggingDebug?: FilterTypes | boolean; | ||||
| 	/** | ||||
| 	 * add stack traces to logging output | ||||
| 	 */ | ||||
| 	loggingTrace?: boolean; | ||||
| 	/** | ||||
| 	 * Set the maximum number of modules to be shown | ||||
| 	 */ | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ const ChunkRenderError = require("./ChunkRenderError"); | |||
| const ChunkTemplate = require("./ChunkTemplate"); | ||||
| const DependencyTemplates = require("./DependencyTemplates"); | ||||
| const Entrypoint = require("./Entrypoint"); | ||||
| const ErrorHelpers = require("./ErrorHelpers"); | ||||
| const FileSystemInfo = require("./FileSystemInfo"); | ||||
| const { | ||||
| 	connectChunkGroupAndChunk, | ||||
|  | @ -41,6 +42,7 @@ const RuntimeGlobals = require("./RuntimeGlobals"); | |||
| const RuntimeTemplate = require("./RuntimeTemplate"); | ||||
| const Stats = require("./Stats"); | ||||
| const WebpackError = require("./WebpackError"); | ||||
| const { Logger, LogType } = require("./logging/Logger"); | ||||
| const StatsFactory = require("./stats/StatsFactory"); | ||||
| const StatsPrinter = require("./stats/StatsPrinter"); | ||||
| const AsyncQueue = require("./util/AsyncQueue"); | ||||
|  | @ -127,6 +129,14 @@ const { arrayToSetDeprecation } = require("./util/deprecation"); | |||
|  * @property {(Record<string, (length: number) => string>)=} contentHashWithLength | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * @typedef {Object} LogEntry | ||||
|  * @property {string} type | ||||
|  * @property {any[]} args | ||||
|  * @property {number} time | ||||
|  * @property {string[]=} trace | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * @typedef {Object} ModulePathData | ||||
|  * @property {string|number} id | ||||
|  | @ -405,6 +415,9 @@ class Compilation { | |||
| 				"compilerIndex" | ||||
| 			]), | ||||
| 
 | ||||
| 			/** @type {SyncBailHook<[string, LogEntry], true>} */ | ||||
| 			log: new SyncBailHook(["origin", "logEntry"]), | ||||
| 
 | ||||
| 			/** @type {HookMap<SyncHook<[Object, Object]>>} */ | ||||
| 			statsPreset: new HookMap(() => new SyncHook(["options", "context"])), | ||||
| 			/** @type {SyncHook<[Object, Object]>} */ | ||||
|  | @ -520,6 +533,8 @@ class Compilation { | |||
| 		this.warnings = []; | ||||
| 		/** @type {Compilation[]} */ | ||||
| 		this.children = []; | ||||
| 		/** @type {Map<string, LogEntry[]>} */ | ||||
| 		this.logging = new Map(); | ||||
| 		/** @type {Map<DepConstructor, ModuleFactory>} */ | ||||
| 		this.dependencyFactories = new Map(); | ||||
| 		/** @type {DependencyTemplates} */ | ||||
|  | @ -582,6 +597,69 @@ class Compilation { | |||
| 		return statsPrinter; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {string | (function(): string)} name name of the logger, or function called once to get the logger name | ||||
| 	 * @returns {Logger} a logger with that name | ||||
| 	 */ | ||||
| 	getLogger(name) { | ||||
| 		if (!name) { | ||||
| 			throw new TypeError("Compilation.getLogger(name) called without a name"); | ||||
| 		} | ||||
| 		/** @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]}`); | ||||
| 					} | ||||
| 				} | ||||
| 				if (logEntries === undefined) { | ||||
| 					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]}`); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Module} module module to be added that was created | ||||
| 	 * @param {ModuleCallback} callback returns the module in the compilation, | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ const RequestShortener = require("./RequestShortener"); | |||
| const ResolverFactory = require("./ResolverFactory"); | ||||
| const Stats = require("./Stats"); | ||||
| const Watching = require("./Watching"); | ||||
| const { Logger } = require("./logging/Logger"); | ||||
| const { join, dirname, mkdirp } = require("./util/fs"); | ||||
| const { makePathsRelative } = require("./util/identifier"); | ||||
| 
 | ||||
|  | @ -133,6 +134,9 @@ class Compiler { | |||
| 			/** @type {SyncHook<[]>} */ | ||||
| 			watchClose: new SyncHook([]), | ||||
| 
 | ||||
| 			/** @type {SyncBailHook<[string, string, any[]], true>} */ | ||||
| 			infrastructurelog: new SyncBailHook(["origin", "type", "args"]), | ||||
| 
 | ||||
| 			// TODO the following hooks are weirdly located here
 | ||||
| 			// TODO move them for webpack 5
 | ||||
| 			/** @type {SyncHook<[]>} */ | ||||
|  | @ -178,6 +182,8 @@ class Compiler { | |||
| 		/** @type {ResolverFactory} */ | ||||
| 		this.resolverFactory = new ResolverFactory(); | ||||
| 
 | ||||
| 		this.infrastructureLogger = undefined; | ||||
| 
 | ||||
| 		/** @type {WebpackOptions} */ | ||||
| 		this.options = /** @type {WebpackOptions} */ ({}); | ||||
| 
 | ||||
|  | @ -201,6 +207,33 @@ class Compiler { | |||
| 		this._assetEmittingWrittenFiles = new Map(); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {string | (function(): string)} name name of the logger, or function called once to get the logger name | ||||
| 	 * @returns {Logger} a logger with that name | ||||
| 	 */ | ||||
| 	getInfrastructureLogger(name) { | ||||
| 		if (!name) { | ||||
| 			throw new TypeError( | ||||
| 				"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" | ||||
| 					); | ||||
| 				} | ||||
| 			} | ||||
| 			if (this.hooks.infrastructurelog.call(name, type, args) === undefined) { | ||||
| 				if (this.infrastructureLogger !== undefined) { | ||||
| 					this.infrastructureLogger(name, type, args); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {WatchOptions} watchOptions the watcher's options | ||||
| 	 * @param {Callback<Stats>} handler signals when the call finishes | ||||
|  |  | |||
|  | @ -248,16 +248,20 @@ class NormalModule extends Module { | |||
| 
 | ||||
| 	createLoaderContext(resolver, options, compilation, fs) { | ||||
| 		const requestShortener = compilation.runtimeTemplate.requestShortener; | ||||
| 		const getCurrentLoaderName = () => { | ||||
| 			const currentLoader = this.getCurrentLoader(loaderContext); | ||||
| 			if (!currentLoader) return "(not in loader scope)"; | ||||
| 			return requestShortener.shorten(currentLoader.loader); | ||||
| 		}; | ||||
| 		const loaderContext = { | ||||
| 			version: 2, | ||||
| 			emitWarning: warning => { | ||||
| 				if (!(warning instanceof Error)) { | ||||
| 					warning = new NonErrorEmittedError(warning); | ||||
| 				} | ||||
| 				const currentLoader = this.getCurrentLoader(loaderContext); | ||||
| 				this.warnings.push( | ||||
| 					new ModuleWarning(warning, { | ||||
| 						from: requestShortener.shorten(currentLoader.loader) | ||||
| 						from: getCurrentLoaderName() | ||||
| 					}) | ||||
| 				); | ||||
| 			}, | ||||
|  | @ -265,13 +269,20 @@ class NormalModule extends Module { | |||
| 				if (!(error instanceof Error)) { | ||||
| 					error = new NonErrorEmittedError(error); | ||||
| 				} | ||||
| 				const currentLoader = this.getCurrentLoader(loaderContext); | ||||
| 				this.errors.push( | ||||
| 					new ModuleError(error, { | ||||
| 						from: requestShortener.shorten(currentLoader.loader) | ||||
| 						from: getCurrentLoaderName() | ||||
| 					}) | ||||
| 				); | ||||
| 			}, | ||||
| 			getLogger: name => { | ||||
| 				const currentLoader = this.getCurrentLoader(loaderContext); | ||||
| 				return compilation.getLogger(() => | ||||
| 					[currentLoader && currentLoader.loader, name, this.identifier()] | ||||
| 						.filter(Boolean) | ||||
| 						.join("|") | ||||
| 				); | ||||
| 			}, | ||||
| 			resolve(context, request, callback) { | ||||
| 				resolver.resolve({}, context, request, {}, callback); | ||||
| 			}, | ||||
|  |  | |||
|  | @ -443,6 +443,12 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { | |||
| 		this.set("resolveLoader.mainFields", ["loader", "main"]); | ||||
| 		this.set("resolveLoader.extensions", [".js"]); | ||||
| 		this.set("resolveLoader.mainFiles", ["index"]); | ||||
| 
 | ||||
| 		this.set("infrastructureLogging", "call", value => | ||||
| 			Object.assign({}, value) | ||||
| 		); | ||||
| 		this.set("infrastructureLogging.level", "info"); | ||||
| 		this.set("infrastructureLogging.debug", false); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,126 @@ | |||
| /* | ||||
| 	MIT License http://www.opensource.org/licenses/mit-license.php
 | ||||
| 	Author Tobias Koppers @sokra | ||||
| */ | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| /** | ||||
|  * @enum {string} | ||||
|  */ | ||||
| const LogType = Object.freeze({ | ||||
| 	error: "error", // message, c style arguments
 | ||||
| 	warn: "warn", // message, c style arguments
 | ||||
| 	info: "info", // message, c style arguments
 | ||||
| 	log: "log", // message, c style arguments
 | ||||
| 	debug: "debug", // message, c style arguments
 | ||||
| 
 | ||||
| 	trace: "trace", // no arguments
 | ||||
| 
 | ||||
| 	group: "group", // [label]
 | ||||
| 	groupCollapsed: "groupCollapsed", // [label]
 | ||||
| 	groupEnd: "groupEnd", // [label]
 | ||||
| 
 | ||||
| 	profile: "profile", // [profileName]
 | ||||
| 	profileEnd: "profileEnd", // [profileName]
 | ||||
| 
 | ||||
| 	time: "time", // name, time as [seconds, nanoseconds]
 | ||||
| 
 | ||||
| 	clear: "clear" // no arguments
 | ||||
| }); | ||||
| 
 | ||||
| exports.LogType = LogType; | ||||
| 
 | ||||
| /** @typedef {LogType} LogTypeEnum */ | ||||
| 
 | ||||
| const LOG_SYMBOL = Symbol("webpack logger raw log method"); | ||||
| const TIMERS_SYMBOL = Symbol("webpack logger times"); | ||||
| 
 | ||||
| class WebpackLogger { | ||||
| 	/** | ||||
| 	 * @param {function(LogType, any[]=): void} log log function | ||||
| 	 */ | ||||
| 	constructor(log) { | ||||
| 		this[LOG_SYMBOL] = log; | ||||
| 	} | ||||
| 
 | ||||
| 	error(...args) { | ||||
| 		this[LOG_SYMBOL](LogType.error, args); | ||||
| 	} | ||||
| 
 | ||||
| 	warn(...args) { | ||||
| 		this[LOG_SYMBOL](LogType.warn, args); | ||||
| 	} | ||||
| 
 | ||||
| 	info(...args) { | ||||
| 		this[LOG_SYMBOL](LogType.info, args); | ||||
| 	} | ||||
| 
 | ||||
| 	log(...args) { | ||||
| 		this[LOG_SYMBOL](LogType.log, args); | ||||
| 	} | ||||
| 
 | ||||
| 	debug(...args) { | ||||
| 		this[LOG_SYMBOL](LogType.debug, args); | ||||
| 	} | ||||
| 
 | ||||
| 	assert(assertion, ...args) { | ||||
| 		if (!assertion) { | ||||
| 			this[LOG_SYMBOL](LogType.error, args); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	trace() { | ||||
| 		this[LOG_SYMBOL](LogType.trace, ["Trace"]); | ||||
| 	} | ||||
| 
 | ||||
| 	clear() { | ||||
| 		this[LOG_SYMBOL](LogType.clear); | ||||
| 	} | ||||
| 
 | ||||
| 	group(...args) { | ||||
| 		this[LOG_SYMBOL](LogType.group, args); | ||||
| 	} | ||||
| 
 | ||||
| 	groupCollapsed(...args) { | ||||
| 		this[LOG_SYMBOL](LogType.groupCollapsed, args); | ||||
| 	} | ||||
| 
 | ||||
| 	groupEnd(...args) { | ||||
| 		this[LOG_SYMBOL](LogType.groupEnd, args); | ||||
| 	} | ||||
| 
 | ||||
| 	profile(label) { | ||||
| 		this[LOG_SYMBOL](LogType.profile, [label]); | ||||
| 	} | ||||
| 
 | ||||
| 	profileEnd(label) { | ||||
| 		this[LOG_SYMBOL](LogType.profileEnd, [label]); | ||||
| 	} | ||||
| 
 | ||||
| 	time(label) { | ||||
| 		this[TIMERS_SYMBOL] = this[TIMERS_SYMBOL] || new Map(); | ||||
| 		this[TIMERS_SYMBOL].set(label, process.hrtime()); | ||||
| 	} | ||||
| 
 | ||||
| 	timeLog(label) { | ||||
| 		const prev = this[TIMERS_SYMBOL] && this[TIMERS_SYMBOL].get(label); | ||||
| 		if (!prev) { | ||||
| 			throw new Error(`No such label '${label}' for WebpackLogger.timeLog()`); | ||||
| 		} | ||||
| 		const time = process.hrtime(prev); | ||||
| 		this[LOG_SYMBOL](LogType.time, [label, ...time]); | ||||
| 	} | ||||
| 
 | ||||
| 	timeEnd(label) { | ||||
| 		const prev = this[TIMERS_SYMBOL] && this[TIMERS_SYMBOL].get(label); | ||||
| 		if (!prev) { | ||||
| 			throw new Error(`No such label '${label}' for WebpackLogger.timeEnd()`); | ||||
| 		} | ||||
| 		const time = process.hrtime(prev); | ||||
| 		this[TIMERS_SYMBOL].delete(label); | ||||
| 		this[LOG_SYMBOL](LogType.time, [label, ...time]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| exports.Logger = WebpackLogger; | ||||
|  | @ -0,0 +1,188 @@ | |||
| /* | ||||
| 	MIT License http://www.opensource.org/licenses/mit-license.php
 | ||||
| 	Author Tobias Koppers @sokra | ||||
| */ | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| const { LogType } = require("./Logger"); | ||||
| 
 | ||||
| /** @typedef {import("../../declarations/WebpackOptions").FilterItemTypes} FilterItemTypes */ | ||||
| /** @typedef {import("../../declarations/WebpackOptions").FilterTypes} FilterTypes */ | ||||
| /** @typedef {import("./Logger").LogTypeEnum} LogTypeEnum */ | ||||
| 
 | ||||
| /** @typedef {function(string): boolean} FilterFunction */ | ||||
| 
 | ||||
| /** | ||||
|  * @typedef {Object} LoggerOptions | ||||
|  * @property {false|true|"none"|"error"|"warn"|"info"|"log"|"verbose"} options.level loglevel | ||||
|  * @property {FilterTypes|boolean} options.debug filter for debug logging | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * @param {FilterItemTypes} item an input item | ||||
|  * @returns {FilterFunction} filter funtion | ||||
|  */ | ||||
| const filterToFunction = item => { | ||||
| 	if (typeof item === "string") { | ||||
| 		const regExp = new RegExp( | ||||
| 			`[\\\\/]${item.replace( | ||||
| 				// eslint-disable-next-line no-useless-escape
 | ||||
| 				/[-[\]{}()*+?.\\^$|]/g, | ||||
| 				"\\$&" | ||||
| 			)}([\\\\/]|$|!|\\?)` | ||||
| 		); | ||||
| 		return ident => regExp.test(ident); | ||||
| 	} | ||||
| 	if (item && typeof item === "object" && typeof item.test === "function") { | ||||
| 		return ident => item.test(ident); | ||||
| 	} | ||||
| 	if (typeof item === "function") { | ||||
| 		return item; | ||||
| 	} | ||||
| 	if (typeof item === "boolean") { | ||||
| 		return () => item; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * @enum {number} */ | ||||
| const LogLevel = { | ||||
| 	none: 6, | ||||
| 	false: 6, | ||||
| 	error: 5, | ||||
| 	warn: 4, | ||||
| 	info: 3, | ||||
| 	log: 2, | ||||
| 	true: 2, | ||||
| 	verbose: 1 | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * @param {LoggerOptions} options options object | ||||
|  * @returns {function(string, LogTypeEnum, any[]): void} logging function | ||||
|  */ | ||||
| module.exports = ({ level = "info", debug = false }) => { | ||||
| 	const debugFilters = | ||||
| 		typeof debug === "boolean" | ||||
| 			? [() => debug] | ||||
| 			: /** @type {FilterItemTypes[]} */ ([]) | ||||
| 					.concat(debug) | ||||
| 					.map(filterToFunction); | ||||
| 	/** @type {number} */ | ||||
| 	const loglevel = LogLevel[`${level}`] || 0; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {string} name name of the logger | ||||
| 	 * @param {LogTypeEnum} type type of the log entry | ||||
| 	 * @param {any[]} args arguments of the log entry | ||||
| 	 * @returns {void} | ||||
| 	 */ | ||||
| 	const logger = (name, type, args) => { | ||||
| 		const labeledArgs = (prefix = "") => { | ||||
| 			if (Array.isArray(args)) { | ||||
| 				if (args.length > 0 && typeof args[0] === "string") { | ||||
| 					return [`${prefix}[${name}] ${args[0]}`, ...args.slice(1)]; | ||||
| 				} else { | ||||
| 					return [`${prefix}[${name}]`, ...args]; | ||||
| 				} | ||||
| 			} else { | ||||
| 				return []; | ||||
| 			} | ||||
| 		}; | ||||
| 		const debug = debugFilters.some(f => f(name)); | ||||
| 		switch (type) { | ||||
| 			case LogType.debug: | ||||
| 				if (!debug) return; | ||||
| 				// eslint-disable-next-line node/no-unsupported-features/node-builtins
 | ||||
| 				if (typeof console.debug === "function") { | ||||
| 					// eslint-disable-next-line node/no-unsupported-features/node-builtins
 | ||||
| 					console.debug(...labeledArgs()); | ||||
| 				} else { | ||||
| 					console.log(...labeledArgs()); | ||||
| 				} | ||||
| 				break; | ||||
| 			case LogType.log: | ||||
| 				if (!debug && loglevel > LogLevel.log) return; | ||||
| 				console.log(...labeledArgs()); | ||||
| 				break; | ||||
| 			case LogType.info: | ||||
| 				if (!debug && loglevel > LogLevel.info) return; | ||||
| 				console.info(...labeledArgs("<i> ")); | ||||
| 				break; | ||||
| 			case LogType.warn: | ||||
| 				if (!debug && loglevel > LogLevel.warn) return; | ||||
| 				console.warn(...labeledArgs("<w> ")); | ||||
| 				break; | ||||
| 			case LogType.error: | ||||
| 				if (!debug && loglevel > LogLevel.error) return; | ||||
| 				console.error(...labeledArgs("<e> ")); | ||||
| 				break; | ||||
| 			case LogType.trace: | ||||
| 				if (!debug) return; | ||||
| 				console.trace(); | ||||
| 				break; | ||||
| 			case LogType.group: | ||||
| 				if (!debug && loglevel > LogLevel.log) return; | ||||
| 				// eslint-disable-next-line node/no-unsupported-features/node-builtins
 | ||||
| 				if (typeof console.group === "function") { | ||||
| 					// eslint-disable-next-line node/no-unsupported-features/node-builtins
 | ||||
| 					console.group(...labeledArgs()); | ||||
| 				} else { | ||||
| 					console.log(...labeledArgs()); | ||||
| 				} | ||||
| 				break; | ||||
| 			case LogType.groupCollapsed: | ||||
| 				if (!debug && loglevel > LogLevel.log) return; | ||||
| 				// eslint-disable-next-line node/no-unsupported-features/node-builtins
 | ||||
| 				if (typeof console.groupCollapsed === "function") { | ||||
| 					// eslint-disable-next-line node/no-unsupported-features/node-builtins
 | ||||
| 					console.groupCollapsed(...labeledArgs()); | ||||
| 				} else { | ||||
| 					console.log(...labeledArgs("<g> ")); | ||||
| 				} | ||||
| 				break; | ||||
| 			case LogType.groupEnd: | ||||
| 				if (!debug && loglevel > LogLevel.log) return; | ||||
| 				// eslint-disable-next-line node/no-unsupported-features/node-builtins
 | ||||
| 				if (typeof console.groupEnd === "function") { | ||||
| 					// eslint-disable-next-line node/no-unsupported-features/node-builtins
 | ||||
| 					console.groupEnd(); | ||||
| 				} else { | ||||
| 					console.log(...labeledArgs("</g> ")); | ||||
| 				} | ||||
| 				break; | ||||
| 			case LogType.time: | ||||
| 				if (!debug && loglevel > LogLevel.log) return; | ||||
| 				console.log( | ||||
| 					`[${name}] ${args[0]}: ${args[1] * 1000 + args[2] / 1000000}ms` | ||||
| 				); | ||||
| 				break; | ||||
| 			case 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(...labeledArgs()); | ||||
| 				} | ||||
| 				break; | ||||
| 			case 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(...labeledArgs()); | ||||
| 				} | ||||
| 				break; | ||||
| 			case LogType.clear: | ||||
| 				if (!debug && loglevel > LogLevel.log) return; | ||||
| 				// eslint-disable-next-line node/no-unsupported-features/node-builtins
 | ||||
| 				if (typeof console.clear === "function") { | ||||
| 					// eslint-disable-next-line node/no-unsupported-features/node-builtins
 | ||||
| 					console.clear(); | ||||
| 				} | ||||
| 				break; | ||||
| 			default: | ||||
| 				throw new Error(`Unexpected LogType ${type}`); | ||||
| 		} | ||||
| 	}; | ||||
| 	return logger; | ||||
| }; | ||||
|  | @ -0,0 +1,42 @@ | |||
| /* | ||||
| 	MIT License http://www.opensource.org/licenses/mit-license.php
 | ||||
| 	Author Tobias Koppers @sokra | ||||
| */ | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| const SyncBailHook = require("tapable/lib/SyncBailHook"); | ||||
| const { Logger } = require("./Logger"); | ||||
| const createConsoleLogger = require("./createConsoleLogger"); | ||||
| 
 | ||||
| /** @type {createConsoleLogger.LoggerOptions} */ | ||||
| let currentDefaultLoggerOptions = { | ||||
| 	level: "info", | ||||
| 	debug: false | ||||
| }; | ||||
| let currentDefaultLogger = createConsoleLogger(currentDefaultLoggerOptions); | ||||
| 
 | ||||
| /** | ||||
|  * @param {string} name name of the logger | ||||
|  * @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); | ||||
| 		} | ||||
| 	}); | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * @param {createConsoleLogger.LoggerOptions} options new options, merge with old options | ||||
|  * @returns {void} | ||||
|  */ | ||||
| exports.configureDefaultLogger = options => { | ||||
| 	Object.assign(currentDefaultLoggerOptions, options); | ||||
| 	currentDefaultLogger = createConsoleLogger(currentDefaultLoggerOptions); | ||||
| }; | ||||
| 
 | ||||
| exports.hooks = { | ||||
| 	log: new SyncBailHook(["origin", "type", "args"]) | ||||
| }; | ||||
|  | @ -7,16 +7,30 @@ | |||
| 
 | ||||
| const CachedInputFileSystem = require("enhanced-resolve/lib/CachedInputFileSystem"); | ||||
| const fs = require("graceful-fs"); | ||||
| const createConsoleLogger = require("../logging/createConsoleLogger"); | ||||
| const NodeWatchFileSystem = require("./NodeWatchFileSystem"); | ||||
| 
 | ||||
| /** @typedef {import("../Compiler")} Compiler */ | ||||
| 
 | ||||
| class NodeEnvironmentPlugin { | ||||
| 	constructor(options) { | ||||
| 		this.options = options || {}; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Compiler} compiler the compiler instance | ||||
| 	 * @returns {void} | ||||
| 	 */ | ||||
| 	apply(compiler) { | ||||
| 		compiler.infrastructureLogger = createConsoleLogger( | ||||
| 			Object.assign( | ||||
| 				{ | ||||
| 					level: "info", | ||||
| 					debug: false | ||||
| 				}, | ||||
| 				this.options.infrastructureLogging | ||||
| 			) | ||||
| 		); | ||||
| 		compiler.inputFileSystem = new CachedInputFileSystem(fs, 60000); | ||||
| 		const inputFileSystem = compiler.inputFileSystem; | ||||
| 		compiler.outputFileSystem = fs; | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| "use strict"; | ||||
| 
 | ||||
| const formatLocation = require("../formatLocation"); | ||||
| const { LogType } = require("../logging/Logger"); | ||||
| const AggressiveSplittingPlugin = require("../optimize/AggressiveSplittingPlugin"); | ||||
| const ConcatenatedModule = require("../optimize/ConcatenatedModule"); | ||||
| const SizeLimitsPlugin = require("../performance/SizeLimitsPlugin"); | ||||
|  | @ -19,6 +20,7 @@ const { | |||
| 	compareModulesById, | ||||
| 	compareModulesByIdOrIdentifier | ||||
| } = require("../util/comparators"); | ||||
| const identifierUtils = require("../util/identifier"); | ||||
| 
 | ||||
| /** @typedef {import("webpack-sources").Source} Source */ | ||||
| /** @typedef {import("../Chunk")} Chunk */ | ||||
|  | @ -46,6 +48,7 @@ const { | |||
| 
 | ||||
| /** | ||||
|  * @typedef {Object} UsualOptions | ||||
|  * @property {string} context | ||||
|  * @property {RequestShortener} requestShortener | ||||
|  * @property {string} chunksSort | ||||
|  * @property {string} modulesSort | ||||
|  | @ -54,6 +57,9 @@ const { | |||
|  * @property {Function[]} excludeModules | ||||
|  * @property {Function[]} warningsFilter | ||||
|  * @property {number} maxModules | ||||
|  * @property {false|"none"|"error"|"warn"|"info"|"log"|"verbose"} logging | ||||
|  * @property {Function[]} loggingDebug | ||||
|  * @property {boolean} loggingTrace | ||||
|  * @property {any} _env | ||||
|  */ | ||||
| 
 | ||||
|  | @ -280,6 +286,128 @@ const SIMPLE_EXTRACTORS = { | |||
| 				context | ||||
| 			); | ||||
| 		}, | ||||
| 		logging: (object, compilation, _context, options, factory) => { | ||||
| 			const util = require("util"); | ||||
| 			const { loggingDebug, loggingTrace, context } = options; | ||||
| 			object.logging = {}; | ||||
| 			let acceptedTypes; | ||||
| 			let collapsedGroups = false; | ||||
| 			switch (options.logging) { | ||||
| 				case "none": | ||||
| 					acceptedTypes = new Set([]); | ||||
| 					break; | ||||
| 				case "error": | ||||
| 					acceptedTypes = new Set([LogType.error]); | ||||
| 					break; | ||||
| 				case "warn": | ||||
| 					acceptedTypes = new Set([LogType.error, LogType.warn]); | ||||
| 					break; | ||||
| 				case "info": | ||||
| 					acceptedTypes = new Set([LogType.error, LogType.warn, LogType.info]); | ||||
| 					break; | ||||
| 				case "log": | ||||
| 					acceptedTypes = new Set([ | ||||
| 						LogType.error, | ||||
| 						LogType.warn, | ||||
| 						LogType.info, | ||||
| 						LogType.log, | ||||
| 						LogType.group, | ||||
| 						LogType.groupEnd, | ||||
| 						LogType.groupCollapsed, | ||||
| 						LogType.clear | ||||
| 					]); | ||||
| 					break; | ||||
| 				case "verbose": | ||||
| 					acceptedTypes = new Set([ | ||||
| 						LogType.error, | ||||
| 						LogType.warn, | ||||
| 						LogType.info, | ||||
| 						LogType.log, | ||||
| 						LogType.group, | ||||
| 						LogType.groupEnd, | ||||
| 						LogType.groupCollapsed, | ||||
| 						LogType.profile, | ||||
| 						LogType.profileEnd, | ||||
| 						LogType.time, | ||||
| 						LogType.clear | ||||
| 					]); | ||||
| 					collapsedGroups = true; | ||||
| 					break; | ||||
| 			} | ||||
| 			let depthInCollapsedGroup = 0; | ||||
| 			for (const [origin, logEntries] of compilation.logging) { | ||||
| 				const debugMode = loggingDebug.some(fn => fn(origin)); | ||||
| 				const groupStack = []; | ||||
| 				const rootList = []; | ||||
| 				let currentList = rootList; | ||||
| 				let processedLogEntries = 0; | ||||
| 				for (const entry of logEntries) { | ||||
| 					let type = entry.type; | ||||
| 					if (!debugMode && !acceptedTypes.has(type)) continue; | ||||
| 
 | ||||
| 					// Expand groups in verbose and debug modes
 | ||||
| 					if (type === LogType.groupCollapsed && (debugMode || collapsedGroups)) | ||||
| 						type = LogType.group; | ||||
| 
 | ||||
| 					if (depthInCollapsedGroup === 0) { | ||||
| 						processedLogEntries++; | ||||
| 					} | ||||
| 
 | ||||
| 					if (type === LogType.groupEnd) { | ||||
| 						groupStack.pop(); | ||||
| 						if (groupStack.length > 0) { | ||||
| 							currentList = groupStack[groupStack.length - 1].children; | ||||
| 						} else { | ||||
| 							currentList = rootList; | ||||
| 						} | ||||
| 						if (depthInCollapsedGroup > 0) depthInCollapsedGroup--; | ||||
| 						continue; | ||||
| 					} | ||||
| 					let message = undefined; | ||||
| 					if (entry.type === LogType.time) { | ||||
| 						message = `${entry.args[0]}: ${entry.args[1] * 1000 + | ||||
| 							entry.args[2] / 1000000}ms`;
 | ||||
| 					} else if (entry.args && entry.args.length > 0) { | ||||
| 						message = util.format(entry.args[0], ...entry.args.slice(1)); | ||||
| 					} | ||||
| 					const newEntry = { | ||||
| 						...entry, | ||||
| 						type, | ||||
| 						message, | ||||
| 						trace: loggingTrace ? entry.trace : undefined, | ||||
| 						children: | ||||
| 							type === LogType.group || type === LogType.groupCollapsed | ||||
| 								? [] | ||||
| 								: undefined | ||||
| 					}; | ||||
| 					currentList.push(newEntry); | ||||
| 					if (newEntry.children) { | ||||
| 						groupStack.push(newEntry); | ||||
| 						currentList = newEntry.children; | ||||
| 						if (depthInCollapsedGroup > 0) { | ||||
| 							depthInCollapsedGroup++; | ||||
| 						} else if (type === LogType.groupCollapsed) { | ||||
| 							depthInCollapsedGroup = 1; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				let name = identifierUtils | ||||
| 					.makePathsRelative(context, origin, compilation.cache) | ||||
| 					.replace(/\|/g, " "); | ||||
| 				if (name in object.logging) { | ||||
| 					let i = 1; | ||||
| 					while (`${name}#${i}` in object.logging) { | ||||
| 						i++; | ||||
| 					} | ||||
| 					name = `${name}#${i}`; | ||||
| 				} | ||||
| 				object.logging[name] = { | ||||
| 					entries: rootList, | ||||
| 					filteredEntries: logEntries.length - processedLogEntries, | ||||
| 					debug: debugMode | ||||
| 				}; | ||||
| 			} | ||||
| 		}, | ||||
| 		children: (object, compilation, context, options, factory) => { | ||||
| 			const { type } = context; | ||||
| 			object.children = factory.create( | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ const NAMED_PRESETS = { | |||
| 		optimizationBailout: true, | ||||
| 		errorDetails: true, | ||||
| 		publicPath: true, | ||||
| 		logging: "verbose", | ||||
| 		orphanModules: true, | ||||
| 		runtime: true, | ||||
| 		exclude: false, | ||||
|  | @ -55,6 +56,7 @@ const NAMED_PRESETS = { | |||
| 		optimizationBailout: true, | ||||
| 		errorDetails: true, | ||||
| 		publicPath: true, | ||||
| 		logging: true, | ||||
| 		runtimeModules: true, | ||||
| 		runtime: true, | ||||
| 		exclude: false, | ||||
|  | @ -65,17 +67,20 @@ const NAMED_PRESETS = { | |||
| 		modules: true, | ||||
| 		maxModules: 0, | ||||
| 		errors: true, | ||||
| 		warnings: true | ||||
| 		warnings: true, | ||||
| 		logging: "warn" | ||||
| 	}, | ||||
| 	"errors-only": { | ||||
| 		all: false, | ||||
| 		errors: true, | ||||
| 		moduleTrace: true | ||||
| 		moduleTrace: true, | ||||
| 		logging: "error" | ||||
| 	}, | ||||
| 	"errors-warnings": { | ||||
| 		all: false, | ||||
| 		errors: true, | ||||
| 		warnings: true | ||||
| 		warnings: true, | ||||
| 		logging: "warn" | ||||
| 	}, | ||||
| 	none: { | ||||
| 		all: false | ||||
|  | @ -132,6 +137,10 @@ const DEFAULTS = { | |||
| 	errorDetails: OFF_FOR_TO_STRING, | ||||
| 	warnings: NORMAL_ON, | ||||
| 	publicPath: OFF_FOR_TO_STRING, | ||||
| 	logging: ({ all }, { forToString }) => | ||||
| 		(forToString && all !== false ? "info" : false), | ||||
| 	loggingDebug: () => [], | ||||
| 	loggingTrace: OFF_FOR_TO_STRING, | ||||
| 	excludeModules: () => [], | ||||
| 	excludeAssets: () => [], | ||||
| 	maxModules: (o, { forToString }) => ((forToString ? 15 : Infinity)), | ||||
|  | @ -142,7 +151,7 @@ const DEFAULTS = { | |||
| 	colors: () => false | ||||
| }; | ||||
| 
 | ||||
| const normalizeExclude = item => { | ||||
| const normalizeFilter = item => { | ||||
| 	if (typeof item === "string") { | ||||
| 		const regExp = new RegExp( | ||||
| 			`[\\\\/]${item.replace( | ||||
|  | @ -169,13 +178,13 @@ const NORMALIZER = { | |||
| 		if (!Array.isArray(value)) { | ||||
| 			value = value ? [value] : []; | ||||
| 		} | ||||
| 		return value.map(normalizeExclude); | ||||
| 		return value.map(normalizeFilter); | ||||
| 	}, | ||||
| 	excludeAssets: value => { | ||||
| 		if (!Array.isArray(value)) { | ||||
| 			value = value ? [value] : []; | ||||
| 		} | ||||
| 		return value.map(normalizeExclude); | ||||
| 		return value.map(normalizeFilter); | ||||
| 	}, | ||||
| 	warningsFilter: value => { | ||||
| 		if (!Array.isArray(value)) { | ||||
|  | @ -195,6 +204,16 @@ const NORMALIZER = { | |||
| 				`Can only filter warnings with Strings or RegExps. (Given: ${filter})` | ||||
| 			); | ||||
| 		}); | ||||
| 	}, | ||||
| 	logging: value => { | ||||
| 		if (value === true) value = "log"; | ||||
| 		return value; | ||||
| 	}, | ||||
| 	loggingDebug: value => { | ||||
| 		if (!Array.isArray(value)) { | ||||
| 			value = value ? [value] : []; | ||||
| 		} | ||||
| 		return value.map(normalizeFilter); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -43,6 +43,12 @@ const printSizes = (sizes, { formatSize }) => { | |||
| 	} | ||||
| }; | ||||
| 
 | ||||
| const mapLines = (str, fn) => | ||||
| 	str | ||||
| 		.split("\n") | ||||
| 		.map(fn) | ||||
| 		.join("\n"); | ||||
| 
 | ||||
| /** | ||||
|  * @param {number} n a number | ||||
|  * @returns {string} number as two digit string, leading 0 | ||||
|  | @ -130,6 +136,14 @@ const SIMPLE_PRINTERS = { | |||
| 						: filteredAssets | ||||
| 			  } ${plural(filteredAssets, "asset", "assets")}` | ||||
| 			: undefined, | ||||
| 	"compilation.logging": (logging, context, printer) => | ||||
| 		Array.isArray(logging) | ||||
| 			? undefined | ||||
| 			: printer.print( | ||||
| 					context.type, | ||||
| 					Object.entries(logging).map(([name, value]) => ({ ...value, name })), | ||||
| 					context | ||||
| 			  ), | ||||
| 	"compilation.children[].compilation.name": name => | ||||
| 		name ? `Child ${name}:` : "Child", | ||||
| 
 | ||||
|  | @ -402,12 +416,45 @@ const SIMPLE_PRINTERS = { | |||
| 	"error.moduleTrace": moduleTrace => undefined, | ||||
| 	"error.separator!": () => "\n", | ||||
| 
 | ||||
| 	"loggingEntry(error).loggingEntry.message": (message, { red }) => | ||||
| 		mapLines(message, x => `<e> ${red(x)}`), | ||||
| 	"loggingEntry(warn).loggingEntry.message": (message, { yellow }) => | ||||
| 		mapLines(message, x => `<w> ${yellow(x)}`), | ||||
| 	"loggingEntry(info).loggingEntry.message": (message, { green }) => | ||||
| 		mapLines(message, x => `<i> ${green(x)}`), | ||||
| 	"loggingEntry(log).loggingEntry.message": (message, { bold }) => | ||||
| 		mapLines(message, x => bold(x)), | ||||
| 	"loggingEntry(debug).loggingEntry.message": message => message, | ||||
| 	"loggingEntry(trace).loggingEntry.message": message => message, | ||||
| 	"loggingEntry(profile).loggingEntry.message": (message, { magenta }) => | ||||
| 		mapLines(message, x => `<p> ${magenta(x)}`), | ||||
| 	"loggingEntry(profileEnd).loggingEntry.message": (message, { magenta }) => | ||||
| 		mapLines(message, x => `</p> ${magenta(x)}`), | ||||
| 	"loggingEntry(time).loggingEntry.message": (message, { magenta }) => | ||||
| 		mapLines(message, x => `<t> ${magenta(x)}`), | ||||
| 	"loggingEntry(group).loggingEntry.message": (message, { cyan }) => | ||||
| 		mapLines(message, x => cyan(x)), | ||||
| 	"loggingEntry(groupCollapsed).loggingEntry.message": (message, { cyan }) => | ||||
| 		mapLines(message, x => `<+> ${cyan(x)}`), | ||||
| 	"loggingEntry(clear).loggingEntry": () => "-------", | ||||
| 	"loggingEntry(groupCollapsed).loggingEntry.children": () => "", | ||||
| 	"loggingEntry.trace[]": trace => | ||||
| 		trace ? mapLines(trace, x => `| ${x}`) : undefined, | ||||
| 
 | ||||
| 	"moduleTraceItem.originName": originName => originName, | ||||
| 
 | ||||
| 	loggingGroup: loggingGroup => | ||||
| 		loggingGroup.entries.length === 0 ? "" : undefined, | ||||
| 	"loggingGroup.debug": (flag, { red }) => ((flag ? red("DEBUG") : undefined)), | ||||
| 	"loggingGroup.name": (name, { bold }) => bold(`LOG from ${name}`), | ||||
| 	"loggingGroup.separator!": () => "\n", | ||||
| 	"loggingGroup.filteredEntries": filteredEntries => | ||||
| 		filteredEntries > 0 ? `+ ${filteredEntries} hidden lines` : undefined, | ||||
| 
 | ||||
| 	"moduleTraceDependency.loc": loc => loc | ||||
| }; | ||||
| 
 | ||||
| /** @type {Record<string, string>} */ | ||||
| /** @type {Record<string, string | Function>} */ | ||||
| const ITEM_NAMES = { | ||||
| 	"compilation.assets[]": "asset", | ||||
| 	"compilation.modules[]": "module", | ||||
|  | @ -416,6 +463,7 @@ const ITEM_NAMES = { | |||
| 	"compilation.namedChunkGroups[]": "chunkGroup", | ||||
| 	"compilation.errors[]": "error", | ||||
| 	"compilation.warnings[]": "error", | ||||
| 	"compilation.logging[]": "loggingGroup", | ||||
| 	"compilation.children[]": "compilation", | ||||
| 	"asset.chunks[]": "assetChunk", | ||||
| 	"asset.auxiliaryChunks[]": "assetChunk", | ||||
|  | @ -427,6 +475,10 @@ const ITEM_NAMES = { | |||
| 	"chunk.origins[]": "chunkOrigin", | ||||
| 	"chunk.rootModules[]": "module", | ||||
| 	"chunk.modules[]": "module", | ||||
| 	"loggingGroup.entries[]": logEntry => | ||||
| 		`loggingEntry(${logEntry.type}).loggingEntry`, | ||||
| 	"loggingEntry.children[]": logEntry => | ||||
| 		`loggingEntry(${logEntry.type}).loggingEntry`, | ||||
| 	"error.moduleTrace[]": "moduleTraceItem", | ||||
| 	"moduleTraceItem.dependencies[]": "moduleTraceDependency" | ||||
| }; | ||||
|  | @ -467,6 +519,7 @@ const PREFERED_ORDERS = { | |||
| 		"chunks", | ||||
| 		"modules", | ||||
| 		"filteredModules", | ||||
| 		"logging", | ||||
| 		"warnings", | ||||
| 		"errors", | ||||
| 		"children", | ||||
|  | @ -572,6 +625,15 @@ const PREFERED_ORDERS = { | |||
| 	error: ERROR_PREFERED_ORDER, | ||||
| 	warning: ERROR_PREFERED_ORDER, | ||||
| 	"chunk.childrenByOrder[]": ["type", "children"], | ||||
| 	loggingGroup: [ | ||||
| 		"debug", | ||||
| 		"name", | ||||
| 		"separator!", | ||||
| 		"entries", | ||||
| 		"separator!", | ||||
| 		"filtredEntries" | ||||
| 	], | ||||
| 	loggingEntry: ["message", "trace", "children"], | ||||
| 	"chunkGroup.childAssets[]": ["type", "children"] | ||||
| }; | ||||
| 
 | ||||
|  | @ -608,7 +670,10 @@ const SIMPLE_ITEMS_JOINER = { | |||
| 			.join(" "), | ||||
| 	"compilation.errors": itemsJoinMoreSpacing, | ||||
| 	"compilation.warnings": itemsJoinMoreSpacing, | ||||
| 	"compilation.logging": itemsJoinMoreSpacing, | ||||
| 	"moduleTraceItem.dependencies": itemsJoinOneLine, | ||||
| 	"loggingEntry.children": items => | ||||
| 		indent(items.filter(Boolean).join("\n"), "  ", false), | ||||
| 	"compilation.children": items => | ||||
| 		items.map(item => indent(item, "    ", true)).join("\n") | ||||
| }; | ||||
|  | @ -701,7 +766,9 @@ const SIMPLE_ELEMENT_JOINERS = { | |||
| 		for (const item of items) { | ||||
| 			if (!item.content) continue; | ||||
| 			const needMoreSpace = | ||||
| 				item.element === "warnings" || item.element === "errors"; | ||||
| 				item.element === "warnings" || | ||||
| 				item.element === "errors" || | ||||
| 				item.element === "logging"; | ||||
| 			if (result.length !== 0) { | ||||
| 				result.push(needMoreSpace || lastNeedMore ? "\n\n" : "\n"); | ||||
| 			} | ||||
|  | @ -797,6 +864,7 @@ const SIMPLE_ELEMENT_JOINERS = { | |||
| 	chunkOrigin: items => "   > " + joinOneLine(items), | ||||
| 	"errors[].error": joinError(true), | ||||
| 	"warnings[].error": joinError(false), | ||||
| 	loggingGroup: items => joinExplicitNewLine(items, "").trimRight(), | ||||
| 	moduleTraceItem: items => " @ " + joinOneLine(items), | ||||
| 	moduleTraceDependency: joinOneLine | ||||
| }; | ||||
|  | @ -973,7 +1041,10 @@ class DefaultStatsPrinterPlugin { | |||
| 						const itemName = ITEM_NAMES[key]; | ||||
| 						stats.hooks.getItemName | ||||
| 							.for(key) | ||||
| 							.tap("DefaultStatsPrinterPlugin", () => itemName); | ||||
| 							.tap( | ||||
| 								"DefaultStatsPrinterPlugin", | ||||
| 								typeof itemName === "string" ? () => itemName : itemName | ||||
| 							); | ||||
| 					} | ||||
| 
 | ||||
| 					for (const key of Object.keys(SIMPLE_ITEMS_JOINER)) { | ||||
|  |  | |||
|  | @ -52,7 +52,9 @@ const createCompiler = options => { | |||
| 	options = new WebpackOptionsDefaulter().process(options); | ||||
| 	const compiler = new Compiler(options.context); | ||||
| 	compiler.options = options; | ||||
| 	new NodeEnvironmentPlugin().apply(compiler); | ||||
| 	new NodeEnvironmentPlugin({ | ||||
| 		infrastructureLogging: options.infrastructureLogging | ||||
| 	}).apply(compiler); | ||||
| 	if (Array.isArray(options.plugins)) { | ||||
| 		for (const plugin of options.plugins) { | ||||
| 			if (typeof plugin === "function") { | ||||
|  |  | |||
|  | @ -252,7 +252,7 @@ | |||
|         }, | ||||
|         { | ||||
|           "instanceof": "Function", | ||||
|           "tsType": "Function" | ||||
|           "tsType": "((value: string) => boolean)" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|  | @ -2006,6 +2006,35 @@ | |||
|           "description": "add the hash of the compilation", | ||||
|           "type": "boolean" | ||||
|         }, | ||||
|         "logging": { | ||||
|           "description": "add logging output", | ||||
|           "anyOf": [ | ||||
|             { | ||||
|               "description": "enable/disable logging output (true: shows normal logging output, loglevel: log)", | ||||
|               "type": "boolean" | ||||
|             }, | ||||
|             { | ||||
|               "description": "specify log level of logging output", | ||||
|               "enum": ["none", "error", "warn", "info", "log", "verbose"] | ||||
|             } | ||||
|           ] | ||||
|         }, | ||||
|         "loggingDebug": { | ||||
|           "description": "Include debug logging of specified loggers (i. e. for plugins or loaders). Filters can be Strings, RegExps or Functions", | ||||
|           "anyOf": [ | ||||
|             { | ||||
|               "$ref": "#/definitions/FilterTypes" | ||||
|             }, | ||||
|             { | ||||
|               "description": "Enable/Disable debug logging for all loggers", | ||||
|               "type": "boolean" | ||||
|             } | ||||
|           ] | ||||
|         }, | ||||
|         "loggingTrace": { | ||||
|           "description": "add stack traces to logging output", | ||||
|           "type": "boolean" | ||||
|         }, | ||||
|         "maxModules": { | ||||
|           "description": "Set the maximum number of modules to be shown", | ||||
|           "type": "number" | ||||
|  | @ -2263,6 +2292,29 @@ | |||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     "infrastructureLogging": { | ||||
|       "description": "Options for infrastructure level logging", | ||||
|       "type": "object", | ||||
|       "additionalProperties": false, | ||||
|       "properties": { | ||||
|         "debug": { | ||||
|           "description": "Enable debug logging for specific loggers", | ||||
|           "anyOf": [ | ||||
|             { | ||||
|               "$ref": "#/definitions/FilterTypes" | ||||
|             }, | ||||
|             { | ||||
|               "description": "Enable/Disable debug logging for all loggers", | ||||
|               "type": "boolean" | ||||
|             } | ||||
|           ] | ||||
|         }, | ||||
|         "level": { | ||||
|           "description": "Log level", | ||||
|           "enum": ["none", "error", "warn", "info", "log", "verbose"] | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "loader": { | ||||
|       "description": "Custom values available in the loader context.", | ||||
|       "type": "object" | ||||
|  |  | |||
|  | @ -709,4 +709,152 @@ describe("Compiler", () => { | |||
| 			done(); | ||||
| 		}); | ||||
| 	}); | ||||
| 	describe("infrastructure logging", () => { | ||||
| 		const CONSOLE_METHODS = [ | ||||
| 			"error", | ||||
| 			"warn", | ||||
| 			"info", | ||||
| 			"log", | ||||
| 			"debug", | ||||
| 			"trace", | ||||
| 			"profile", | ||||
| 			"profileEnd", | ||||
| 			"group", | ||||
| 			"groupEnd", | ||||
| 			"groupCollapsed" | ||||
| 		]; | ||||
| 		const spies = {}; | ||||
| 		beforeEach(() => { | ||||
| 			for (const method of CONSOLE_METHODS) { | ||||
| 				if (console[method]) { | ||||
| 					spies[method] = jest.spyOn(console, method).mockImplementation(); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 		afterEach(() => { | ||||
| 			for (const method in spies) { | ||||
| 				spies[method].mockRestore(); | ||||
| 				delete spies[method]; | ||||
| 			} | ||||
| 		}); | ||||
| 		class MyPlugin { | ||||
| 			apply(compiler) { | ||||
| 				const logger = compiler.getInfrastructureLogger("MyPlugin"); | ||||
| 				logger.time("Time"); | ||||
| 				logger.group("Group"); | ||||
| 				logger.error("Error"); | ||||
| 				logger.warn("Warning"); | ||||
| 				logger.info("Info"); | ||||
| 				logger.log("Log"); | ||||
| 				logger.debug("Debug"); | ||||
| 				logger.groupCollapsed("Collaped group"); | ||||
| 				logger.log("Log inside collapsed group"); | ||||
| 				logger.groupEnd(); | ||||
| 				logger.groupEnd(); | ||||
| 				logger.timeEnd("Time"); | ||||
| 			} | ||||
| 		} | ||||
| 		it("should log to the console (verbose)", done => { | ||||
| 			const compiler = webpack({ | ||||
| 				context: path.join(__dirname, "fixtures"), | ||||
| 				entry: "./a", | ||||
| 				output: { | ||||
| 					path: "/", | ||||
| 					filename: "bundle.js" | ||||
| 				}, | ||||
| 				infrastructureLogging: { | ||||
| 					level: "verbose" | ||||
| 				}, | ||||
| 				plugins: [new MyPlugin()] | ||||
| 			}); | ||||
| 			compiler.outputFileSystem = new MemoryFs(); | ||||
| 			compiler.run((err, stats) => { | ||||
| 				expect(spies.group).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.group).toHaveBeenCalledWith("[MyPlugin] Group"); | ||||
| 				expect(spies.groupCollapsed).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.groupCollapsed).toHaveBeenCalledWith( | ||||
| 					"[MyPlugin] Collaped group" | ||||
| 				); | ||||
| 				expect(spies.error).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.error).toHaveBeenCalledWith("<e> [MyPlugin] Error"); | ||||
| 				expect(spies.warn).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.warn).toHaveBeenCalledWith("<w> [MyPlugin] Warning"); | ||||
| 				expect(spies.info).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.info).toHaveBeenCalledWith("<i> [MyPlugin] Info"); | ||||
| 				expect(spies.log).toHaveBeenCalledTimes(3); | ||||
| 				expect(spies.log).toHaveBeenCalledWith("[MyPlugin] Log"); | ||||
| 				expect(spies.log).toHaveBeenCalledWith( | ||||
| 					"[MyPlugin] Log inside collapsed group" | ||||
| 				); | ||||
| 				expect(spies.debug).toHaveBeenCalledTimes(0); | ||||
| 				expect(spies.groupEnd).toHaveBeenCalledTimes(2); | ||||
| 				done(); | ||||
| 			}); | ||||
| 		}); | ||||
| 		it("should log to the console (debug mode)", done => { | ||||
| 			const compiler = webpack({ | ||||
| 				context: path.join(__dirname, "fixtures"), | ||||
| 				entry: "./a", | ||||
| 				output: { | ||||
| 					path: "/", | ||||
| 					filename: "bundle.js" | ||||
| 				}, | ||||
| 				infrastructureLogging: { | ||||
| 					level: "error", | ||||
| 					debug: /MyPlugin/ | ||||
| 				}, | ||||
| 				plugins: [new MyPlugin()] | ||||
| 			}); | ||||
| 			compiler.outputFileSystem = new MemoryFs(); | ||||
| 			compiler.run((err, stats) => { | ||||
| 				expect(spies.group).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.group).toHaveBeenCalledWith("[MyPlugin] Group"); | ||||
| 				expect(spies.groupCollapsed).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.groupCollapsed).toHaveBeenCalledWith( | ||||
| 					"[MyPlugin] Collaped group" | ||||
| 				); | ||||
| 				expect(spies.error).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.error).toHaveBeenCalledWith("<e> [MyPlugin] Error"); | ||||
| 				expect(spies.warn).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.warn).toHaveBeenCalledWith("<w> [MyPlugin] Warning"); | ||||
| 				expect(spies.info).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.info).toHaveBeenCalledWith("<i> [MyPlugin] Info"); | ||||
| 				expect(spies.log).toHaveBeenCalledTimes(3); | ||||
| 				expect(spies.log).toHaveBeenCalledWith("[MyPlugin] Log"); | ||||
| 				expect(spies.log).toHaveBeenCalledWith( | ||||
| 					"[MyPlugin] Log inside collapsed group" | ||||
| 				); | ||||
| 				expect(spies.debug).toHaveBeenCalledTimes(1); | ||||
| 				expect(spies.debug).toHaveBeenCalledWith("[MyPlugin] Debug"); | ||||
| 				expect(spies.groupEnd).toHaveBeenCalledTimes(2); | ||||
| 				done(); | ||||
| 			}); | ||||
| 		}); | ||||
| 		it("should log to the console (none)", done => { | ||||
| 			const compiler = webpack({ | ||||
| 				context: path.join(__dirname, "fixtures"), | ||||
| 				entry: "./a", | ||||
| 				output: { | ||||
| 					path: "/", | ||||
| 					filename: "bundle.js" | ||||
| 				}, | ||||
| 				infrastructureLogging: { | ||||
| 					level: "none" | ||||
| 				}, | ||||
| 				plugins: [new MyPlugin()] | ||||
| 			}); | ||||
| 			compiler.outputFileSystem = new MemoryFs(); | ||||
| 			compiler.run((err, stats) => { | ||||
| 				expect(spies.group).toHaveBeenCalledTimes(0); | ||||
| 				expect(spies.groupCollapsed).toHaveBeenCalledTimes(0); | ||||
| 				expect(spies.error).toHaveBeenCalledTimes(0); | ||||
| 				expect(spies.warn).toHaveBeenCalledTimes(0); | ||||
| 				expect(spies.info).toHaveBeenCalledTimes(0); | ||||
| 				expect(spies.log).toHaveBeenCalledTimes(0); | ||||
| 				expect(spies.debug).toHaveBeenCalledTimes(0); | ||||
| 				expect(spies.groupEnd).toHaveBeenCalledTimes(0); | ||||
| 				done(); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| }); | ||||
|  |  | |||
|  | @ -259,69 +259,63 @@ describe("JavascriptParser", () => { | |||
| 			const state = testCases[name][1]; | ||||
| 
 | ||||
| 			const testParser = new JavascriptParser({}); | ||||
| 			testParser.hooks.canRename.tap( | ||||
| 				"abc", | ||||
| 				"JavascriptParserTest", | ||||
| 				expr => true | ||||
| 			); | ||||
| 			testParser.hooks.canRename.tap( | ||||
| 				"ijk", | ||||
| 				"JavascriptParserTest", | ||||
| 				expr => true | ||||
| 			); | ||||
| 			testParser.hooks.call.tap("abc", "JavascriptParserTest", expr => { | ||||
| 			testParser.hooks.canRename | ||||
| 				.for("abc") | ||||
| 				.tap("JavascriptParserTest", expr => true); | ||||
| 			testParser.hooks.canRename | ||||
| 				.for("ijk") | ||||
| 				.tap("JavascriptParserTest", expr => true); | ||||
| 			testParser.hooks.call.for("abc").tap("JavascriptParserTest", expr => { | ||||
| 				if (!testParser.state.abc) testParser.state.abc = []; | ||||
| 				testParser.state.abc.push(testParser.parseString(expr.arguments[0])); | ||||
| 				return true; | ||||
| 			}); | ||||
| 			testParser.hooks.call.tap("cde.abc", "JavascriptParserTest", expr => { | ||||
| 			testParser.hooks.call.for("cde.abc").tap("JavascriptParserTest", expr => { | ||||
| 				if (!testParser.state.cdeabc) testParser.state.cdeabc = []; | ||||
| 				testParser.state.cdeabc.push(testParser.parseString(expr.arguments[0])); | ||||
| 				return true; | ||||
| 			}); | ||||
| 			testParser.hooks.call.tap("cde.ddd.abc", "JavascriptParserTest", expr => { | ||||
| 				if (!testParser.state.cdedddabc) testParser.state.cdedddabc = []; | ||||
| 				testParser.state.cdedddabc.push( | ||||
| 					testParser.parseString(expr.arguments[0]) | ||||
| 				); | ||||
| 				return true; | ||||
| 			}); | ||||
| 			testParser.hooks.expression.tap("fgh", "JavascriptParserTest", expr => { | ||||
| 				if (!testParser.state.fgh) testParser.state.fgh = []; | ||||
| 				testParser.state.fgh.push( | ||||
| 					Array.from(testParser.scope.definitions.asSet()).join(" ") | ||||
| 				); | ||||
| 				return true; | ||||
| 			}); | ||||
| 			testParser.hooks.expression.tap( | ||||
| 				"fgh.sub", | ||||
| 				"JavascriptParserTest", | ||||
| 				expr => { | ||||
| 			testParser.hooks.call | ||||
| 				.for("cde.ddd.abc") | ||||
| 				.tap("JavascriptParserTest", expr => { | ||||
| 					if (!testParser.state.cdedddabc) testParser.state.cdedddabc = []; | ||||
| 					testParser.state.cdedddabc.push( | ||||
| 						testParser.parseString(expr.arguments[0]) | ||||
| 					); | ||||
| 					return true; | ||||
| 				}); | ||||
| 			testParser.hooks.expression | ||||
| 				.for("fgh") | ||||
| 				.tap("JavascriptParserTest", expr => { | ||||
| 					if (!testParser.state.fgh) testParser.state.fgh = []; | ||||
| 					testParser.state.fgh.push( | ||||
| 						Array.from(testParser.scope.definitions.asSet()).join(" ") | ||||
| 					); | ||||
| 					return true; | ||||
| 				}); | ||||
| 			testParser.hooks.expression | ||||
| 				.for("fgh.sub") | ||||
| 				.tap("JavascriptParserTest", expr => { | ||||
| 					if (!testParser.state.fghsub) testParser.state.fghsub = []; | ||||
| 					testParser.state.fghsub.push( | ||||
| 						testParser.scope.inTry ? "try" : "notry" | ||||
| 					); | ||||
| 					return true; | ||||
| 				} | ||||
| 			); | ||||
| 			testParser.hooks.expression.tap( | ||||
| 				"ijk.sub", | ||||
| 				"JavascriptParserTest", | ||||
| 				expr => { | ||||
| 				}); | ||||
| 			testParser.hooks.expression | ||||
| 				.for("ijk.sub") | ||||
| 				.tap("JavascriptParserTest", expr => { | ||||
| 					if (!testParser.state.ijksub) testParser.state.ijksub = []; | ||||
| 					testParser.state.ijksub.push("test"); | ||||
| 					return true; | ||||
| 				} | ||||
| 			); | ||||
| 			testParser.hooks.expression.tap( | ||||
| 				"memberExpr", | ||||
| 				"JavascriptParserTest", | ||||
| 				expr => { | ||||
| 				}); | ||||
| 			testParser.hooks.expression | ||||
| 				.for("memberExpr") | ||||
| 				.tap("JavascriptParserTest", expr => { | ||||
| 					if (!testParser.state.expressions) testParser.state.expressions = []; | ||||
| 					testParser.state.expressions.push(expr.name); | ||||
| 					return true; | ||||
| 				} | ||||
| 			); | ||||
| 				}); | ||||
| 			testParser.hooks.new.tap("xyz", "JavascriptParserTest", expr => { | ||||
| 				if (!testParser.state.xyz) testParser.state.xyz = []; | ||||
| 				testParser.state.xyz.push(testParser.parseString(expr.arguments[0])); | ||||
|  | @ -367,23 +361,21 @@ describe("JavascriptParser", () => { | |||
| 	describe("expression evaluation", () => { | ||||
| 		function evaluateInParser(source) { | ||||
| 			const parser = new JavascriptParser(); | ||||
| 			parser.hooks.call.tap("test", "JavascriptParserTest", expr => { | ||||
| 			parser.hooks.call.for("test").tap("JavascriptParserTest", expr => { | ||||
| 				parser.state.result = parser.evaluateExpression(expr.arguments[0]); | ||||
| 			}); | ||||
| 			parser.hooks.evaluateIdentifier.tap( | ||||
| 				"aString", | ||||
| 				"JavascriptParserTest", | ||||
| 				expr => | ||||
| 			parser.hooks.evaluateIdentifier | ||||
| 				.for("aString") | ||||
| 				.tap("JavascriptParserTest", expr => | ||||
| 					new BasicEvaluatedExpression() | ||||
| 						.setString("aString") | ||||
| 						.setRange(expr.range) | ||||
| 			); | ||||
| 			parser.hooks.evaluateIdentifier.tap( | ||||
| 				"b.Number", | ||||
| 				"JavascriptParserTest", | ||||
| 				expr => | ||||
| 				); | ||||
| 			parser.hooks.evaluateIdentifier | ||||
| 				.for("b.Number") | ||||
| 				.tap("JavascriptParserTest", expr => | ||||
| 					new BasicEvaluatedExpression().setNumber(123).setRange(expr.range) | ||||
| 			); | ||||
| 				); | ||||
| 			return parser.parse("test(" + source + ");").result; | ||||
| 		} | ||||
| 
 | ||||
|  | @ -615,7 +607,7 @@ describe("JavascriptParser", () => { | |||
| 			}; | ||||
| 
 | ||||
| 			const parser = new JavascriptParser(); | ||||
| 			parser.hooks.call.tap("require", "JavascriptParserTest", expr => { | ||||
| 			parser.hooks.call.for("require").tap("JavascriptParserTest", expr => { | ||||
| 				const param = parser.evaluateExpression(expr.arguments[0]); | ||||
| 				parser.state.param = param.string; | ||||
| 			}); | ||||
|  |  | |||
|  | @ -6,6 +6,15 @@ const fs = require("graceful-fs"); | |||
| 
 | ||||
| const webpack = require(".."); | ||||
| 
 | ||||
| /** | ||||
|  * Escapes regular expression metacharacters | ||||
|  * @param {string} str String to quote | ||||
|  * @returns {string} Escaped string | ||||
|  */ | ||||
| const quotemeta = str => { | ||||
| 	return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&"); | ||||
| }; | ||||
| 
 | ||||
| const base = path.join(__dirname, "statsCases"); | ||||
| const outputBase = path.join(__dirname, "js", "stats"); | ||||
| const tests = fs | ||||
|  | @ -129,24 +138,21 @@ describe("StatsTestCases", () => { | |||
| 				if (!hasColorSetting) { | ||||
| 					actual = actual | ||||
| 						.replace(/\u001b\[[0-9;]*m/g, "") | ||||
| 						.replace(/[0-9]+(\s?ms)/g, "X$1"); | ||||
| 						.replace(/[.0-9]+(\s?ms)/g, "X$1"); | ||||
| 				} else { | ||||
| 					actual = actual | ||||
| 						.replace(/\u001b\[1m\u001b\[([0-9;]*)m/g, "<CLR=$1,BOLD>") | ||||
| 						.replace(/\u001b\[1m/g, "<CLR=BOLD>") | ||||
| 						.replace(/\u001b\[39m\u001b\[22m/g, "</CLR>") | ||||
| 						.replace(/\u001b\[([0-9;]*)m/g, "<CLR=$1>") | ||||
| 						.replace(/[0-9]+(<\/CLR>)?(\s?ms)/g, "X$1$2"); | ||||
| 						.replace(/[.0-9]+(<\/CLR>)?(\s?ms)/g, "X$1$2"); | ||||
| 				} | ||||
| 				const testPath = path.join(base, testName); | ||||
| 				const testPathPattern = testPath.replace( | ||||
| 					/[-[\]\\/{}()*+?.^$|]/g, | ||||
| 					"\\$&" | ||||
| 				); | ||||
| 				actual = actual | ||||
| 					.replace(/\r\n?/g, "\n") | ||||
| 					.replace(/[\t ]*Version:.+\n/g, "") | ||||
| 					.replace(new RegExp(testPathPattern, "g"), "Xdir/" + testName) | ||||
| 					.replace(new RegExp(quotemeta(testPath), "g"), "Xdir/" + testName) | ||||
| 					.replace(/(\w)\\(\w)/g, "$1/$2") | ||||
| 					.replace(/, additional resolving: Xms/g, ""); | ||||
| 				expect(actual).toMatchSnapshot(); | ||||
| 				done(); | ||||
|  |  | |||
|  | @ -193,7 +193,7 @@ describe("Validation", () => { | |||
| 			expect(msg).toMatchInlineSnapshot(` | ||||
| "Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema. | ||||
|  - configuration has an unknown property 'postcss'. These properties are valid: | ||||
|    object { amd?, bail?, cache?, context?, dependencies?, devServer?, devtool?, entry?, experiments?, externals?, loader?, mode?, module?, name?, node?, optimization?, output?, parallelism?, performance?, plugins?, profile?, recordsInputPath?, recordsOutputPath?, recordsPath?, resolve?, resolveLoader?, serve?, stats?, target?, watch?, watchOptions? } | ||||
|    object { amd?, bail?, cache?, context?, dependencies?, devServer?, devtool?, entry?, experiments?, externals?, infrastructureLogging?, loader?, mode?, module?, name?, node?, optimization?, output?, parallelism?, performance?, plugins?, profile?, recordsInputPath?, recordsOutputPath?, recordsPath?, resolve?, resolveLoader?, serve?, stats?, target?, watch?, watchOptions? } | ||||
|    For typos: please correct them. | ||||
|    For loader options: webpack >= v2.0.0 no longer allows custom properties in configuration. | ||||
|      Loaders should be updated to allow passing options via loader options in module.rules. | ||||
|  |  | |||
|  | @ -1277,6 +1277,43 @@ Child 4 chunks: | |||
|      [767] ./d.js 22 bytes {524} [built]" | ||||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for logging 1`] = ` | ||||
| "Hash: <CLR=BOLD>17d1aced1f8edabe0aa9</CLR> | ||||
| Time: <CLR=BOLD>X</CLR>ms | ||||
| Built at: 1970-04-20 <CLR=BOLD>12:42:42</CLR> | ||||
|   <CLR=BOLD>Asset</CLR>      <CLR=BOLD>Size</CLR>  <CLR=BOLD>Chunks</CLR>             <CLR=BOLD>Chunk Names</CLR> | ||||
| <CLR=32,BOLD>main.js</CLR>  1.32 KiB   {<CLR=33,BOLD>179</CLR>}  <CLR=32,BOLD>[emitted]</CLR>  main | ||||
| Entrypoint <CLR=BOLD>main</CLR> = <CLR=32,BOLD>main.js</CLR> | ||||
| [390] <CLR=BOLD>./index.js</CLR> 1 bytes {<CLR=33,BOLD>179</CLR>} <CLR=32,BOLD>[built]</CLR> | ||||
| 
 | ||||
| <CLR=BOLD>LOG from MyPlugin</CLR> | ||||
| <i> <CLR=32,BOLD>Plugin is now active</CLR> | ||||
| <+> <CLR=36,BOLD>Nested</CLR> | ||||
| + 3 hidden lines | ||||
| 
 | ||||
| <CLR=31,BOLD>DEBUG</CLR> <CLR=BOLD>LOG from ./node_modules/custom-loader/index.js ./node_modules/custom-loader/index.js!./index.js</CLR> | ||||
| <e> <CLR=31,BOLD>An error</CLR> | ||||
| |     at Object.<anonymous>.module.exports (Xdir/logging/node_modules/custom-loader/index.js:5:9) | ||||
| <w> <CLR=33,BOLD>A warning</CLR> | ||||
| |     at Object.<anonymous>.module.exports (Xdir/logging/node_modules/custom-loader/index.js:6:9) | ||||
| <CLR=36,BOLD>Unimportant</CLR> | ||||
|   <i> <CLR=32,BOLD>Info message</CLR> | ||||
|   <CLR=BOLD>Just log</CLR> | ||||
|   Just debug | ||||
|   <t> <CLR=35,BOLD>Measure: Xms</CLR> | ||||
|   <CLR=36,BOLD>Nested</CLR> | ||||
|     <CLR=BOLD>Log inside collapsed group</CLR> | ||||
|   Trace | ||||
|   |     at Object.<anonymous>.module.exports (Xdir/logging/node_modules/custom-loader/index.js:15:9) | ||||
|   <t> <CLR=35,BOLD>Measure: Xms</CLR> | ||||
|   ------- | ||||
|   <CLR=BOLD>After clear</CLR> | ||||
| 
 | ||||
| <CLR=31,BOLD>DEBUG</CLR> <CLR=BOLD>LOG from ./node_modules/custom-loader/index.js Named Logger ./node_modules/custom-loader/index.js!./index.js</CLR> | ||||
| Message with named logger | ||||
| " | ||||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for max-modules 1`] = ` | ||||
| "Hash: 8a3d2df87a4f01705c82 | ||||
| Time: Xms | ||||
|  | @ -2062,20 +2099,48 @@ webpack/runtime/jsonp chunk loading 3.36 KiB {179} [runtime] | |||
|       [used exports unknown] | ||||
| webpack/runtime/publicPath 27 bytes {179} [runtime] | ||||
|       [no exports] | ||||
|       [used exports unknown]" | ||||
|       [used exports unknown] | ||||
| 
 | ||||
| LOG from MyPlugin | ||||
| Group | ||||
|   <e> Error | ||||
|   <w> Warning | ||||
|   <i> Info | ||||
|   Log | ||||
|   <+> Collaped group | ||||
| + 3 hidden lines | ||||
| " | ||||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for preset-errors-only 1`] = `""`; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for preset-errors-only-error 1`] = ` | ||||
| "ERROR in ./index.js 1:0-25 | ||||
| "LOG from MyPlugin | ||||
| <e> Error | ||||
| + 9 hidden lines | ||||
| 
 | ||||
| ERROR in ./index.js 1:0-25 | ||||
| Module not found: Error: Can't resolve 'does-not-exist' in 'Xdir/preset-errors-only-error' | ||||
| " | ||||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for preset-errors-warnings 1`] = `""`; | ||||
| exports[`StatsTestCases should print correct stats for preset-errors-warnings 1`] = ` | ||||
| "LOG from MyPlugin | ||||
| <e> Error | ||||
| <w> Warning | ||||
| + 8 hidden lines | ||||
| " | ||||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for preset-minimal 1`] = `"   10 modules"`; | ||||
| exports[`StatsTestCases should print correct stats for preset-minimal 1`] = ` | ||||
| "   10 modules | ||||
| 
 | ||||
| LOG from MyPlugin | ||||
| <e> Error | ||||
| <w> Warning | ||||
| + 8 hidden lines | ||||
| " | ||||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for preset-minimal-simple 1`] = `"   1 module"`; | ||||
| 
 | ||||
|  | @ -2109,7 +2174,14 @@ Entrypoint main = main.js | |||
| [767] ./d.js 22 bytes {524} [built] | ||||
| [847] ./a.js 22 bytes {179} [built] | ||||
| [996] ./b.js 22 bytes {996} [built] | ||||
|     + 4 hidden modules" | ||||
|     + 4 hidden modules | ||||
| 
 | ||||
| LOG from MyPlugin | ||||
| <e> Error | ||||
| <w> Warning | ||||
| <i> Info | ||||
| + 7 hidden lines | ||||
| " | ||||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for preset-normal-performance 1`] = ` | ||||
|  | @ -2230,7 +2302,18 @@ chunk {996} 996.js 22 bytes <{179}> [rendered] | |||
|  [996] ./b.js 22 bytes {996} [depth 1] [built] | ||||
|        ModuleConcatenation bailout: Module is not an ECMAScript module | ||||
|        amd require ./b [10] ./index.js 2:0-16 | ||||
|        [10] Xms -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)" | ||||
|        [10] Xms -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms) | ||||
| 
 | ||||
| LOG from MyPlugin | ||||
| Group | ||||
|   <e> Error | ||||
|   <w> Warning | ||||
|   <i> Info | ||||
|   Log | ||||
|   Collaped group | ||||
|     Log inside collapsed group | ||||
| + 1 hidden lines | ||||
| " | ||||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for resolve-plugin-context 1`] = ` | ||||
|  |  | |||
|  | @ -0,0 +1,21 @@ | |||
| /* eslint-disable node/no-unsupported-features/node-builtins */ | ||||
| module.exports = function(source) { | ||||
| 	const logger = this.getLogger ? this.getLogger() : console; | ||||
| 	logger.time("Measure"); | ||||
| 	logger.error("An error"); | ||||
| 	logger.warn("A %s", "warning"); | ||||
| 	logger.group("Unimportant"); | ||||
| 	logger.info("Info message"); | ||||
| 	logger.log("Just log"); | ||||
| 	logger.debug("Just debug"); | ||||
| 	logger.timeLog("Measure"); | ||||
| 	logger.groupCollapsed("Nested"); | ||||
| 	logger.log("Log inside collapsed group"); | ||||
| 	logger.groupEnd("Nested"); | ||||
| 	logger.trace(); | ||||
| 	logger.timeEnd("Measure"); | ||||
| 	logger.clear(); | ||||
| 	logger.log("After clear"); | ||||
| 	this.getLogger("Named Logger").debug("Message with named logger"); | ||||
| 	return source; | ||||
| }; | ||||
|  | @ -0,0 +1,36 @@ | |||
| class MyPlugin { | ||||
| 	apply(compiler) { | ||||
| 		compiler.hooks.compilation.tap("MyPlugin", compilation => { | ||||
| 			const logger = compilation.getLogger("MyPlugin"); | ||||
| 			logger.info("Plugin is now active"); | ||||
| 			logger.debug("Debug message should not be visible"); | ||||
| 			logger.groupCollapsed("Nested"); | ||||
| 			logger.log("Log inside collapsed group"); | ||||
| 			logger.groupEnd("Nested"); | ||||
| 
 | ||||
| 			const otherLogger = compilation.getLogger("MyOtherPlugin"); | ||||
| 			otherLogger.debug("debug message only"); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
| 	mode: "production", | ||||
| 	entry: "./index", | ||||
| 	performance: false, | ||||
| 	module: { | ||||
| 		rules: [ | ||||
| 			{ | ||||
| 				test: /index\.js$/, | ||||
| 				use: "custom-loader" | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	plugins: [new MyPlugin()], | ||||
| 	stats: { | ||||
| 		colors: true, | ||||
| 		logging: true, | ||||
| 		loggingDebug: "custom-loader", | ||||
| 		loggingTrace: true | ||||
| 	} | ||||
| }; | ||||
|  | @ -1,5 +1,24 @@ | |||
| class MyPlugin { | ||||
| 	apply(compiler) { | ||||
| 		compiler.hooks.compilation.tap("MyPlugin", compilation => { | ||||
| 			const logger = compilation.getLogger("MyPlugin"); | ||||
| 			logger.group("Group"); | ||||
| 			logger.error("Error"); | ||||
| 			logger.warn("Warning"); | ||||
| 			logger.info("Info"); | ||||
| 			logger.log("Log"); | ||||
| 			logger.debug("Debug"); | ||||
| 			logger.groupCollapsed("Collaped group"); | ||||
| 			logger.log("Log inside collapsed group"); | ||||
| 			logger.groupEnd(); | ||||
| 			logger.groupEnd(); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
| 	mode: "production", | ||||
| 	entry: "./index", | ||||
| 	stats: "detailed" | ||||
| 	stats: "detailed", | ||||
| 	plugins: [new MyPlugin()] | ||||
| }; | ||||
|  |  | |||
|  | @ -1,5 +1,24 @@ | |||
| class MyPlugin { | ||||
| 	apply(compiler) { | ||||
| 		compiler.hooks.compilation.tap("MyPlugin", compilation => { | ||||
| 			const logger = compilation.getLogger("MyPlugin"); | ||||
| 			logger.group("Group"); | ||||
| 			logger.error("Error"); | ||||
| 			logger.warn("Warning"); | ||||
| 			logger.info("Info"); | ||||
| 			logger.log("Log"); | ||||
| 			logger.debug("Debug"); | ||||
| 			logger.groupCollapsed("Collaped group"); | ||||
| 			logger.log("Log inside collapsed group"); | ||||
| 			logger.groupEnd(); | ||||
| 			logger.groupEnd(); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
| 	mode: "production", | ||||
| 	entry: "./index", | ||||
| 	stats: "errors-only" | ||||
| 	stats: "errors-only", | ||||
| 	plugins: [new MyPlugin()] | ||||
| }; | ||||
|  |  | |||
|  | @ -1,5 +1,24 @@ | |||
| class MyPlugin { | ||||
| 	apply(compiler) { | ||||
| 		compiler.hooks.compilation.tap("MyPlugin", compilation => { | ||||
| 			const logger = compilation.getLogger("MyPlugin"); | ||||
| 			logger.group("Group"); | ||||
| 			logger.error("Error"); | ||||
| 			logger.warn("Warning"); | ||||
| 			logger.info("Info"); | ||||
| 			logger.log("Log"); | ||||
| 			logger.debug("Debug"); | ||||
| 			logger.groupCollapsed("Collaped group"); | ||||
| 			logger.log("Log inside collapsed group"); | ||||
| 			logger.groupEnd(); | ||||
| 			logger.groupEnd(); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
| 	mode: "production", | ||||
| 	entry: "./index", | ||||
| 	stats: "errors-warnings" | ||||
| 	stats: "errors-warnings", | ||||
| 	plugins: [new MyPlugin()] | ||||
| }; | ||||
|  |  | |||
|  | @ -1,5 +1,24 @@ | |||
| class MyPlugin { | ||||
| 	apply(compiler) { | ||||
| 		compiler.hooks.compilation.tap("MyPlugin", compilation => { | ||||
| 			const logger = compilation.getLogger("MyPlugin"); | ||||
| 			logger.group("Group"); | ||||
| 			logger.error("Error"); | ||||
| 			logger.warn("Warning"); | ||||
| 			logger.info("Info"); | ||||
| 			logger.log("Log"); | ||||
| 			logger.debug("Debug"); | ||||
| 			logger.groupCollapsed("Collaped group"); | ||||
| 			logger.log("Log inside collapsed group"); | ||||
| 			logger.groupEnd(); | ||||
| 			logger.groupEnd(); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
| 	mode: "production", | ||||
| 	entry: "./index", | ||||
| 	stats: "minimal" | ||||
| 	stats: "minimal", | ||||
| 	plugins: [new MyPlugin()] | ||||
| }; | ||||
|  |  | |||
|  | @ -1,5 +1,24 @@ | |||
| class MyPlugin { | ||||
| 	apply(compiler) { | ||||
| 		compiler.hooks.compilation.tap("MyPlugin", compilation => { | ||||
| 			const logger = compilation.getLogger("MyPlugin"); | ||||
| 			logger.group("Group"); | ||||
| 			logger.error("Error"); | ||||
| 			logger.warn("Warning"); | ||||
| 			logger.info("Info"); | ||||
| 			logger.log("Log"); | ||||
| 			logger.debug("Debug"); | ||||
| 			logger.groupCollapsed("Collaped group"); | ||||
| 			logger.log("Log inside collapsed group"); | ||||
| 			logger.groupEnd(); | ||||
| 			logger.groupEnd(); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
| 	mode: "production", | ||||
| 	entry: "./index", | ||||
| 	stats: false | ||||
| 	stats: false, | ||||
| 	plugins: [new MyPlugin()] | ||||
| }; | ||||
|  |  | |||
|  | @ -1,5 +1,24 @@ | |||
| class MyPlugin { | ||||
| 	apply(compiler) { | ||||
| 		compiler.hooks.compilation.tap("MyPlugin", compilation => { | ||||
| 			const logger = compilation.getLogger("MyPlugin"); | ||||
| 			logger.group("Group"); | ||||
| 			logger.error("Error"); | ||||
| 			logger.warn("Warning"); | ||||
| 			logger.info("Info"); | ||||
| 			logger.log("Log"); | ||||
| 			logger.debug("Debug"); | ||||
| 			logger.groupCollapsed("Collaped group"); | ||||
| 			logger.log("Log inside collapsed group"); | ||||
| 			logger.groupEnd(); | ||||
| 			logger.groupEnd(); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
| 	mode: "production", | ||||
| 	entry: "./index", | ||||
| 	stats: "normal" | ||||
| 	stats: "normal", | ||||
| 	plugins: [new MyPlugin()] | ||||
| }; | ||||
|  |  | |||
|  | @ -1,6 +1,25 @@ | |||
| class MyPlugin { | ||||
| 	apply(compiler) { | ||||
| 		compiler.hooks.compilation.tap("MyPlugin", compilation => { | ||||
| 			const logger = compilation.getLogger("MyPlugin"); | ||||
| 			logger.group("Group"); | ||||
| 			logger.error("Error"); | ||||
| 			logger.warn("Warning"); | ||||
| 			logger.info("Info"); | ||||
| 			logger.log("Log"); | ||||
| 			logger.debug("Debug"); | ||||
| 			logger.groupCollapsed("Collaped group"); | ||||
| 			logger.log("Log inside collapsed group"); | ||||
| 			logger.groupEnd(); | ||||
| 			logger.groupEnd(); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
| 	mode: "production", | ||||
| 	entry: "./index", | ||||
| 	profile: true, | ||||
| 	stats: "verbose" | ||||
| 	stats: "verbose", | ||||
| 	plugins: [new MyPlugin()] | ||||
| }; | ||||
|  |  | |||
							
								
								
									
										46
									
								
								yarn.lock
								
								
								
								
							
							
						
						
									
										46
									
								
								yarn.lock
								
								
								
								
							|  | @ -373,9 +373,9 @@ | |||
|   integrity sha512-MeatbbUsZ80BEsKPXby6pUZjUM9ZuHIpWElN0siopih3fvnlpX2O9L6D5+dzDIb36lf9tM/8U4PVdLQ+L4qr4A== | ||||
| 
 | ||||
| "@types/node@^10.12.21": | ||||
|   version "10.14.12" | ||||
|   resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.12.tgz#0eec3155a46e6c4db1f27c3e588a205f767d622f" | ||||
|   integrity sha512-QcAKpaO6nhHLlxWBvpc4WeLrTvPqlHOvaj0s5GriKkA1zq+bsFBPpfYCvQhLqLgYlIko8A9YrPdaMHCo5mBcpg== | ||||
|   version "10.14.13" | ||||
|   resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.13.tgz#ac786d623860adf39a3f51d629480aacd6a6eec7" | ||||
|   integrity sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ== | ||||
| 
 | ||||
| "@types/prettier@^1.16.1": | ||||
|   version "1.16.1" | ||||
|  | @ -609,9 +609,9 @@ acorn@^5.5.3: | |||
|   integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== | ||||
| 
 | ||||
| acorn@^6.0.1, acorn@^6.0.7, acorn@^6.2.0: | ||||
|   version "6.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.0.tgz#67f0da2fc339d6cfb5d6fb244fd449f33cd8bbe3" | ||||
|   integrity sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw== | ||||
|   version "6.2.1" | ||||
|   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51" | ||||
|   integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q== | ||||
| 
 | ||||
| ajv-errors@^1.0.0: | ||||
|   version "1.0.1" | ||||
|  | @ -1321,10 +1321,10 @@ commander@^2.14.1, commander@^2.19.0, commander@^2.9.0, commander@~2.20.0: | |||
|   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" | ||||
|   integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== | ||||
| 
 | ||||
| comment-parser@^0.5.5: | ||||
|   version "0.5.5" | ||||
|   resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.5.5.tgz#c2584cae7c2f0afc773e96b2ee98f8c10cbd693d" | ||||
|   integrity sha512-oB3TinFT+PV3p8UwDQt71+HkG03+zwPwikDlKU6ZDmql6QX2zFlQ+G0GGSDqyJhdZi4PSlzFBm+YJ+ebOX3Vgw== | ||||
| comment-parser@^0.6.0: | ||||
|   version "0.6.1" | ||||
|   resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.6.1.tgz#88040c7c0a57c62e64962c3e888518620a42e7c9" | ||||
|   integrity sha512-Putzd7Ilyvknmb1KxGf5el9uw0sPx9gEVnDrm8tlvXGN1i8Uaa2VBxB32hUhfzTlrEhhxNQ+pKq4ZNe8wNxjmw== | ||||
| 
 | ||||
| commondir@^1.0.1: | ||||
|   version "1.0.1" | ||||
|  | @ -1841,16 +1841,16 @@ eslint-plugin-es@^1.3.1: | |||
|     regexpp "^2.0.1" | ||||
| 
 | ||||
| eslint-plugin-jest@^22.2.2: | ||||
|   version "22.8.0" | ||||
|   resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.8.0.tgz#242ef5459e8da25d2c41438e95eb546e03d7fae1" | ||||
|   integrity sha512-2VftZMfILmlhL3VMq5ptHRIuyyXb3ShDEDb1J1UjvWNzm4l+UK/YmwNuTuJcM0gv8pJuOfiR/8ZptJ8Ou68pFw== | ||||
|   version "22.13.0" | ||||
|   resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.13.0.tgz#d7d134c6e3c2f67cc50f5fa89a329db579d28428" | ||||
|   integrity sha512-bIr8LL7buUXS8Pk69SFgaDKgyvPQkDu6i8ko0lP54uccszlo4EOwtstDXOZl5Af3JwudbECxRUbCpL/2cKDkkg== | ||||
| 
 | ||||
| eslint-plugin-jsdoc@^15.3.2: | ||||
|   version "15.5.2" | ||||
|   resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-15.5.2.tgz#89768320c64ec2f30d12209e1926c4decca0568a" | ||||
|   integrity sha512-5s39RYGaqugWVoOfc6pAwj9yeNh7mclygBWTyYVJX+sGiNchwCtgHbn2AjeonOw0g168CPI3itiXetHj2Yo8gg== | ||||
|   version "15.5.3" | ||||
|   resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-15.5.3.tgz#44e408e3bf2f60f3ad18dc829f9b9a1e34f33154" | ||||
|   integrity sha512-lw8wYa1UFV53JLoqKOQR8YBkKlE/aguR+HGyytL9VKsVvm83DK8ReYnNNDRKik3MF661cGuaUuGfIEcdqg9l4A== | ||||
|   dependencies: | ||||
|     comment-parser "^0.5.5" | ||||
|     comment-parser "^0.6.0" | ||||
|     debug "^4.1.1" | ||||
|     flat-map-polyfill "^0.3.8" | ||||
|     jsdoctypeparser "5.0.1" | ||||
|  | @ -3835,9 +3835,9 @@ lodash.sortby@^4.7.0: | |||
|   integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= | ||||
| 
 | ||||
| lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.4: | ||||
|   version "4.17.14" | ||||
|   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" | ||||
|   integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== | ||||
|   version "4.17.15" | ||||
|   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" | ||||
|   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== | ||||
| 
 | ||||
| log-driver@^1.2.7: | ||||
|   version "1.2.7" | ||||
|  | @ -5500,9 +5500,9 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: | |||
|   integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= | ||||
| 
 | ||||
| simple-git@^1.65.0, simple-git@^1.85.0: | ||||
|   version "1.121.0" | ||||
|   resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.121.0.tgz#4bdf0828cd1b0bb3cb7ed9bead2771982ef5876a" | ||||
|   integrity sha512-LyYri/nuAX8+cx9nZw38mWO6oHNi//CmiPlkBL7aVjZIsdldve7eeDwXu9L4wP/74MpNHucXkXc/BOuIQShhPg== | ||||
|   version "1.122.0" | ||||
|   resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.122.0.tgz#33b2d3a760aa02df470c79fbab5413d4f4e68945" | ||||
|   integrity sha512-plTwhnkIHrw2TFMJbJH/mKwWGgFbj03V9wcfBKa4FsuvgJbpwdlSJnlvkIQWDV1CVLaf2Gl6zSNeRRnxBRhX1g== | ||||
|   dependencies: | ||||
|     debug "^4.0.1" | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue