diff options
author | 2020-11-16 00:10:28 +0100 | |
---|---|---|
committer | 2020-11-16 00:10:28 +0100 | |
commit | e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d (patch) | |
tree | 55713f725f77b44ebfec86e4eec3ce33e71458ca /node_modules/webpack/lib/Compiler.js | |
download | website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.gz website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.bz2 website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.zip |
api, login, auth
Diffstat (limited to 'node_modules/webpack/lib/Compiler.js')
-rw-r--r-- | node_modules/webpack/lib/Compiler.js | 735 |
1 files changed, 735 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/Compiler.js b/node_modules/webpack/lib/Compiler.js new file mode 100644 index 0000000..376aa28 --- /dev/null +++ b/node_modules/webpack/lib/Compiler.js @@ -0,0 +1,735 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const parseJson = require("json-parse-better-errors"); +const asyncLib = require("neo-async"); +const path = require("path"); +const { Source } = require("webpack-sources"); +const util = require("util"); +const { + Tapable, + SyncHook, + SyncBailHook, + AsyncParallelHook, + AsyncSeriesHook +} = require("tapable"); + +const Compilation = require("./Compilation"); +const Stats = require("./Stats"); +const Watching = require("./Watching"); +const NormalModuleFactory = require("./NormalModuleFactory"); +const ContextModuleFactory = require("./ContextModuleFactory"); +const ResolverFactory = require("./ResolverFactory"); + +const RequestShortener = require("./RequestShortener"); +const { makePathsRelative } = require("./util/identifier"); +const ConcurrentCompilationError = require("./ConcurrentCompilationError"); +const { Logger } = require("./logging/Logger"); + +/** @typedef {import("../declarations/WebpackOptions").Entry} Entry */ +/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */ + +/** + * @typedef {Object} CompilationParams + * @property {NormalModuleFactory} normalModuleFactory + * @property {ContextModuleFactory} contextModuleFactory + * @property {Set<string>} compilationDependencies + */ + +class Compiler extends Tapable { + constructor(context) { + super(); + this.hooks = { + /** @type {SyncBailHook<Compilation>} */ + shouldEmit: new SyncBailHook(["compilation"]), + /** @type {AsyncSeriesHook<Stats>} */ + done: new AsyncSeriesHook(["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, Buffer>} */ + assetEmitted: new AsyncSeriesHook(["file", "content"]), + /** @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 {AsyncSeriesHook<Compilation>} */ + afterCompile: new AsyncSeriesHook(["compilation"]), + + /** @type {AsyncSeriesHook<Compiler>} */ + watchRun: new AsyncSeriesHook(["compiler"]), + /** @type {SyncHook<Error>} */ + failed: new SyncHook(["error"]), + /** @type {SyncHook<string, string>} */ + invalid: new SyncHook(["filename", "changeTime"]), + /** @type {SyncHook} */ + watchClose: new SyncHook([]), + + /** @type {SyncBailHook<string, string, any[]>} */ + 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>} */ + entryOption: new SyncBailHook(["context", "entry"]) + }; + // TODO webpack 5 remove this + this.hooks.infrastructurelog = this.hooks.infrastructureLog; + + this._pluginCompat.tap("Compiler", options => { + switch (options.name) { + case "additional-pass": + case "before-run": + case "run": + case "emit": + case "after-emit": + case "before-compile": + case "make": + case "after-compile": + case "watch-run": + options.async = true; + break; + } + }); + + /** @type {string=} */ + this.name = undefined; + /** @type {Compilation=} */ + this.parentCompilation = undefined; + /** @type {string} */ + this.outputPath = ""; + + this.outputFileSystem = null; + this.inputFileSystem = null; + + /** @type {string|null} */ + this.recordsInputPath = null; + /** @type {string|null} */ + this.recordsOutputPath = null; + this.records = {}; + this.removedFiles = new Set(); + /** @type {Map<string, number>} */ + this.fileTimestamps = new Map(); + /** @type {Map<string, number>} */ + this.contextTimestamps = new Map(); + /** @type {ResolverFactory} */ + this.resolverFactory = new ResolverFactory(); + + this.infrastructureLogger = undefined; + + // TODO remove in webpack 5 + this.resolvers = { + normal: { + plugins: util.deprecate((hook, fn) => { + this.resolverFactory.plugin("resolver normal", resolver => { + resolver.plugin(hook, fn); + }); + }, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.plugin(/* … */);\n}); instead.'), + apply: util.deprecate((...args) => { + this.resolverFactory.plugin("resolver normal", resolver => { + resolver.apply(...args); + }); + }, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.apply(/* … */);\n}); instead.') + }, + loader: { + plugins: util.deprecate((hook, fn) => { + this.resolverFactory.plugin("resolver loader", resolver => { + resolver.plugin(hook, fn); + }); + }, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.plugin(/* … */);\n}); instead.'), + apply: util.deprecate((...args) => { + this.resolverFactory.plugin("resolver loader", resolver => { + resolver.apply(...args); + }); + }, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.apply(/* … */);\n}); instead.') + }, + context: { + plugins: util.deprecate((hook, fn) => { + this.resolverFactory.plugin("resolver context", resolver => { + resolver.plugin(hook, fn); + }); + }, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.plugin(/* … */);\n}); instead.'), + apply: util.deprecate((...args) => { + this.resolverFactory.plugin("resolver context", resolver => { + resolver.apply(...args); + }); + }, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.apply(/* … */);\n}); instead.') + } + }; + + /** @type {WebpackOptions} */ + this.options = /** @type {WebpackOptions} */ ({}); + + this.context = context; + + this.requestShortener = new RequestShortener(context); + + /** @type {boolean} */ + this.running = false; + + /** @type {boolean} */ + this.watchMode = false; + + /** @private @type {WeakMap<Source, { sizeOnlySource: SizeOnlySource, writtenTo: Map<string, number> }>} */ + this._assetEmittingSourceCache = new WeakMap(); + /** @private @type {Map<string, number>} */ + 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); + } + } + }); + } + + watch(watchOptions, handler) { + if (this.running) return handler(new ConcurrentCompilationError()); + + this.running = true; + this.watchMode = true; + this.fileTimestamps = new Map(); + this.contextTimestamps = new Map(); + this.removedFiles = new Set(); + return new Watching(this, watchOptions, handler); + } + + run(callback) { + if (this.running) return callback(new ConcurrentCompilationError()); + + const finalCallback = (err, stats) => { + this.running = false; + + if (err) { + this.hooks.failed.call(err); + } + + if (callback !== undefined) return callback(err, stats); + }; + + const startTime = Date.now(); + + this.running = true; + + const onCompiled = (err, compilation) => { + if (err) return finalCallback(err); + + if (this.hooks.shouldEmit.call(compilation) === false) { + const stats = new Stats(compilation); + stats.startTime = startTime; + stats.endTime = Date.now(); + this.hooks.done.callAsync(stats, err => { + if (err) return finalCallback(err); + return finalCallback(null, stats); + }); + return; + } + + this.emitAssets(compilation, err => { + if (err) return finalCallback(err); + + if (compilation.hooks.needAdditionalPass.call()) { + compilation.needAdditionalPass = true; + + const stats = new Stats(compilation); + stats.startTime = startTime; + stats.endTime = Date.now(); + this.hooks.done.callAsync(stats, err => { + if (err) return finalCallback(err); + + this.hooks.additionalPass.callAsync(err => { + if (err) return finalCallback(err); + this.compile(onCompiled); + }); + }); + return; + } + + this.emitRecords(err => { + if (err) return finalCallback(err); + + const stats = new Stats(compilation); + stats.startTime = startTime; + stats.endTime = Date.now(); + this.hooks.done.callAsync(stats, err => { + if (err) return finalCallback(err); + return finalCallback(null, stats); + }); + }); + }); + }; + + 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); + }); + }); + }); + } + + runAsChild(callback) { + this.compile((err, compilation) => { + if (err) return callback(err); + + this.parentCompilation.children.push(compilation); + for (const { name, source, info } of compilation.getAssets()) { + this.parentCompilation.emitAsset(name, source, info); + } + + const entries = Array.from( + compilation.entrypoints.values(), + ep => ep.chunks + ).reduce((array, chunks) => { + return array.concat(chunks); + }, []); + + return callback(null, entries, compilation); + }); + } + + purgeInputFileSystem() { + if (this.inputFileSystem && this.inputFileSystem.purge) { + this.inputFileSystem.purge(); + } + } + + emitAssets(compilation, callback) { + let outputPath; + const emitFiles = err => { + if (err) return callback(err); + + asyncLib.forEachLimit( + compilation.getAssets(), + 15, + ({ name: file, source }, callback) => { + let targetFile = file; + const queryStringIdx = targetFile.indexOf("?"); + if (queryStringIdx >= 0) { + targetFile = targetFile.substr(0, queryStringIdx); + } + + const writeOut = err => { + if (err) return callback(err); + const targetPath = this.outputFileSystem.join( + outputPath, + targetFile + ); + // TODO webpack 5 remove futureEmitAssets option and make it on by default + if (this.options.output.futureEmitAssets) { + // 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); + } + + // 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 skip writing the file + // as it's already there + // (we assume one doesn't remove files while the Compiler is running) + + compilation.updateAsset(file, cacheEntry.sizeOnlySource, { + size: cacheEntry.sizeOnlySource.size() + }); + + return callback(); + } + } + + // TODO webpack 5: if info.immutable check if file already exists in output + // skip emitting if it's already there + + // get the binary (Buffer) content from the Source + /** @type {Buffer} */ + let content; + if (typeof source.buffer === "function") { + content = source.buffer(); + } else { + const bufferOrString = source.source(); + if (Buffer.isBuffer(bufferOrString)) { + content = bufferOrString; + } else { + content = Buffer.from(bufferOrString, "utf8"); + } + } + + // 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) + cacheEntry.sizeOnlySource = new SizeOnlySource(content.length); + compilation.updateAsset(file, cacheEntry.sizeOnlySource, { + size: content.length + }); + + // Write the file to output file system + 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, callback); + }); + } else { + if (source.existsAt === targetPath) { + source.emitted = false; + return callback(); + } + let content = source.source(); + + if (!Buffer.isBuffer(content)) { + content = Buffer.from(content, "utf8"); + } + + source.existsAt = targetPath; + source.emitted = true; + this.outputFileSystem.writeFile(targetPath, content, err => { + if (err) return callback(err); + this.hooks.assetEmitted.callAsync(file, content, callback); + }); + } + }; + + if (targetFile.match(/\/|\\/)) { + const dir = path.dirname(targetFile); + this.outputFileSystem.mkdirp( + this.outputFileSystem.join(outputPath, dir), + writeOut + ); + } else { + writeOut(); + } + }, + err => { + if (err) return callback(err); + + 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); + this.outputFileSystem.mkdirp(outputPath, emitFiles); + }); + } + + emitRecords(callback) { + if (!this.recordsOutputPath) return callback(); + const idx1 = this.recordsOutputPath.lastIndexOf("/"); + const idx2 = this.recordsOutputPath.lastIndexOf("\\"); + let recordsOutputPathDirectory = null; + if (idx1 > idx2) { + recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1); + } else if (idx1 < idx2) { + recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2); + } + + const writeFile = () => { + this.outputFileSystem.writeFile( + this.recordsOutputPath, + JSON.stringify(this.records, undefined, 2), + callback + ); + }; + + if (!recordsOutputPathDirectory) { + return writeFile(); + } + this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => { + if (err) return callback(err); + writeFile(); + }); + } + + 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) { + e.message = "Cannot parse records: " + e.message; + return callback(e); + } + + return callback(); + }); + }); + } + + createChildCompiler( + compilation, + compilerName, + compilerIndex, + outputOptions, + plugins + ) { + const childCompiler = new Compiler(this.context); + if (Array.isArray(plugins)) { + for (const plugin of plugins) { + 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(); + } + } + } + childCompiler.name = compilerName; + childCompiler.outputPath = this.outputPath; + childCompiler.inputFileSystem = this.inputFileSystem; + childCompiler.outputFileSystem = null; + childCompiler.resolverFactory = this.resolverFactory; + childCompiler.fileTimestamps = this.fileTimestamps; + childCompiler.contextTimestamps = this.contextTimestamps; + + const relativeCompilerName = makePathsRelative(this.context, compilerName); + 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.options = Object.create(this.options); + childCompiler.options.output = Object.create(childCompiler.options.output); + for (const name in outputOptions) { + childCompiler.options.output[name] = outputOptions[name]; + } + childCompiler.parentCompilation = compilation; + + compilation.hooks.childCompiler.call( + childCompiler, + compilerName, + compilerIndex + ); + + return childCompiler; + } + + isChild() { + return !!this.parentCompilation; + } + + createCompilation() { + return new Compilation(this); + } + + newCompilation(params) { + const compilation = this.createCompilation(); + compilation.fileTimestamps = this.fileTimestamps; + compilation.contextTimestamps = this.contextTimestamps; + compilation.name = this.name; + compilation.records = this.records; + compilation.compilationDependencies = params.compilationDependencies; + this.hooks.thisCompilation.call(compilation, params); + this.hooks.compilation.call(compilation, params); + return compilation; + } + + createNormalModuleFactory() { + const normalModuleFactory = new NormalModuleFactory( + this.options.context, + this.resolverFactory, + this.options.module || {} + ); + 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(), + compilationDependencies: new Set() + }; + return params; + } + + 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); + + this.hooks.make.callAsync(compilation, err => { + if (err) return callback(err); + + compilation.finish(err => { + if (err) return callback(err); + + compilation.seal(err => { + if (err) return callback(err); + + this.hooks.afterCompile.callAsync(compilation, err => { + if (err) return callback(err); + + return callback(null, compilation); + }); + }); + }); + }); + }); + } +} + +module.exports = Compiler; + +class SizeOnlySource extends Source { + constructor(size) { + super(); + this._size = size; + } + + _error() { + return new Error( + "Content and Map of this Source is no longer available (only size() is supported)" + ); + } + + size() { + return this._size; + } + + /** + * @param {any} options options + * @returns {string} the source + */ + source(options) { + throw this._error(); + } + + node() { + throw this._error(); + } + + listMap() { + throw this._error(); + } + + map() { + throw this._error(); + } + + listNode() { + throw this._error(); + } + + updateHash() { + throw this._error(); + } +} |