mirror of https://github.com/webpack/webpack.git
				
				
				
			
						commit
						c17dfde7a8
					
				|  | @ -75,6 +75,16 @@ export type ExternalItem = | ||||||
|  * via the `definition` "ArrayOfStringValues". |  * via the `definition` "ArrayOfStringValues". | ||||||
|  */ |  */ | ||||||
| export type ArrayOfStringValues = string[]; | 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 |  * One or multiple rule conditions | ||||||
|  * |  * | ||||||
|  | @ -256,16 +266,6 @@ export type OptimizationSplitChunksSizes = | ||||||
| 			 */ | 			 */ | ||||||
| 			[k: string]: number; | 			[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 { | 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`. | 	 * 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; | 	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. | 	 * Custom values available in the loader context. | ||||||
| 	 */ | 	 */ | ||||||
|  | @ -1435,6 +1448,18 @@ export interface StatsOptions { | ||||||
| 	 * add the hash of the compilation | 	 * add the hash of the compilation | ||||||
| 	 */ | 	 */ | ||||||
| 	hash?: boolean; | 	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 | 	 * Set the maximum number of modules to be shown | ||||||
| 	 */ | 	 */ | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ const ChunkRenderError = require("./ChunkRenderError"); | ||||||
| const ChunkTemplate = require("./ChunkTemplate"); | const ChunkTemplate = require("./ChunkTemplate"); | ||||||
| const DependencyTemplates = require("./DependencyTemplates"); | const DependencyTemplates = require("./DependencyTemplates"); | ||||||
| const Entrypoint = require("./Entrypoint"); | const Entrypoint = require("./Entrypoint"); | ||||||
|  | const ErrorHelpers = require("./ErrorHelpers"); | ||||||
| const FileSystemInfo = require("./FileSystemInfo"); | const FileSystemInfo = require("./FileSystemInfo"); | ||||||
| const { | const { | ||||||
| 	connectChunkGroupAndChunk, | 	connectChunkGroupAndChunk, | ||||||
|  | @ -41,6 +42,7 @@ const RuntimeGlobals = require("./RuntimeGlobals"); | ||||||
| const RuntimeTemplate = require("./RuntimeTemplate"); | const RuntimeTemplate = require("./RuntimeTemplate"); | ||||||
| const Stats = require("./Stats"); | const Stats = require("./Stats"); | ||||||
| const WebpackError = require("./WebpackError"); | const WebpackError = require("./WebpackError"); | ||||||
|  | const { Logger, LogType } = require("./logging/Logger"); | ||||||
| const StatsFactory = require("./stats/StatsFactory"); | const StatsFactory = require("./stats/StatsFactory"); | ||||||
| const StatsPrinter = require("./stats/StatsPrinter"); | const StatsPrinter = require("./stats/StatsPrinter"); | ||||||
| const AsyncQueue = require("./util/AsyncQueue"); | const AsyncQueue = require("./util/AsyncQueue"); | ||||||
|  | @ -127,6 +129,14 @@ const { arrayToSetDeprecation } = require("./util/deprecation"); | ||||||
|  * @property {(Record<string, (length: number) => string>)=} contentHashWithLength |  * @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 |  * @typedef {Object} ModulePathData | ||||||
|  * @property {string|number} id |  * @property {string|number} id | ||||||
|  | @ -405,6 +415,9 @@ class Compilation { | ||||||
| 				"compilerIndex" | 				"compilerIndex" | ||||||
| 			]), | 			]), | ||||||
| 
 | 
 | ||||||
|  | 			/** @type {SyncBailHook<[string, LogEntry], true>} */ | ||||||
|  | 			log: new SyncBailHook(["origin", "logEntry"]), | ||||||
|  | 
 | ||||||
| 			/** @type {HookMap<SyncHook<[Object, Object]>>} */ | 			/** @type {HookMap<SyncHook<[Object, Object]>>} */ | ||||||
| 			statsPreset: new HookMap(() => new SyncHook(["options", "context"])), | 			statsPreset: new HookMap(() => new SyncHook(["options", "context"])), | ||||||
| 			/** @type {SyncHook<[Object, Object]>} */ | 			/** @type {SyncHook<[Object, Object]>} */ | ||||||
|  | @ -520,6 +533,8 @@ class Compilation { | ||||||
| 		this.warnings = []; | 		this.warnings = []; | ||||||
| 		/** @type {Compilation[]} */ | 		/** @type {Compilation[]} */ | ||||||
| 		this.children = []; | 		this.children = []; | ||||||
|  | 		/** @type {Map<string, LogEntry[]>} */ | ||||||
|  | 		this.logging = new Map(); | ||||||
| 		/** @type {Map<DepConstructor, ModuleFactory>} */ | 		/** @type {Map<DepConstructor, ModuleFactory>} */ | ||||||
| 		this.dependencyFactories = new Map(); | 		this.dependencyFactories = new Map(); | ||||||
| 		/** @type {DependencyTemplates} */ | 		/** @type {DependencyTemplates} */ | ||||||
|  | @ -582,6 +597,69 @@ class Compilation { | ||||||
| 		return statsPrinter; | 		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 {Module} module module to be added that was created | ||||||
| 	 * @param {ModuleCallback} callback returns the module in the compilation, | 	 * @param {ModuleCallback} callback returns the module in the compilation, | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ const RequestShortener = require("./RequestShortener"); | ||||||
| const ResolverFactory = require("./ResolverFactory"); | const ResolverFactory = require("./ResolverFactory"); | ||||||
| const Stats = require("./Stats"); | const Stats = require("./Stats"); | ||||||
| const Watching = require("./Watching"); | const Watching = require("./Watching"); | ||||||
|  | const { Logger } = require("./logging/Logger"); | ||||||
| const { join, dirname, mkdirp } = require("./util/fs"); | const { join, dirname, mkdirp } = require("./util/fs"); | ||||||
| const { makePathsRelative } = require("./util/identifier"); | const { makePathsRelative } = require("./util/identifier"); | ||||||
| 
 | 
 | ||||||
|  | @ -133,6 +134,9 @@ class Compiler { | ||||||
| 			/** @type {SyncHook<[]>} */ | 			/** @type {SyncHook<[]>} */ | ||||||
| 			watchClose: new 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 the following hooks are weirdly located here
 | ||||||
| 			// TODO move them for webpack 5
 | 			// TODO move them for webpack 5
 | ||||||
| 			/** @type {SyncHook<[]>} */ | 			/** @type {SyncHook<[]>} */ | ||||||
|  | @ -178,6 +182,8 @@ class Compiler { | ||||||
| 		/** @type {ResolverFactory} */ | 		/** @type {ResolverFactory} */ | ||||||
| 		this.resolverFactory = new ResolverFactory(); | 		this.resolverFactory = new ResolverFactory(); | ||||||
| 
 | 
 | ||||||
|  | 		this.infrastructureLogger = undefined; | ||||||
|  | 
 | ||||||
| 		/** @type {WebpackOptions} */ | 		/** @type {WebpackOptions} */ | ||||||
| 		this.options = /** @type {WebpackOptions} */ ({}); | 		this.options = /** @type {WebpackOptions} */ ({}); | ||||||
| 
 | 
 | ||||||
|  | @ -201,6 +207,33 @@ class Compiler { | ||||||
| 		this._assetEmittingWrittenFiles = new Map(); | 		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 {WatchOptions} watchOptions the watcher's options | ||||||
| 	 * @param {Callback<Stats>} handler signals when the call finishes | 	 * @param {Callback<Stats>} handler signals when the call finishes | ||||||
|  |  | ||||||
|  | @ -248,16 +248,20 @@ class NormalModule extends Module { | ||||||
| 
 | 
 | ||||||
| 	createLoaderContext(resolver, options, compilation, fs) { | 	createLoaderContext(resolver, options, compilation, fs) { | ||||||
| 		const requestShortener = compilation.runtimeTemplate.requestShortener; | 		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 = { | 		const loaderContext = { | ||||||
| 			version: 2, | 			version: 2, | ||||||
| 			emitWarning: warning => { | 			emitWarning: warning => { | ||||||
| 				if (!(warning instanceof Error)) { | 				if (!(warning instanceof Error)) { | ||||||
| 					warning = new NonErrorEmittedError(warning); | 					warning = new NonErrorEmittedError(warning); | ||||||
| 				} | 				} | ||||||
| 				const currentLoader = this.getCurrentLoader(loaderContext); |  | ||||||
| 				this.warnings.push( | 				this.warnings.push( | ||||||
| 					new ModuleWarning(warning, { | 					new ModuleWarning(warning, { | ||||||
| 						from: requestShortener.shorten(currentLoader.loader) | 						from: getCurrentLoaderName() | ||||||
| 					}) | 					}) | ||||||
| 				); | 				); | ||||||
| 			}, | 			}, | ||||||
|  | @ -265,13 +269,20 @@ class NormalModule extends Module { | ||||||
| 				if (!(error instanceof Error)) { | 				if (!(error instanceof Error)) { | ||||||
| 					error = new NonErrorEmittedError(error); | 					error = new NonErrorEmittedError(error); | ||||||
| 				} | 				} | ||||||
| 				const currentLoader = this.getCurrentLoader(loaderContext); |  | ||||||
| 				this.errors.push( | 				this.errors.push( | ||||||
| 					new ModuleError(error, { | 					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) { | 			resolve(context, request, callback) { | ||||||
| 				resolver.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.mainFields", ["loader", "main"]); | ||||||
| 		this.set("resolveLoader.extensions", [".js"]); | 		this.set("resolveLoader.extensions", [".js"]); | ||||||
| 		this.set("resolveLoader.mainFiles", ["index"]); | 		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 CachedInputFileSystem = require("enhanced-resolve/lib/CachedInputFileSystem"); | ||||||
| const fs = require("graceful-fs"); | const fs = require("graceful-fs"); | ||||||
|  | const createConsoleLogger = require("../logging/createConsoleLogger"); | ||||||
| const NodeWatchFileSystem = require("./NodeWatchFileSystem"); | const NodeWatchFileSystem = require("./NodeWatchFileSystem"); | ||||||
| 
 | 
 | ||||||
| /** @typedef {import("../Compiler")} Compiler */ | /** @typedef {import("../Compiler")} Compiler */ | ||||||
| 
 | 
 | ||||||
| class NodeEnvironmentPlugin { | class NodeEnvironmentPlugin { | ||||||
|  | 	constructor(options) { | ||||||
|  | 		this.options = options || {}; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param {Compiler} compiler the compiler instance | 	 * @param {Compiler} compiler the compiler instance | ||||||
| 	 * @returns {void} | 	 * @returns {void} | ||||||
| 	 */ | 	 */ | ||||||
| 	apply(compiler) { | 	apply(compiler) { | ||||||
|  | 		compiler.infrastructureLogger = createConsoleLogger( | ||||||
|  | 			Object.assign( | ||||||
|  | 				{ | ||||||
|  | 					level: "info", | ||||||
|  | 					debug: false | ||||||
|  | 				}, | ||||||
|  | 				this.options.infrastructureLogging | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
| 		compiler.inputFileSystem = new CachedInputFileSystem(fs, 60000); | 		compiler.inputFileSystem = new CachedInputFileSystem(fs, 60000); | ||||||
| 		const inputFileSystem = compiler.inputFileSystem; | 		const inputFileSystem = compiler.inputFileSystem; | ||||||
| 		compiler.outputFileSystem = fs; | 		compiler.outputFileSystem = fs; | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const formatLocation = require("../formatLocation"); | const formatLocation = require("../formatLocation"); | ||||||
|  | const { LogType } = require("../logging/Logger"); | ||||||
| const AggressiveSplittingPlugin = require("../optimize/AggressiveSplittingPlugin"); | const AggressiveSplittingPlugin = require("../optimize/AggressiveSplittingPlugin"); | ||||||
| const ConcatenatedModule = require("../optimize/ConcatenatedModule"); | const ConcatenatedModule = require("../optimize/ConcatenatedModule"); | ||||||
| const SizeLimitsPlugin = require("../performance/SizeLimitsPlugin"); | const SizeLimitsPlugin = require("../performance/SizeLimitsPlugin"); | ||||||
|  | @ -19,6 +20,7 @@ const { | ||||||
| 	compareModulesById, | 	compareModulesById, | ||||||
| 	compareModulesByIdOrIdentifier | 	compareModulesByIdOrIdentifier | ||||||
| } = require("../util/comparators"); | } = require("../util/comparators"); | ||||||
|  | const identifierUtils = require("../util/identifier"); | ||||||
| 
 | 
 | ||||||
| /** @typedef {import("webpack-sources").Source} Source */ | /** @typedef {import("webpack-sources").Source} Source */ | ||||||
| /** @typedef {import("../Chunk")} Chunk */ | /** @typedef {import("../Chunk")} Chunk */ | ||||||
|  | @ -46,6 +48,7 @@ const { | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * @typedef {Object} UsualOptions |  * @typedef {Object} UsualOptions | ||||||
|  |  * @property {string} context | ||||||
|  * @property {RequestShortener} requestShortener |  * @property {RequestShortener} requestShortener | ||||||
|  * @property {string} chunksSort |  * @property {string} chunksSort | ||||||
|  * @property {string} modulesSort |  * @property {string} modulesSort | ||||||
|  | @ -54,6 +57,9 @@ const { | ||||||
|  * @property {Function[]} excludeModules |  * @property {Function[]} excludeModules | ||||||
|  * @property {Function[]} warningsFilter |  * @property {Function[]} warningsFilter | ||||||
|  * @property {number} maxModules |  * @property {number} maxModules | ||||||
|  |  * @property {false|"none"|"error"|"warn"|"info"|"log"|"verbose"} logging | ||||||
|  |  * @property {Function[]} loggingDebug | ||||||
|  |  * @property {boolean} loggingTrace | ||||||
|  * @property {any} _env |  * @property {any} _env | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | @ -280,6 +286,128 @@ const SIMPLE_EXTRACTORS = { | ||||||
| 				context | 				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) => { | 		children: (object, compilation, context, options, factory) => { | ||||||
| 			const { type } = context; | 			const { type } = context; | ||||||
| 			object.children = factory.create( | 			object.children = factory.create( | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ const NAMED_PRESETS = { | ||||||
| 		optimizationBailout: true, | 		optimizationBailout: true, | ||||||
| 		errorDetails: true, | 		errorDetails: true, | ||||||
| 		publicPath: true, | 		publicPath: true, | ||||||
|  | 		logging: "verbose", | ||||||
| 		orphanModules: true, | 		orphanModules: true, | ||||||
| 		runtime: true, | 		runtime: true, | ||||||
| 		exclude: false, | 		exclude: false, | ||||||
|  | @ -55,6 +56,7 @@ const NAMED_PRESETS = { | ||||||
| 		optimizationBailout: true, | 		optimizationBailout: true, | ||||||
| 		errorDetails: true, | 		errorDetails: true, | ||||||
| 		publicPath: true, | 		publicPath: true, | ||||||
|  | 		logging: true, | ||||||
| 		runtimeModules: true, | 		runtimeModules: true, | ||||||
| 		runtime: true, | 		runtime: true, | ||||||
| 		exclude: false, | 		exclude: false, | ||||||
|  | @ -65,17 +67,20 @@ const NAMED_PRESETS = { | ||||||
| 		modules: true, | 		modules: true, | ||||||
| 		maxModules: 0, | 		maxModules: 0, | ||||||
| 		errors: true, | 		errors: true, | ||||||
| 		warnings: true | 		warnings: true, | ||||||
|  | 		logging: "warn" | ||||||
| 	}, | 	}, | ||||||
| 	"errors-only": { | 	"errors-only": { | ||||||
| 		all: false, | 		all: false, | ||||||
| 		errors: true, | 		errors: true, | ||||||
| 		moduleTrace: true | 		moduleTrace: true, | ||||||
|  | 		logging: "error" | ||||||
| 	}, | 	}, | ||||||
| 	"errors-warnings": { | 	"errors-warnings": { | ||||||
| 		all: false, | 		all: false, | ||||||
| 		errors: true, | 		errors: true, | ||||||
| 		warnings: true | 		warnings: true, | ||||||
|  | 		logging: "warn" | ||||||
| 	}, | 	}, | ||||||
| 	none: { | 	none: { | ||||||
| 		all: false | 		all: false | ||||||
|  | @ -132,6 +137,10 @@ const DEFAULTS = { | ||||||
| 	errorDetails: OFF_FOR_TO_STRING, | 	errorDetails: OFF_FOR_TO_STRING, | ||||||
| 	warnings: NORMAL_ON, | 	warnings: NORMAL_ON, | ||||||
| 	publicPath: OFF_FOR_TO_STRING, | 	publicPath: OFF_FOR_TO_STRING, | ||||||
|  | 	logging: ({ all }, { forToString }) => | ||||||
|  | 		(forToString && all !== false ? "info" : false), | ||||||
|  | 	loggingDebug: () => [], | ||||||
|  | 	loggingTrace: OFF_FOR_TO_STRING, | ||||||
| 	excludeModules: () => [], | 	excludeModules: () => [], | ||||||
| 	excludeAssets: () => [], | 	excludeAssets: () => [], | ||||||
| 	maxModules: (o, { forToString }) => ((forToString ? 15 : Infinity)), | 	maxModules: (o, { forToString }) => ((forToString ? 15 : Infinity)), | ||||||
|  | @ -142,7 +151,7 @@ const DEFAULTS = { | ||||||
| 	colors: () => false | 	colors: () => false | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const normalizeExclude = item => { | const normalizeFilter = item => { | ||||||
| 	if (typeof item === "string") { | 	if (typeof item === "string") { | ||||||
| 		const regExp = new RegExp( | 		const regExp = new RegExp( | ||||||
| 			`[\\\\/]${item.replace( | 			`[\\\\/]${item.replace( | ||||||
|  | @ -169,13 +178,13 @@ const NORMALIZER = { | ||||||
| 		if (!Array.isArray(value)) { | 		if (!Array.isArray(value)) { | ||||||
| 			value = value ? [value] : []; | 			value = value ? [value] : []; | ||||||
| 		} | 		} | ||||||
| 		return value.map(normalizeExclude); | 		return value.map(normalizeFilter); | ||||||
| 	}, | 	}, | ||||||
| 	excludeAssets: value => { | 	excludeAssets: value => { | ||||||
| 		if (!Array.isArray(value)) { | 		if (!Array.isArray(value)) { | ||||||
| 			value = value ? [value] : []; | 			value = value ? [value] : []; | ||||||
| 		} | 		} | ||||||
| 		return value.map(normalizeExclude); | 		return value.map(normalizeFilter); | ||||||
| 	}, | 	}, | ||||||
| 	warningsFilter: value => { | 	warningsFilter: value => { | ||||||
| 		if (!Array.isArray(value)) { | 		if (!Array.isArray(value)) { | ||||||
|  | @ -195,6 +204,16 @@ const NORMALIZER = { | ||||||
| 				`Can only filter warnings with Strings or RegExps. (Given: ${filter})` | 				`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 |  * @param {number} n a number | ||||||
|  * @returns {string} number as two digit string, leading 0 |  * @returns {string} number as two digit string, leading 0 | ||||||
|  | @ -130,6 +136,14 @@ const SIMPLE_PRINTERS = { | ||||||
| 						: filteredAssets | 						: filteredAssets | ||||||
| 			  } ${plural(filteredAssets, "asset", "assets")}` | 			  } ${plural(filteredAssets, "asset", "assets")}` | ||||||
| 			: undefined, | 			: 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 => | 	"compilation.children[].compilation.name": name => | ||||||
| 		name ? `Child ${name}:` : "Child", | 		name ? `Child ${name}:` : "Child", | ||||||
| 
 | 
 | ||||||
|  | @ -402,12 +416,45 @@ const SIMPLE_PRINTERS = { | ||||||
| 	"error.moduleTrace": moduleTrace => undefined, | 	"error.moduleTrace": moduleTrace => undefined, | ||||||
| 	"error.separator!": () => "\n", | 	"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, | 	"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 | 	"moduleTraceDependency.loc": loc => loc | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** @type {Record<string, string>} */ | /** @type {Record<string, string | Function>} */ | ||||||
| const ITEM_NAMES = { | const ITEM_NAMES = { | ||||||
| 	"compilation.assets[]": "asset", | 	"compilation.assets[]": "asset", | ||||||
| 	"compilation.modules[]": "module", | 	"compilation.modules[]": "module", | ||||||
|  | @ -416,6 +463,7 @@ const ITEM_NAMES = { | ||||||
| 	"compilation.namedChunkGroups[]": "chunkGroup", | 	"compilation.namedChunkGroups[]": "chunkGroup", | ||||||
| 	"compilation.errors[]": "error", | 	"compilation.errors[]": "error", | ||||||
| 	"compilation.warnings[]": "error", | 	"compilation.warnings[]": "error", | ||||||
|  | 	"compilation.logging[]": "loggingGroup", | ||||||
| 	"compilation.children[]": "compilation", | 	"compilation.children[]": "compilation", | ||||||
| 	"asset.chunks[]": "assetChunk", | 	"asset.chunks[]": "assetChunk", | ||||||
| 	"asset.auxiliaryChunks[]": "assetChunk", | 	"asset.auxiliaryChunks[]": "assetChunk", | ||||||
|  | @ -427,6 +475,10 @@ const ITEM_NAMES = { | ||||||
| 	"chunk.origins[]": "chunkOrigin", | 	"chunk.origins[]": "chunkOrigin", | ||||||
| 	"chunk.rootModules[]": "module", | 	"chunk.rootModules[]": "module", | ||||||
| 	"chunk.modules[]": "module", | 	"chunk.modules[]": "module", | ||||||
|  | 	"loggingGroup.entries[]": logEntry => | ||||||
|  | 		`loggingEntry(${logEntry.type}).loggingEntry`, | ||||||
|  | 	"loggingEntry.children[]": logEntry => | ||||||
|  | 		`loggingEntry(${logEntry.type}).loggingEntry`, | ||||||
| 	"error.moduleTrace[]": "moduleTraceItem", | 	"error.moduleTrace[]": "moduleTraceItem", | ||||||
| 	"moduleTraceItem.dependencies[]": "moduleTraceDependency" | 	"moduleTraceItem.dependencies[]": "moduleTraceDependency" | ||||||
| }; | }; | ||||||
|  | @ -467,6 +519,7 @@ const PREFERED_ORDERS = { | ||||||
| 		"chunks", | 		"chunks", | ||||||
| 		"modules", | 		"modules", | ||||||
| 		"filteredModules", | 		"filteredModules", | ||||||
|  | 		"logging", | ||||||
| 		"warnings", | 		"warnings", | ||||||
| 		"errors", | 		"errors", | ||||||
| 		"children", | 		"children", | ||||||
|  | @ -572,6 +625,15 @@ const PREFERED_ORDERS = { | ||||||
| 	error: ERROR_PREFERED_ORDER, | 	error: ERROR_PREFERED_ORDER, | ||||||
| 	warning: ERROR_PREFERED_ORDER, | 	warning: ERROR_PREFERED_ORDER, | ||||||
| 	"chunk.childrenByOrder[]": ["type", "children"], | 	"chunk.childrenByOrder[]": ["type", "children"], | ||||||
|  | 	loggingGroup: [ | ||||||
|  | 		"debug", | ||||||
|  | 		"name", | ||||||
|  | 		"separator!", | ||||||
|  | 		"entries", | ||||||
|  | 		"separator!", | ||||||
|  | 		"filtredEntries" | ||||||
|  | 	], | ||||||
|  | 	loggingEntry: ["message", "trace", "children"], | ||||||
| 	"chunkGroup.childAssets[]": ["type", "children"] | 	"chunkGroup.childAssets[]": ["type", "children"] | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -608,7 +670,10 @@ const SIMPLE_ITEMS_JOINER = { | ||||||
| 			.join(" "), | 			.join(" "), | ||||||
| 	"compilation.errors": itemsJoinMoreSpacing, | 	"compilation.errors": itemsJoinMoreSpacing, | ||||||
| 	"compilation.warnings": itemsJoinMoreSpacing, | 	"compilation.warnings": itemsJoinMoreSpacing, | ||||||
|  | 	"compilation.logging": itemsJoinMoreSpacing, | ||||||
| 	"moduleTraceItem.dependencies": itemsJoinOneLine, | 	"moduleTraceItem.dependencies": itemsJoinOneLine, | ||||||
|  | 	"loggingEntry.children": items => | ||||||
|  | 		indent(items.filter(Boolean).join("\n"), "  ", false), | ||||||
| 	"compilation.children": items => | 	"compilation.children": items => | ||||||
| 		items.map(item => indent(item, "    ", true)).join("\n") | 		items.map(item => indent(item, "    ", true)).join("\n") | ||||||
| }; | }; | ||||||
|  | @ -701,7 +766,9 @@ const SIMPLE_ELEMENT_JOINERS = { | ||||||
| 		for (const item of items) { | 		for (const item of items) { | ||||||
| 			if (!item.content) continue; | 			if (!item.content) continue; | ||||||
| 			const needMoreSpace = | 			const needMoreSpace = | ||||||
| 				item.element === "warnings" || item.element === "errors"; | 				item.element === "warnings" || | ||||||
|  | 				item.element === "errors" || | ||||||
|  | 				item.element === "logging"; | ||||||
| 			if (result.length !== 0) { | 			if (result.length !== 0) { | ||||||
| 				result.push(needMoreSpace || lastNeedMore ? "\n\n" : "\n"); | 				result.push(needMoreSpace || lastNeedMore ? "\n\n" : "\n"); | ||||||
| 			} | 			} | ||||||
|  | @ -797,6 +864,7 @@ const SIMPLE_ELEMENT_JOINERS = { | ||||||
| 	chunkOrigin: items => "   > " + joinOneLine(items), | 	chunkOrigin: items => "   > " + joinOneLine(items), | ||||||
| 	"errors[].error": joinError(true), | 	"errors[].error": joinError(true), | ||||||
| 	"warnings[].error": joinError(false), | 	"warnings[].error": joinError(false), | ||||||
|  | 	loggingGroup: items => joinExplicitNewLine(items, "").trimRight(), | ||||||
| 	moduleTraceItem: items => " @ " + joinOneLine(items), | 	moduleTraceItem: items => " @ " + joinOneLine(items), | ||||||
| 	moduleTraceDependency: joinOneLine | 	moduleTraceDependency: joinOneLine | ||||||
| }; | }; | ||||||
|  | @ -973,7 +1041,10 @@ class DefaultStatsPrinterPlugin { | ||||||
| 						const itemName = ITEM_NAMES[key]; | 						const itemName = ITEM_NAMES[key]; | ||||||
| 						stats.hooks.getItemName | 						stats.hooks.getItemName | ||||||
| 							.for(key) | 							.for(key) | ||||||
| 							.tap("DefaultStatsPrinterPlugin", () => itemName); | 							.tap( | ||||||
|  | 								"DefaultStatsPrinterPlugin", | ||||||
|  | 								typeof itemName === "string" ? () => itemName : itemName | ||||||
|  | 							); | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					for (const key of Object.keys(SIMPLE_ITEMS_JOINER)) { | 					for (const key of Object.keys(SIMPLE_ITEMS_JOINER)) { | ||||||
|  |  | ||||||
|  | @ -52,7 +52,9 @@ const createCompiler = options => { | ||||||
| 	options = new WebpackOptionsDefaulter().process(options); | 	options = new WebpackOptionsDefaulter().process(options); | ||||||
| 	const compiler = new Compiler(options.context); | 	const compiler = new Compiler(options.context); | ||||||
| 	compiler.options = options; | 	compiler.options = options; | ||||||
| 	new NodeEnvironmentPlugin().apply(compiler); | 	new NodeEnvironmentPlugin({ | ||||||
|  | 		infrastructureLogging: options.infrastructureLogging | ||||||
|  | 	}).apply(compiler); | ||||||
| 	if (Array.isArray(options.plugins)) { | 	if (Array.isArray(options.plugins)) { | ||||||
| 		for (const plugin of options.plugins) { | 		for (const plugin of options.plugins) { | ||||||
| 			if (typeof plugin === "function") { | 			if (typeof plugin === "function") { | ||||||
|  |  | ||||||
|  | @ -252,7 +252,7 @@ | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           "instanceof": "Function", |           "instanceof": "Function", | ||||||
|           "tsType": "Function" |           "tsType": "((value: string) => boolean)" | ||||||
|         } |         } | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|  | @ -2006,6 +2006,35 @@ | ||||||
|           "description": "add the hash of the compilation", |           "description": "add the hash of the compilation", | ||||||
|           "type": "boolean" |           "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": { |         "maxModules": { | ||||||
|           "description": "Set the maximum number of modules to be shown", |           "description": "Set the maximum number of modules to be shown", | ||||||
|           "type": "number" |           "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": { |     "loader": { | ||||||
|       "description": "Custom values available in the loader context.", |       "description": "Custom values available in the loader context.", | ||||||
|       "type": "object" |       "type": "object" | ||||||
|  |  | ||||||
|  | @ -709,4 +709,152 @@ describe("Compiler", () => { | ||||||
| 			done(); | 			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 state = testCases[name][1]; | ||||||
| 
 | 
 | ||||||
| 			const testParser = new JavascriptParser({}); | 			const testParser = new JavascriptParser({}); | ||||||
| 			testParser.hooks.canRename.tap( | 			testParser.hooks.canRename | ||||||
| 				"abc", | 				.for("abc") | ||||||
| 				"JavascriptParserTest", | 				.tap("JavascriptParserTest", expr => true); | ||||||
| 				expr => true | 			testParser.hooks.canRename | ||||||
| 			); | 				.for("ijk") | ||||||
| 			testParser.hooks.canRename.tap( | 				.tap("JavascriptParserTest", expr => true); | ||||||
| 				"ijk", | 			testParser.hooks.call.for("abc").tap("JavascriptParserTest", expr => { | ||||||
| 				"JavascriptParserTest", |  | ||||||
| 				expr => true |  | ||||||
| 			); |  | ||||||
| 			testParser.hooks.call.tap("abc", "JavascriptParserTest", expr => { |  | ||||||
| 				if (!testParser.state.abc) testParser.state.abc = []; | 				if (!testParser.state.abc) testParser.state.abc = []; | ||||||
| 				testParser.state.abc.push(testParser.parseString(expr.arguments[0])); | 				testParser.state.abc.push(testParser.parseString(expr.arguments[0])); | ||||||
| 				return true; | 				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 = []; | 				if (!testParser.state.cdeabc) testParser.state.cdeabc = []; | ||||||
| 				testParser.state.cdeabc.push(testParser.parseString(expr.arguments[0])); | 				testParser.state.cdeabc.push(testParser.parseString(expr.arguments[0])); | ||||||
| 				return true; | 				return true; | ||||||
| 			}); | 			}); | ||||||
| 			testParser.hooks.call.tap("cde.ddd.abc", "JavascriptParserTest", expr => { | 			testParser.hooks.call | ||||||
|  | 				.for("cde.ddd.abc") | ||||||
|  | 				.tap("JavascriptParserTest", expr => { | ||||||
| 					if (!testParser.state.cdedddabc) testParser.state.cdedddabc = []; | 					if (!testParser.state.cdedddabc) testParser.state.cdedddabc = []; | ||||||
| 					testParser.state.cdedddabc.push( | 					testParser.state.cdedddabc.push( | ||||||
| 						testParser.parseString(expr.arguments[0]) | 						testParser.parseString(expr.arguments[0]) | ||||||
| 					); | 					); | ||||||
| 					return true; | 					return true; | ||||||
| 				}); | 				}); | ||||||
| 			testParser.hooks.expression.tap("fgh", "JavascriptParserTest", expr => { | 			testParser.hooks.expression | ||||||
|  | 				.for("fgh") | ||||||
|  | 				.tap("JavascriptParserTest", expr => { | ||||||
| 					if (!testParser.state.fgh) testParser.state.fgh = []; | 					if (!testParser.state.fgh) testParser.state.fgh = []; | ||||||
| 					testParser.state.fgh.push( | 					testParser.state.fgh.push( | ||||||
| 						Array.from(testParser.scope.definitions.asSet()).join(" ") | 						Array.from(testParser.scope.definitions.asSet()).join(" ") | ||||||
| 					); | 					); | ||||||
| 					return true; | 					return true; | ||||||
| 				}); | 				}); | ||||||
| 			testParser.hooks.expression.tap( | 			testParser.hooks.expression | ||||||
| 				"fgh.sub", | 				.for("fgh.sub") | ||||||
| 				"JavascriptParserTest", | 				.tap("JavascriptParserTest", expr => { | ||||||
| 				expr => { |  | ||||||
| 					if (!testParser.state.fghsub) testParser.state.fghsub = []; | 					if (!testParser.state.fghsub) testParser.state.fghsub = []; | ||||||
| 					testParser.state.fghsub.push( | 					testParser.state.fghsub.push( | ||||||
| 						testParser.scope.inTry ? "try" : "notry" | 						testParser.scope.inTry ? "try" : "notry" | ||||||
| 					); | 					); | ||||||
| 					return true; | 					return true; | ||||||
| 				} | 				}); | ||||||
| 			); | 			testParser.hooks.expression | ||||||
| 			testParser.hooks.expression.tap( | 				.for("ijk.sub") | ||||||
| 				"ijk.sub", | 				.tap("JavascriptParserTest", expr => { | ||||||
| 				"JavascriptParserTest", |  | ||||||
| 				expr => { |  | ||||||
| 					if (!testParser.state.ijksub) testParser.state.ijksub = []; | 					if (!testParser.state.ijksub) testParser.state.ijksub = []; | ||||||
| 					testParser.state.ijksub.push("test"); | 					testParser.state.ijksub.push("test"); | ||||||
| 					return true; | 					return true; | ||||||
| 				} | 				}); | ||||||
| 			); | 			testParser.hooks.expression | ||||||
| 			testParser.hooks.expression.tap( | 				.for("memberExpr") | ||||||
| 				"memberExpr", | 				.tap("JavascriptParserTest", expr => { | ||||||
| 				"JavascriptParserTest", |  | ||||||
| 				expr => { |  | ||||||
| 					if (!testParser.state.expressions) testParser.state.expressions = []; | 					if (!testParser.state.expressions) testParser.state.expressions = []; | ||||||
| 					testParser.state.expressions.push(expr.name); | 					testParser.state.expressions.push(expr.name); | ||||||
| 					return true; | 					return true; | ||||||
| 				} | 				}); | ||||||
| 			); |  | ||||||
| 			testParser.hooks.new.tap("xyz", "JavascriptParserTest", expr => { | 			testParser.hooks.new.tap("xyz", "JavascriptParserTest", expr => { | ||||||
| 				if (!testParser.state.xyz) testParser.state.xyz = []; | 				if (!testParser.state.xyz) testParser.state.xyz = []; | ||||||
| 				testParser.state.xyz.push(testParser.parseString(expr.arguments[0])); | 				testParser.state.xyz.push(testParser.parseString(expr.arguments[0])); | ||||||
|  | @ -367,21 +361,19 @@ describe("JavascriptParser", () => { | ||||||
| 	describe("expression evaluation", () => { | 	describe("expression evaluation", () => { | ||||||
| 		function evaluateInParser(source) { | 		function evaluateInParser(source) { | ||||||
| 			const parser = new JavascriptParser(); | 			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.state.result = parser.evaluateExpression(expr.arguments[0]); | ||||||
| 			}); | 			}); | ||||||
| 			parser.hooks.evaluateIdentifier.tap( | 			parser.hooks.evaluateIdentifier | ||||||
| 				"aString", | 				.for("aString") | ||||||
| 				"JavascriptParserTest", | 				.tap("JavascriptParserTest", expr => | ||||||
| 				expr => |  | ||||||
| 					new BasicEvaluatedExpression() | 					new BasicEvaluatedExpression() | ||||||
| 						.setString("aString") | 						.setString("aString") | ||||||
| 						.setRange(expr.range) | 						.setRange(expr.range) | ||||||
| 				); | 				); | ||||||
| 			parser.hooks.evaluateIdentifier.tap( | 			parser.hooks.evaluateIdentifier | ||||||
| 				"b.Number", | 				.for("b.Number") | ||||||
| 				"JavascriptParserTest", | 				.tap("JavascriptParserTest", expr => | ||||||
| 				expr => |  | ||||||
| 					new BasicEvaluatedExpression().setNumber(123).setRange(expr.range) | 					new BasicEvaluatedExpression().setNumber(123).setRange(expr.range) | ||||||
| 				); | 				); | ||||||
| 			return parser.parse("test(" + source + ");").result; | 			return parser.parse("test(" + source + ");").result; | ||||||
|  | @ -615,7 +607,7 @@ describe("JavascriptParser", () => { | ||||||
| 			}; | 			}; | ||||||
| 
 | 
 | ||||||
| 			const parser = new 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]); | 				const param = parser.evaluateExpression(expr.arguments[0]); | ||||||
| 				parser.state.param = param.string; | 				parser.state.param = param.string; | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
|  | @ -6,6 +6,15 @@ const fs = require("graceful-fs"); | ||||||
| 
 | 
 | ||||||
| const webpack = require(".."); | 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 base = path.join(__dirname, "statsCases"); | ||||||
| const outputBase = path.join(__dirname, "js", "stats"); | const outputBase = path.join(__dirname, "js", "stats"); | ||||||
| const tests = fs | const tests = fs | ||||||
|  | @ -129,24 +138,21 @@ describe("StatsTestCases", () => { | ||||||
| 				if (!hasColorSetting) { | 				if (!hasColorSetting) { | ||||||
| 					actual = actual | 					actual = actual | ||||||
| 						.replace(/\u001b\[[0-9;]*m/g, "") | 						.replace(/\u001b\[[0-9;]*m/g, "") | ||||||
| 						.replace(/[0-9]+(\s?ms)/g, "X$1"); | 						.replace(/[.0-9]+(\s?ms)/g, "X$1"); | ||||||
| 				} else { | 				} else { | ||||||
| 					actual = actual | 					actual = actual | ||||||
| 						.replace(/\u001b\[1m\u001b\[([0-9;]*)m/g, "<CLR=$1,BOLD>") | 						.replace(/\u001b\[1m\u001b\[([0-9;]*)m/g, "<CLR=$1,BOLD>") | ||||||
| 						.replace(/\u001b\[1m/g, "<CLR=BOLD>") | 						.replace(/\u001b\[1m/g, "<CLR=BOLD>") | ||||||
| 						.replace(/\u001b\[39m\u001b\[22m/g, "</CLR>") | 						.replace(/\u001b\[39m\u001b\[22m/g, "</CLR>") | ||||||
| 						.replace(/\u001b\[([0-9;]*)m/g, "<CLR=$1>") | 						.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 testPath = path.join(base, testName); | ||||||
| 				const testPathPattern = testPath.replace( |  | ||||||
| 					/[-[\]\\/{}()*+?.^$|]/g, |  | ||||||
| 					"\\$&" |  | ||||||
| 				); |  | ||||||
| 				actual = actual | 				actual = actual | ||||||
| 					.replace(/\r\n?/g, "\n") | 					.replace(/\r\n?/g, "\n") | ||||||
| 					.replace(/[\t ]*Version:.+\n/g, "") | 					.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, ""); | 					.replace(/, additional resolving: Xms/g, ""); | ||||||
| 				expect(actual).toMatchSnapshot(); | 				expect(actual).toMatchSnapshot(); | ||||||
| 				done(); | 				done(); | ||||||
|  |  | ||||||
|  | @ -193,7 +193,7 @@ describe("Validation", () => { | ||||||
| 			expect(msg).toMatchInlineSnapshot(` | 			expect(msg).toMatchInlineSnapshot(` | ||||||
| "Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema. | "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: |  - 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 typos: please correct them. | ||||||
|    For loader options: webpack >= v2.0.0 no longer allows custom properties in configuration. |    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. |      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]" |      [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`] = ` | exports[`StatsTestCases should print correct stats for max-modules 1`] = ` | ||||||
| "Hash: 8a3d2df87a4f01705c82 | "Hash: 8a3d2df87a4f01705c82 | ||||||
| Time: Xms | Time: Xms | ||||||
|  | @ -2062,20 +2099,48 @@ webpack/runtime/jsonp chunk loading 3.36 KiB {179} [runtime] | ||||||
|       [used exports unknown] |       [used exports unknown] | ||||||
| webpack/runtime/publicPath 27 bytes {179} [runtime] | webpack/runtime/publicPath 27 bytes {179} [runtime] | ||||||
|       [no exports] |       [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 1`] = `""`; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for preset-errors-only-error 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' | 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"`; | 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] | [767] ./d.js 22 bytes {524} [built] | ||||||
| [847] ./a.js 22 bytes {179} [built] | [847] ./a.js 22 bytes {179} [built] | ||||||
| [996] ./b.js 22 bytes {996} [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`] = ` | 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] |  [996] ./b.js 22 bytes {996} [depth 1] [built] | ||||||
|        ModuleConcatenation bailout: Module is not an ECMAScript module |        ModuleConcatenation bailout: Module is not an ECMAScript module | ||||||
|        amd require ./b [10] ./index.js 2:0-16 |        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`] = ` | 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 = { | module.exports = { | ||||||
| 	mode: "production", | 	mode: "production", | ||||||
| 	entry: "./index", | 	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 = { | module.exports = { | ||||||
| 	mode: "production", | 	mode: "production", | ||||||
| 	entry: "./index", | 	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 = { | module.exports = { | ||||||
| 	mode: "production", | 	mode: "production", | ||||||
| 	entry: "./index", | 	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 = { | module.exports = { | ||||||
| 	mode: "production", | 	mode: "production", | ||||||
| 	entry: "./index", | 	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 = { | module.exports = { | ||||||
| 	mode: "production", | 	mode: "production", | ||||||
| 	entry: "./index", | 	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 = { | module.exports = { | ||||||
| 	mode: "production", | 	mode: "production", | ||||||
| 	entry: "./index", | 	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 = { | module.exports = { | ||||||
| 	mode: "production", | 	mode: "production", | ||||||
| 	entry: "./index", | 	entry: "./index", | ||||||
| 	profile: true, | 	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== |   integrity sha512-MeatbbUsZ80BEsKPXby6pUZjUM9ZuHIpWElN0siopih3fvnlpX2O9L6D5+dzDIb36lf9tM/8U4PVdLQ+L4qr4A== | ||||||
| 
 | 
 | ||||||
| "@types/node@^10.12.21": | "@types/node@^10.12.21": | ||||||
|   version "10.14.12" |   version "10.14.13" | ||||||
|   resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.12.tgz#0eec3155a46e6c4db1f27c3e588a205f767d622f" |   resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.13.tgz#ac786d623860adf39a3f51d629480aacd6a6eec7" | ||||||
|   integrity sha512-QcAKpaO6nhHLlxWBvpc4WeLrTvPqlHOvaj0s5GriKkA1zq+bsFBPpfYCvQhLqLgYlIko8A9YrPdaMHCo5mBcpg== |   integrity sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ== | ||||||
| 
 | 
 | ||||||
| "@types/prettier@^1.16.1": | "@types/prettier@^1.16.1": | ||||||
|   version "1.16.1" |   version "1.16.1" | ||||||
|  | @ -609,9 +609,9 @@ acorn@^5.5.3: | ||||||
|   integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== |   integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== | ||||||
| 
 | 
 | ||||||
| acorn@^6.0.1, acorn@^6.0.7, acorn@^6.2.0: | acorn@^6.0.1, acorn@^6.0.7, acorn@^6.2.0: | ||||||
|   version "6.2.0" |   version "6.2.1" | ||||||
|   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.0.tgz#67f0da2fc339d6cfb5d6fb244fd449f33cd8bbe3" |   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51" | ||||||
|   integrity sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw== |   integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q== | ||||||
| 
 | 
 | ||||||
| ajv-errors@^1.0.0: | ajv-errors@^1.0.0: | ||||||
|   version "1.0.1" |   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" |   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" | ||||||
|   integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== |   integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== | ||||||
| 
 | 
 | ||||||
| comment-parser@^0.5.5: | comment-parser@^0.6.0: | ||||||
|   version "0.5.5" |   version "0.6.1" | ||||||
|   resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.5.5.tgz#c2584cae7c2f0afc773e96b2ee98f8c10cbd693d" |   resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.6.1.tgz#88040c7c0a57c62e64962c3e888518620a42e7c9" | ||||||
|   integrity sha512-oB3TinFT+PV3p8UwDQt71+HkG03+zwPwikDlKU6ZDmql6QX2zFlQ+G0GGSDqyJhdZi4PSlzFBm+YJ+ebOX3Vgw== |   integrity sha512-Putzd7Ilyvknmb1KxGf5el9uw0sPx9gEVnDrm8tlvXGN1i8Uaa2VBxB32hUhfzTlrEhhxNQ+pKq4ZNe8wNxjmw== | ||||||
| 
 | 
 | ||||||
| commondir@^1.0.1: | commondir@^1.0.1: | ||||||
|   version "1.0.1" |   version "1.0.1" | ||||||
|  | @ -1841,16 +1841,16 @@ eslint-plugin-es@^1.3.1: | ||||||
|     regexpp "^2.0.1" |     regexpp "^2.0.1" | ||||||
| 
 | 
 | ||||||
| eslint-plugin-jest@^22.2.2: | eslint-plugin-jest@^22.2.2: | ||||||
|   version "22.8.0" |   version "22.13.0" | ||||||
|   resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.8.0.tgz#242ef5459e8da25d2c41438e95eb546e03d7fae1" |   resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.13.0.tgz#d7d134c6e3c2f67cc50f5fa89a329db579d28428" | ||||||
|   integrity sha512-2VftZMfILmlhL3VMq5ptHRIuyyXb3ShDEDb1J1UjvWNzm4l+UK/YmwNuTuJcM0gv8pJuOfiR/8ZptJ8Ou68pFw== |   integrity sha512-bIr8LL7buUXS8Pk69SFgaDKgyvPQkDu6i8ko0lP54uccszlo4EOwtstDXOZl5Af3JwudbECxRUbCpL/2cKDkkg== | ||||||
| 
 | 
 | ||||||
| eslint-plugin-jsdoc@^15.3.2: | eslint-plugin-jsdoc@^15.3.2: | ||||||
|   version "15.5.2" |   version "15.5.3" | ||||||
|   resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-15.5.2.tgz#89768320c64ec2f30d12209e1926c4decca0568a" |   resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-15.5.3.tgz#44e408e3bf2f60f3ad18dc829f9b9a1e34f33154" | ||||||
|   integrity sha512-5s39RYGaqugWVoOfc6pAwj9yeNh7mclygBWTyYVJX+sGiNchwCtgHbn2AjeonOw0g168CPI3itiXetHj2Yo8gg== |   integrity sha512-lw8wYa1UFV53JLoqKOQR8YBkKlE/aguR+HGyytL9VKsVvm83DK8ReYnNNDRKik3MF661cGuaUuGfIEcdqg9l4A== | ||||||
|   dependencies: |   dependencies: | ||||||
|     comment-parser "^0.5.5" |     comment-parser "^0.6.0" | ||||||
|     debug "^4.1.1" |     debug "^4.1.1" | ||||||
|     flat-map-polyfill "^0.3.8" |     flat-map-polyfill "^0.3.8" | ||||||
|     jsdoctypeparser "5.0.1" |     jsdoctypeparser "5.0.1" | ||||||
|  | @ -3835,9 +3835,9 @@ lodash.sortby@^4.7.0: | ||||||
|   integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= |   integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= | ||||||
| 
 | 
 | ||||||
| lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.4: | lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.4: | ||||||
|   version "4.17.14" |   version "4.17.15" | ||||||
|   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" |   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" | ||||||
|   integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== |   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== | ||||||
| 
 | 
 | ||||||
| log-driver@^1.2.7: | log-driver@^1.2.7: | ||||||
|   version "1.2.7" |   version "1.2.7" | ||||||
|  | @ -5500,9 +5500,9 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: | ||||||
|   integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= |   integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= | ||||||
| 
 | 
 | ||||||
| simple-git@^1.65.0, simple-git@^1.85.0: | simple-git@^1.65.0, simple-git@^1.85.0: | ||||||
|   version "1.121.0" |   version "1.122.0" | ||||||
|   resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.121.0.tgz#4bdf0828cd1b0bb3cb7ed9bead2771982ef5876a" |   resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.122.0.tgz#33b2d3a760aa02df470c79fbab5413d4f4e68945" | ||||||
|   integrity sha512-LyYri/nuAX8+cx9nZw38mWO6oHNi//CmiPlkBL7aVjZIsdldve7eeDwXu9L4wP/74MpNHucXkXc/BOuIQShhPg== |   integrity sha512-plTwhnkIHrw2TFMJbJH/mKwWGgFbj03V9wcfBKa4FsuvgJbpwdlSJnlvkIQWDV1CVLaf2Gl6zSNeRRnxBRhX1g== | ||||||
|   dependencies: |   dependencies: | ||||||
|     debug "^4.0.1" |     debug "^4.0.1" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue