From 2cdf0cb352ab6a2d0f8cb25120e4ebc92c5316e3 Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sun, 5 Nov 2023 17:23:37 +0800 Subject: removed autoprefix hover as it will have a high chance of making hover stopped working --- node_modules/webpack/lib/Compiler.js | 1234 ---------------------------------- 1 file changed, 1234 deletions(-) delete mode 100644 node_modules/webpack/lib/Compiler.js (limited to 'node_modules/webpack/lib/Compiler.js') diff --git a/node_modules/webpack/lib/Compiler.js b/node_modules/webpack/lib/Compiler.js deleted file mode 100644 index 7cc07486..00000000 --- a/node_modules/webpack/lib/Compiler.js +++ /dev/null @@ -1,1234 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const parseJson = require("json-parse-even-better-errors"); -const asyncLib = require("neo-async"); -const { - SyncHook, - SyncBailHook, - AsyncParallelHook, - AsyncSeriesHook -} = require("tapable"); -const { SizeOnlySource } = require("webpack-sources"); -const webpack = require("./"); -const Cache = require("./Cache"); -const CacheFacade = require("./CacheFacade"); -const ChunkGraph = require("./ChunkGraph"); -const Compilation = require("./Compilation"); -const ConcurrentCompilationError = require("./ConcurrentCompilationError"); -const ContextModuleFactory = require("./ContextModuleFactory"); -const ModuleGraph = require("./ModuleGraph"); -const NormalModuleFactory = require("./NormalModuleFactory"); -const RequestShortener = require("./RequestShortener"); -const ResolverFactory = require("./ResolverFactory"); -const Stats = require("./Stats"); -const Watching = require("./Watching"); -const WebpackError = require("./WebpackError"); -const { Logger } = require("./logging/Logger"); -const { join, dirname, mkdirp } = require("./util/fs"); -const { makePathsRelative } = require("./util/identifier"); -const { isSourceEqual } = require("./util/source"); - -/** @typedef {import("webpack-sources").Source} Source */ -/** @typedef {import("../declarations/WebpackOptions").EntryNormalized} Entry */ -/** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */ -/** @typedef {import("../declarations/WebpackOptions").WatchOptions} WatchOptions */ -/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */ -/** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */ -/** @typedef {import("./Chunk")} Chunk */ -/** @typedef {import("./Dependency")} Dependency */ -/** @typedef {import("./FileSystemInfo").FileSystemInfoEntry} FileSystemInfoEntry */ -/** @typedef {import("./Module")} Module */ -/** @typedef {import("./util/WeakTupleMap")} WeakTupleMap */ -/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ -/** @typedef {import("./util/fs").IntermediateFileSystem} IntermediateFileSystem */ -/** @typedef {import("./util/fs").OutputFileSystem} OutputFileSystem */ -/** @typedef {import("./util/fs").WatchFileSystem} WatchFileSystem */ - -/** - * @typedef {Object} CompilationParams - * @property {NormalModuleFactory} normalModuleFactory - * @property {ContextModuleFactory} contextModuleFactory - */ - -/** - * @template T - * @callback Callback - * @param {(Error | null)=} err - * @param {T=} result - */ - -/** - * @callback RunAsChildCallback - * @param {(Error | null)=} err - * @param {Chunk[]=} entries - * @param {Compilation=} compilation - */ - -/** - * @typedef {Object} AssetEmittedInfo - * @property {Buffer} content - * @property {Source} source - * @property {Compilation} compilation - * @property {string} outputPath - * @property {string} targetPath - */ - -/** - * @param {string[]} array an array - * @returns {boolean} true, if the array is sorted - */ -const isSorted = array => { - for (let i = 1; i < array.length; i++) { - if (array[i - 1] > array[i]) return false; - } - return true; -}; - -/** - * @param {Object} obj an object - * @param {string[]} keys the keys of the object - * @returns {Object} the object with properties sorted by property name - */ -const sortObject = (obj, keys) => { - const o = {}; - for (const k of keys.sort()) { - o[k] = obj[k]; - } - return o; -}; - -/** - * @param {string} filename filename - * @param {string | string[] | undefined} hashes list of hashes - * @returns {boolean} true, if the filename contains any hash - */ -const includesHash = (filename, hashes) => { - if (!hashes) return false; - if (Array.isArray(hashes)) { - return hashes.some(hash => filename.includes(hash)); - } else { - return filename.includes(hashes); - } -}; - -class Compiler { - /** - * @param {string} context the compilation path - * @param {WebpackOptions} options options - */ - constructor(context, options = /** @type {WebpackOptions} */ ({})) { - this.hooks = Object.freeze({ - /** @type {SyncHook<[]>} */ - initialize: new SyncHook([]), - - /** @type {SyncBailHook<[Compilation], boolean | undefined>} */ - shouldEmit: new SyncBailHook(["compilation"]), - /** @type {AsyncSeriesHook<[Stats]>} */ - done: new AsyncSeriesHook(["stats"]), - /** @type {SyncHook<[Stats]>} */ - afterDone: new SyncHook(["stats"]), - /** @type {AsyncSeriesHook<[]>} */ - additionalPass: new AsyncSeriesHook([]), - /** @type {AsyncSeriesHook<[Compiler]>} */ - beforeRun: new AsyncSeriesHook(["compiler"]), - /** @type {AsyncSeriesHook<[Compiler]>} */ - run: new AsyncSeriesHook(["compiler"]), - /** @type {AsyncSeriesHook<[Compilation]>} */ - emit: new AsyncSeriesHook(["compilation"]), - /** @type {AsyncSeriesHook<[string, AssetEmittedInfo]>} */ - assetEmitted: new AsyncSeriesHook(["file", "info"]), - /** @type {AsyncSeriesHook<[Compilation]>} */ - afterEmit: new AsyncSeriesHook(["compilation"]), - - /** @type {SyncHook<[Compilation, CompilationParams]>} */ - thisCompilation: new SyncHook(["compilation", "params"]), - /** @type {SyncHook<[Compilation, CompilationParams]>} */ - compilation: new SyncHook(["compilation", "params"]), - /** @type {SyncHook<[NormalModuleFactory]>} */ - normalModuleFactory: new SyncHook(["normalModuleFactory"]), - /** @type {SyncHook<[ContextModuleFactory]>} */ - contextModuleFactory: new SyncHook(["contextModuleFactory"]), - - /** @type {AsyncSeriesHook<[CompilationParams]>} */ - beforeCompile: new AsyncSeriesHook(["params"]), - /** @type {SyncHook<[CompilationParams]>} */ - compile: new SyncHook(["params"]), - /** @type {AsyncParallelHook<[Compilation]>} */ - make: new AsyncParallelHook(["compilation"]), - /** @type {AsyncParallelHook<[Compilation]>} */ - finishMake: new AsyncSeriesHook(["compilation"]), - /** @type {AsyncSeriesHook<[Compilation]>} */ - afterCompile: new AsyncSeriesHook(["compilation"]), - - /** @type {AsyncSeriesHook<[]>} */ - readRecords: new AsyncSeriesHook([]), - /** @type {AsyncSeriesHook<[]>} */ - emitRecords: new AsyncSeriesHook([]), - - /** @type {AsyncSeriesHook<[Compiler]>} */ - watchRun: new AsyncSeriesHook(["compiler"]), - /** @type {SyncHook<[Error]>} */ - failed: new SyncHook(["error"]), - /** @type {SyncHook<[string | null, number]>} */ - invalid: new SyncHook(["filename", "changeTime"]), - /** @type {SyncHook<[]>} */ - watchClose: new SyncHook([]), - /** @type {AsyncSeriesHook<[]>} */ - shutdown: new AsyncSeriesHook([]), - - /** @type {SyncBailHook<[string, string, any[]], true>} */ - infrastructureLog: new SyncBailHook(["origin", "type", "args"]), - - // TODO the following hooks are weirdly located here - // TODO move them for webpack 5 - /** @type {SyncHook<[]>} */ - environment: new SyncHook([]), - /** @type {SyncHook<[]>} */ - afterEnvironment: new SyncHook([]), - /** @type {SyncHook<[Compiler]>} */ - afterPlugins: new SyncHook(["compiler"]), - /** @type {SyncHook<[Compiler]>} */ - afterResolvers: new SyncHook(["compiler"]), - /** @type {SyncBailHook<[string, Entry], boolean>} */ - entryOption: new SyncBailHook(["context", "entry"]) - }); - - this.webpack = webpack; - - /** @type {string=} */ - this.name = undefined; - /** @type {Compilation=} */ - this.parentCompilation = undefined; - /** @type {Compiler} */ - this.root = this; - /** @type {string} */ - this.outputPath = ""; - /** @type {Watching | undefined} */ - this.watching = undefined; - - /** @type {OutputFileSystem} */ - this.outputFileSystem = null; - /** @type {IntermediateFileSystem} */ - this.intermediateFileSystem = null; - /** @type {InputFileSystem} */ - this.inputFileSystem = null; - /** @type {WatchFileSystem} */ - this.watchFileSystem = null; - - /** @type {string|null} */ - this.recordsInputPath = null; - /** @type {string|null} */ - this.recordsOutputPath = null; - this.records = {}; - /** @type {Set} */ - this.managedPaths = new Set(); - /** @type {Set} */ - this.immutablePaths = new Set(); - - /** @type {ReadonlySet | undefined} */ - this.modifiedFiles = undefined; - /** @type {ReadonlySet | undefined} */ - this.removedFiles = undefined; - /** @type {ReadonlyMap | undefined} */ - this.fileTimestamps = undefined; - /** @type {ReadonlyMap | undefined} */ - this.contextTimestamps = undefined; - /** @type {number | undefined} */ - this.fsStartTime = undefined; - - /** @type {ResolverFactory} */ - this.resolverFactory = new ResolverFactory(); - - this.infrastructureLogger = undefined; - - this.options = options; - - this.context = context; - - this.requestShortener = new RequestShortener(context, this.root); - - this.cache = new Cache(); - - /** @type {Map, memCache: WeakTupleMap }> | undefined} */ - this.moduleMemCaches = undefined; - - this.compilerPath = ""; - - /** @type {boolean} */ - this.running = false; - - /** @type {boolean} */ - this.idle = false; - - /** @type {boolean} */ - this.watchMode = false; - - this._backCompat = this.options.experiments.backCompat !== false; - - /** @type {Compilation} */ - this._lastCompilation = undefined; - /** @type {NormalModuleFactory} */ - this._lastNormalModuleFactory = undefined; - - /** @private @type {WeakMap }>} */ - this._assetEmittingSourceCache = new WeakMap(); - /** @private @type {Map} */ - this._assetEmittingWrittenFiles = new Map(); - /** @private @type {Set} */ - this._assetEmittingPreviousFiles = new Set(); - } - - /** - * @param {string} name cache name - * @returns {CacheFacade} the cache facade instance - */ - getCache(name) { - return new CacheFacade( - this.cache, - `${this.compilerPath}${name}`, - this.options.output.hashFunction - ); - } - - /** - * @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); - } - } - }, - childName => { - if (typeof name === "function") { - if (typeof childName === "function") { - return this.getInfrastructureLogger(() => { - if (typeof name === "function") { - name = name(); - if (!name) { - throw new TypeError( - "Compiler.getInfrastructureLogger(name) called with a function not returning a name" - ); - } - } - if (typeof childName === "function") { - childName = childName(); - if (!childName) { - throw new TypeError( - "Logger.getChildLogger(name) called with a function not returning a name" - ); - } - } - return `${name}/${childName}`; - }); - } else { - return this.getInfrastructureLogger(() => { - if (typeof name === "function") { - name = name(); - if (!name) { - throw new TypeError( - "Compiler.getInfrastructureLogger(name) called with a function not returning a name" - ); - } - } - return `${name}/${childName}`; - }); - } - } else { - if (typeof childName === "function") { - return this.getInfrastructureLogger(() => { - if (typeof childName === "function") { - childName = childName(); - if (!childName) { - throw new TypeError( - "Logger.getChildLogger(name) called with a function not returning a name" - ); - } - } - return `${name}/${childName}`; - }); - } else { - return this.getInfrastructureLogger(`${name}/${childName}`); - } - } - } - ); - } - - // TODO webpack 6: solve this in a better way - // e.g. move compilation specific info from Modules into ModuleGraph - _cleanupLastCompilation() { - if (this._lastCompilation !== undefined) { - for (const module of this._lastCompilation.modules) { - ChunkGraph.clearChunkGraphForModule(module); - ModuleGraph.clearModuleGraphForModule(module); - module.cleanupForCache(); - } - for (const chunk of this._lastCompilation.chunks) { - ChunkGraph.clearChunkGraphForChunk(chunk); - } - this._lastCompilation = undefined; - } - } - - // TODO webpack 6: solve this in a better way - _cleanupLastNormalModuleFactory() { - if (this._lastNormalModuleFactory !== undefined) { - this._lastNormalModuleFactory.cleanupForCache(); - this._lastNormalModuleFactory = undefined; - } - } - - /** - * @param {WatchOptions} watchOptions the watcher's options - * @param {Callback} handler signals when the call finishes - * @returns {Watching} a compiler watcher - */ - watch(watchOptions, handler) { - if (this.running) { - return handler(new ConcurrentCompilationError()); - } - - this.running = true; - this.watchMode = true; - this.watching = new Watching(this, watchOptions, handler); - return this.watching; - } - - /** - * @param {Callback} callback signals when the call finishes - * @returns {void} - */ - run(callback) { - if (this.running) { - return callback(new ConcurrentCompilationError()); - } - - let logger; - - const finalCallback = (err, stats) => { - if (logger) logger.time("beginIdle"); - this.idle = true; - this.cache.beginIdle(); - this.idle = true; - if (logger) logger.timeEnd("beginIdle"); - this.running = false; - if (err) { - this.hooks.failed.call(err); - } - if (callback !== undefined) callback(err, stats); - this.hooks.afterDone.call(stats); - }; - - const startTime = Date.now(); - - this.running = true; - - const onCompiled = (err, compilation) => { - if (err) return finalCallback(err); - - if (this.hooks.shouldEmit.call(compilation) === false) { - compilation.startTime = startTime; - compilation.endTime = Date.now(); - const stats = new Stats(compilation); - this.hooks.done.callAsync(stats, err => { - if (err) return finalCallback(err); - return finalCallback(null, stats); - }); - return; - } - - process.nextTick(() => { - logger = compilation.getLogger("webpack.Compiler"); - logger.time("emitAssets"); - this.emitAssets(compilation, err => { - logger.timeEnd("emitAssets"); - if (err) return finalCallback(err); - - if (compilation.hooks.needAdditionalPass.call()) { - compilation.needAdditionalPass = true; - - compilation.startTime = startTime; - compilation.endTime = Date.now(); - logger.time("done hook"); - const stats = new Stats(compilation); - this.hooks.done.callAsync(stats, err => { - logger.timeEnd("done hook"); - if (err) return finalCallback(err); - - this.hooks.additionalPass.callAsync(err => { - if (err) return finalCallback(err); - this.compile(onCompiled); - }); - }); - return; - } - - logger.time("emitRecords"); - this.emitRecords(err => { - logger.timeEnd("emitRecords"); - if (err) return finalCallback(err); - - compilation.startTime = startTime; - compilation.endTime = Date.now(); - logger.time("done hook"); - const stats = new Stats(compilation); - this.hooks.done.callAsync(stats, err => { - logger.timeEnd("done hook"); - if (err) return finalCallback(err); - this.cache.storeBuildDependencies( - compilation.buildDependencies, - err => { - if (err) return finalCallback(err); - return finalCallback(null, stats); - } - ); - }); - }); - }); - }); - }; - - const run = () => { - this.hooks.beforeRun.callAsync(this, err => { - if (err) return finalCallback(err); - - this.hooks.run.callAsync(this, err => { - if (err) return finalCallback(err); - - this.readRecords(err => { - if (err) return finalCallback(err); - - this.compile(onCompiled); - }); - }); - }); - }; - - if (this.idle) { - this.cache.endIdle(err => { - if (err) return finalCallback(err); - - this.idle = false; - run(); - }); - } else { - run(); - } - } - - /** - * @param {RunAsChildCallback} callback signals when the call finishes - * @returns {void} - */ - runAsChild(callback) { - const startTime = Date.now(); - - const finalCallback = (err, entries, compilation) => { - try { - callback(err, entries, compilation); - } catch (e) { - const err = new WebpackError( - `compiler.runAsChild callback error: ${e}` - ); - err.details = e.stack; - this.parentCompilation.errors.push(err); - } - }; - - this.compile((err, compilation) => { - if (err) return finalCallback(err); - - this.parentCompilation.children.push(compilation); - for (const { name, source, info } of compilation.getAssets()) { - this.parentCompilation.emitAsset(name, source, info); - } - - const entries = []; - for (const ep of compilation.entrypoints.values()) { - entries.push(...ep.chunks); - } - - compilation.startTime = startTime; - compilation.endTime = Date.now(); - - return finalCallback(null, entries, compilation); - }); - } - - purgeInputFileSystem() { - if (this.inputFileSystem && this.inputFileSystem.purge) { - this.inputFileSystem.purge(); - } - } - - /** - * @param {Compilation} compilation the compilation - * @param {Callback} callback signals when the assets are emitted - * @returns {void} - */ - emitAssets(compilation, callback) { - let outputPath; - - const emitFiles = err => { - if (err) return callback(err); - - const assets = compilation.getAssets(); - compilation.assets = { ...compilation.assets }; - /** @type {Map} */ - const caseInsensitiveMap = new Map(); - /** @type {Set} */ - const allTargetPaths = new Set(); - asyncLib.forEachLimit( - assets, - 15, - ({ name: file, source, info }, callback) => { - let targetFile = file; - let immutable = info.immutable; - const queryStringIdx = targetFile.indexOf("?"); - if (queryStringIdx >= 0) { - targetFile = targetFile.slice(0, queryStringIdx); - // We may remove the hash, which is in the query string - // So we recheck if the file is immutable - // This doesn't cover all cases, but immutable is only a performance optimization anyway - immutable = - immutable && - (includesHash(targetFile, info.contenthash) || - includesHash(targetFile, info.chunkhash) || - includesHash(targetFile, info.modulehash) || - includesHash(targetFile, info.fullhash)); - } - - const writeOut = err => { - if (err) return callback(err); - const targetPath = join( - this.outputFileSystem, - outputPath, - targetFile - ); - allTargetPaths.add(targetPath); - - // check if the target file has already been written by this Compiler - const targetFileGeneration = - this._assetEmittingWrittenFiles.get(targetPath); - - // create an cache entry for this Source if not already existing - let cacheEntry = this._assetEmittingSourceCache.get(source); - if (cacheEntry === undefined) { - cacheEntry = { - sizeOnlySource: undefined, - writtenTo: new Map() - }; - this._assetEmittingSourceCache.set(source, cacheEntry); - } - - let similarEntry; - - const checkSimilarFile = () => { - const caseInsensitiveTargetPath = targetPath.toLowerCase(); - similarEntry = caseInsensitiveMap.get(caseInsensitiveTargetPath); - if (similarEntry !== undefined) { - const { path: other, source: otherSource } = similarEntry; - if (isSourceEqual(otherSource, source)) { - // Size may or may not be available at this point. - // If it's not available add to "waiting" list and it will be updated once available - if (similarEntry.size !== undefined) { - updateWithReplacementSource(similarEntry.size); - } else { - if (!similarEntry.waiting) similarEntry.waiting = []; - similarEntry.waiting.push({ file, cacheEntry }); - } - alreadyWritten(); - } else { - const err = - new WebpackError(`Prevent writing to file that only differs in casing or query string from already written file. -This will lead to a race-condition and corrupted files on case-insensitive file systems. -${targetPath} -${other}`); - err.file = file; - callback(err); - } - return true; - } else { - caseInsensitiveMap.set( - caseInsensitiveTargetPath, - (similarEntry = { - path: targetPath, - source, - size: undefined, - waiting: undefined - }) - ); - return false; - } - }; - - /** - * get the binary (Buffer) content from the Source - * @returns {Buffer} content for the source - */ - const getContent = () => { - if (typeof source.buffer === "function") { - return source.buffer(); - } else { - const bufferOrString = source.source(); - if (Buffer.isBuffer(bufferOrString)) { - return bufferOrString; - } else { - return Buffer.from(bufferOrString, "utf8"); - } - } - }; - - const alreadyWritten = () => { - // cache the information that the Source has been already been written to that location - if (targetFileGeneration === undefined) { - const newGeneration = 1; - this._assetEmittingWrittenFiles.set(targetPath, newGeneration); - cacheEntry.writtenTo.set(targetPath, newGeneration); - } else { - cacheEntry.writtenTo.set(targetPath, targetFileGeneration); - } - callback(); - }; - - /** - * Write the file to output file system - * @param {Buffer} content content to be written - * @returns {void} - */ - const doWrite = content => { - this.outputFileSystem.writeFile(targetPath, content, err => { - if (err) return callback(err); - - // information marker that the asset has been emitted - compilation.emittedAssets.add(file); - - // cache the information that the Source has been written to that location - const newGeneration = - targetFileGeneration === undefined - ? 1 - : targetFileGeneration + 1; - cacheEntry.writtenTo.set(targetPath, newGeneration); - this._assetEmittingWrittenFiles.set(targetPath, newGeneration); - this.hooks.assetEmitted.callAsync( - file, - { - content, - source, - outputPath, - compilation, - targetPath - }, - callback - ); - }); - }; - - const updateWithReplacementSource = size => { - updateFileWithReplacementSource(file, cacheEntry, size); - similarEntry.size = size; - if (similarEntry.waiting !== undefined) { - for (const { file, cacheEntry } of similarEntry.waiting) { - updateFileWithReplacementSource(file, cacheEntry, size); - } - } - }; - - const updateFileWithReplacementSource = ( - file, - cacheEntry, - size - ) => { - // Create a replacement resource which only allows to ask for size - // This allows to GC all memory allocated by the Source - // (expect when the Source is stored in any other cache) - if (!cacheEntry.sizeOnlySource) { - cacheEntry.sizeOnlySource = new SizeOnlySource(size); - } - compilation.updateAsset(file, cacheEntry.sizeOnlySource, { - size - }); - }; - - const processExistingFile = stats => { - // skip emitting if it's already there and an immutable file - if (immutable) { - updateWithReplacementSource(stats.size); - return alreadyWritten(); - } - - const content = getContent(); - - updateWithReplacementSource(content.length); - - // if it exists and content on disk matches content - // skip writing the same content again - // (to keep mtime and don't trigger watchers) - // for a fast negative match file size is compared first - if (content.length === stats.size) { - compilation.comparedForEmitAssets.add(file); - return this.outputFileSystem.readFile( - targetPath, - (err, existingContent) => { - if ( - err || - !content.equals(/** @type {Buffer} */ (existingContent)) - ) { - return doWrite(content); - } else { - return alreadyWritten(); - } - } - ); - } - - return doWrite(content); - }; - - const processMissingFile = () => { - const content = getContent(); - - updateWithReplacementSource(content.length); - - return doWrite(content); - }; - - // if the target file has already been written - if (targetFileGeneration !== undefined) { - // check if the Source has been written to this target file - const writtenGeneration = cacheEntry.writtenTo.get(targetPath); - if (writtenGeneration === targetFileGeneration) { - // if yes, we may skip writing the file - // if it's already there - // (we assume one doesn't modify files while the Compiler is running, other then removing them) - - if (this._assetEmittingPreviousFiles.has(targetPath)) { - // We assume that assets from the last compilation say intact on disk (they are not removed) - compilation.updateAsset(file, cacheEntry.sizeOnlySource, { - size: cacheEntry.sizeOnlySource.size() - }); - - return callback(); - } else { - // Settings immutable will make it accept file content without comparing when file exist - immutable = true; - } - } else if (!immutable) { - if (checkSimilarFile()) return; - // We wrote to this file before which has very likely a different content - // skip comparing and assume content is different for performance - // This case happens often during watch mode. - return processMissingFile(); - } - } - - if (checkSimilarFile()) return; - if (this.options.output.compareBeforeEmit) { - this.outputFileSystem.stat(targetPath, (err, stats) => { - const exists = !err && stats.isFile(); - - if (exists) { - processExistingFile(stats); - } else { - processMissingFile(); - } - }); - } else { - processMissingFile(); - } - }; - - if (targetFile.match(/\/|\\/)) { - const fs = this.outputFileSystem; - const dir = dirname(fs, join(fs, outputPath, targetFile)); - mkdirp(fs, dir, writeOut); - } else { - writeOut(); - } - }, - err => { - // Clear map to free up memory - caseInsensitiveMap.clear(); - if (err) { - this._assetEmittingPreviousFiles.clear(); - return callback(err); - } - - this._assetEmittingPreviousFiles = allTargetPaths; - - this.hooks.afterEmit.callAsync(compilation, err => { - if (err) return callback(err); - - return callback(); - }); - } - ); - }; - - this.hooks.emit.callAsync(compilation, err => { - if (err) return callback(err); - outputPath = compilation.getPath(this.outputPath, {}); - mkdirp(this.outputFileSystem, outputPath, emitFiles); - }); - } - - /** - * @param {Callback} callback signals when the call finishes - * @returns {void} - */ - emitRecords(callback) { - if (this.hooks.emitRecords.isUsed()) { - if (this.recordsOutputPath) { - asyncLib.parallel( - [ - cb => this.hooks.emitRecords.callAsync(cb), - this._emitRecords.bind(this) - ], - err => callback(err) - ); - } else { - this.hooks.emitRecords.callAsync(callback); - } - } else { - if (this.recordsOutputPath) { - this._emitRecords(callback); - } else { - callback(); - } - } - } - - /** - * @param {Callback} callback signals when the call finishes - * @returns {void} - */ - _emitRecords(callback) { - const writeFile = () => { - this.outputFileSystem.writeFile( - this.recordsOutputPath, - JSON.stringify( - this.records, - (n, value) => { - if ( - typeof value === "object" && - value !== null && - !Array.isArray(value) - ) { - const keys = Object.keys(value); - if (!isSorted(keys)) { - return sortObject(value, keys); - } - } - return value; - }, - 2 - ), - callback - ); - }; - - const recordsOutputPathDirectory = dirname( - this.outputFileSystem, - this.recordsOutputPath - ); - if (!recordsOutputPathDirectory) { - return writeFile(); - } - mkdirp(this.outputFileSystem, recordsOutputPathDirectory, err => { - if (err) return callback(err); - writeFile(); - }); - } - - /** - * @param {Callback} callback signals when the call finishes - * @returns {void} - */ - readRecords(callback) { - if (this.hooks.readRecords.isUsed()) { - if (this.recordsInputPath) { - asyncLib.parallel( - [ - cb => this.hooks.readRecords.callAsync(cb), - this._readRecords.bind(this) - ], - err => callback(err) - ); - } else { - this.records = {}; - this.hooks.readRecords.callAsync(callback); - } - } else { - if (this.recordsInputPath) { - this._readRecords(callback); - } else { - this.records = {}; - callback(); - } - } - } - - /** - * @param {Callback} callback signals when the call finishes - * @returns {void} - */ - _readRecords(callback) { - if (!this.recordsInputPath) { - this.records = {}; - return callback(); - } - this.inputFileSystem.stat(this.recordsInputPath, err => { - // It doesn't exist - // We can ignore this. - if (err) return callback(); - - this.inputFileSystem.readFile(this.recordsInputPath, (err, content) => { - if (err) return callback(err); - - try { - this.records = parseJson(content.toString("utf-8")); - } catch (e) { - return callback(new Error(`Cannot parse records: ${e.message}`)); - } - - return callback(); - }); - }); - } - - /** - * @param {Compilation} compilation the compilation - * @param {string} compilerName the compiler's name - * @param {number} compilerIndex the compiler's index - * @param {OutputOptions=} outputOptions the output options - * @param {WebpackPluginInstance[]=} plugins the plugins to apply - * @returns {Compiler} a child compiler - */ - createChildCompiler( - compilation, - compilerName, - compilerIndex, - outputOptions, - plugins - ) { - const childCompiler = new Compiler(this.context, { - ...this.options, - output: { - ...this.options.output, - ...outputOptions - } - }); - childCompiler.name = compilerName; - childCompiler.outputPath = this.outputPath; - childCompiler.inputFileSystem = this.inputFileSystem; - childCompiler.outputFileSystem = null; - childCompiler.resolverFactory = this.resolverFactory; - childCompiler.modifiedFiles = this.modifiedFiles; - childCompiler.removedFiles = this.removedFiles; - childCompiler.fileTimestamps = this.fileTimestamps; - childCompiler.contextTimestamps = this.contextTimestamps; - childCompiler.fsStartTime = this.fsStartTime; - childCompiler.cache = this.cache; - childCompiler.compilerPath = `${this.compilerPath}${compilerName}|${compilerIndex}|`; - childCompiler._backCompat = this._backCompat; - - const relativeCompilerName = makePathsRelative( - this.context, - compilerName, - this.root - ); - if (!this.records[relativeCompilerName]) { - this.records[relativeCompilerName] = []; - } - if (this.records[relativeCompilerName][compilerIndex]) { - childCompiler.records = this.records[relativeCompilerName][compilerIndex]; - } else { - this.records[relativeCompilerName].push((childCompiler.records = {})); - } - - childCompiler.parentCompilation = compilation; - childCompiler.root = this.root; - if (Array.isArray(plugins)) { - for (const plugin of plugins) { - if (plugin) { - plugin.apply(childCompiler); - } - } - } - for (const name in this.hooks) { - if ( - ![ - "make", - "compile", - "emit", - "afterEmit", - "invalid", - "done", - "thisCompilation" - ].includes(name) - ) { - if (childCompiler.hooks[name]) { - childCompiler.hooks[name].taps = this.hooks[name].taps.slice(); - } - } - } - - compilation.hooks.childCompiler.call( - childCompiler, - compilerName, - compilerIndex - ); - - return childCompiler; - } - - isChild() { - return !!this.parentCompilation; - } - - createCompilation(params) { - this._cleanupLastCompilation(); - return (this._lastCompilation = new Compilation(this, params)); - } - - /** - * @param {CompilationParams} params the compilation parameters - * @returns {Compilation} the created compilation - */ - newCompilation(params) { - const compilation = this.createCompilation(params); - compilation.name = this.name; - compilation.records = this.records; - this.hooks.thisCompilation.call(compilation, params); - this.hooks.compilation.call(compilation, params); - return compilation; - } - - createNormalModuleFactory() { - this._cleanupLastNormalModuleFactory(); - const normalModuleFactory = new NormalModuleFactory({ - context: this.options.context, - fs: this.inputFileSystem, - resolverFactory: this.resolverFactory, - options: this.options.module, - associatedObjectForCache: this.root, - layers: this.options.experiments.layers - }); - this._lastNormalModuleFactory = normalModuleFactory; - this.hooks.normalModuleFactory.call(normalModuleFactory); - return normalModuleFactory; - } - - createContextModuleFactory() { - const contextModuleFactory = new ContextModuleFactory(this.resolverFactory); - this.hooks.contextModuleFactory.call(contextModuleFactory); - return contextModuleFactory; - } - - newCompilationParams() { - const params = { - normalModuleFactory: this.createNormalModuleFactory(), - contextModuleFactory: this.createContextModuleFactory() - }; - return params; - } - - /** - * @param {Callback} callback signals when the compilation finishes - * @returns {void} - */ - compile(callback) { - const params = this.newCompilationParams(); - this.hooks.beforeCompile.callAsync(params, err => { - if (err) return callback(err); - - this.hooks.compile.call(params); - - const compilation = this.newCompilation(params); - - const logger = compilation.getLogger("webpack.Compiler"); - - logger.time("make hook"); - this.hooks.make.callAsync(compilation, err => { - logger.timeEnd("make hook"); - if (err) return callback(err); - - logger.time("finish make hook"); - this.hooks.finishMake.callAsync(compilation, err => { - logger.timeEnd("finish make hook"); - if (err) return callback(err); - - process.nextTick(() => { - logger.time("finish compilation"); - compilation.finish(err => { - logger.timeEnd("finish compilation"); - if (err) return callback(err); - - logger.time("seal compilation"); - compilation.seal(err => { - logger.timeEnd("seal compilation"); - if (err) return callback(err); - - logger.time("afterCompile hook"); - this.hooks.afterCompile.callAsync(compilation, err => { - logger.timeEnd("afterCompile hook"); - if (err) return callback(err); - - return callback(null, compilation); - }); - }); - }); - }); - }); - }); - }); - } - - /** - * @param {Callback} callback signals when the compiler closes - * @returns {void} - */ - close(callback) { - if (this.watching) { - // When there is still an active watching, close this first - this.watching.close(err => { - this.close(callback); - }); - return; - } - this.hooks.shutdown.callAsync(err => { - if (err) return callback(err); - // Get rid of reference to last compilation to avoid leaking memory - // We can't run this._cleanupLastCompilation() as the Stats to this compilation - // might be still in use. We try to get rid of the reference to the cache instead. - this._lastCompilation = undefined; - this._lastNormalModuleFactory = undefined; - this.cache.shutdown(callback); - }); - } -} - -module.exports = Compiler; -- cgit v1.2.3