diff options
Diffstat (limited to 'node_modules/webpack/lib/NormalModule.js')
| -rw-r--r-- | node_modules/webpack/lib/NormalModule.js | 1639 |
1 files changed, 0 insertions, 1639 deletions
diff --git a/node_modules/webpack/lib/NormalModule.js b/node_modules/webpack/lib/NormalModule.js deleted file mode 100644 index eea12c93..00000000 --- a/node_modules/webpack/lib/NormalModule.js +++ /dev/null @@ -1,1639 +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 { getContext, runLoaders } = require("loader-runner"); -const querystring = require("querystring"); -const { HookMap, SyncHook, AsyncSeriesBailHook } = require("tapable"); -const { - CachedSource, - OriginalSource, - RawSource, - SourceMapSource -} = require("webpack-sources"); -const Compilation = require("./Compilation"); -const HookWebpackError = require("./HookWebpackError"); -const Module = require("./Module"); -const ModuleBuildError = require("./ModuleBuildError"); -const ModuleError = require("./ModuleError"); -const ModuleGraphConnection = require("./ModuleGraphConnection"); -const ModuleParseError = require("./ModuleParseError"); -const { JAVASCRIPT_MODULE_TYPE_AUTO } = require("./ModuleTypeConstants"); -const ModuleWarning = require("./ModuleWarning"); -const RuntimeGlobals = require("./RuntimeGlobals"); -const UnhandledSchemeError = require("./UnhandledSchemeError"); -const WebpackError = require("./WebpackError"); -const formatLocation = require("./formatLocation"); -const LazySet = require("./util/LazySet"); -const { isSubset } = require("./util/SetHelpers"); -const { getScheme } = require("./util/URLAbsoluteSpecifier"); -const { - compareLocations, - concatComparators, - compareSelect, - keepOriginalOrder -} = require("./util/comparators"); -const createHash = require("./util/createHash"); -const { createFakeHook } = require("./util/deprecation"); -const { join } = require("./util/fs"); -const { - contextify, - absolutify, - makePathsRelative -} = require("./util/identifier"); -const makeSerializable = require("./util/makeSerializable"); -const memoize = require("./util/memoize"); - -/** @typedef {import("webpack-sources").Source} Source */ -/** @typedef {import("../declarations/WebpackOptions").Mode} Mode */ -/** @typedef {import("../declarations/WebpackOptions").ResolveOptions} ResolveOptions */ -/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */ -/** @typedef {import("./ChunkGraph")} ChunkGraph */ -/** @typedef {import("./Compiler")} Compiler */ -/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */ -/** @typedef {import("./DependencyTemplates")} DependencyTemplates */ -/** @typedef {import("./Generator")} Generator */ -/** @typedef {import("./Module").BuildInfo} BuildInfo */ -/** @typedef {import("./Module").BuildMeta} BuildMeta */ -/** @typedef {import("./Module").CodeGenerationContext} CodeGenerationContext */ -/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */ -/** @typedef {import("./Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */ -/** @typedef {import("./Module").KnownBuildInfo} KnownBuildInfo */ -/** @typedef {import("./Module").LibIdentOptions} LibIdentOptions */ -/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */ -/** @typedef {import("./Module").SourceTypes} SourceTypes */ -/** @typedef {import("./Module").UnsafeCacheData} UnsafeCacheData */ -/** @typedef {import("./ModuleGraph")} ModuleGraph */ -/** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */ -/** @typedef {import("./ModuleTypeConstants").JavaScriptModuleTypes} JavaScriptModuleTypes */ -/** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */ -/** @typedef {import("./Parser")} Parser */ -/** @typedef {import("./RequestShortener")} RequestShortener */ -/** @typedef {import("./ResolverFactory").ResolveContext} ResolveContext */ -/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */ -/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ -/** @typedef {import("./logging/Logger").Logger} WebpackLogger */ -/** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */ -/** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */ -/** @typedef {import("./util/Hash")} Hash */ -/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ -/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */ -/** @typedef {import("./util/createHash").Algorithm} Algorithm */ -/** - * @template T - * @typedef {import("./util/deprecation").FakeHook<T>} FakeHook - */ - -/** @typedef {{[k: string]: any}} ParserOptions */ -/** @typedef {{[k: string]: any}} GeneratorOptions */ - -/** @typedef {UnsafeCacheData & { parser: undefined | Parser, parserOptions: undefined | ParserOptions, generator: undefined | Generator, generatorOptions: undefined | GeneratorOptions }} NormalModuleUnsafeCacheData */ - -/** - * @template T - * @typedef {import("../declarations/LoaderContext").LoaderContext<T>} LoaderContext - */ - -/** - * @template T - * @typedef {import("../declarations/LoaderContext").NormalModuleLoaderContext<T>} NormalModuleLoaderContext - */ - -/** - * @typedef {object} SourceMap - * @property {number} version - * @property {string[]} sources - * @property {string} mappings - * @property {string=} file - * @property {string=} sourceRoot - * @property {string[]=} sourcesContent - * @property {string[]=} names - */ - -const getInvalidDependenciesModuleWarning = memoize(() => - require("./InvalidDependenciesModuleWarning") -); -const getValidate = memoize(() => require("schema-utils").validate); - -const ABSOLUTE_PATH_REGEX = /^([a-zA-Z]:\\|\\\\|\/)/; - -/** - * @typedef {object} LoaderItem - * @property {string} loader - * @property {any} options - * @property {string?} ident - * @property {string?} type - */ - -/** - * @param {string} context absolute context path - * @param {string} source a source path - * @param {object=} associatedObjectForCache an object to which the cache will be attached - * @returns {string} new source path - */ -const contextifySourceUrl = (context, source, associatedObjectForCache) => { - if (source.startsWith("webpack://")) return source; - return `webpack://${makePathsRelative( - context, - source, - associatedObjectForCache - )}`; -}; - -/** - * @param {string} context absolute context path - * @param {SourceMap} sourceMap a source map - * @param {object=} associatedObjectForCache an object to which the cache will be attached - * @returns {SourceMap} new source map - */ -const contextifySourceMap = (context, sourceMap, associatedObjectForCache) => { - if (!Array.isArray(sourceMap.sources)) return sourceMap; - const { sourceRoot } = sourceMap; - /** @type {function(string): string} */ - const mapper = !sourceRoot - ? source => source - : sourceRoot.endsWith("/") - ? source => - source.startsWith("/") - ? `${sourceRoot.slice(0, -1)}${source}` - : `${sourceRoot}${source}` - : source => - source.startsWith("/") - ? `${sourceRoot}${source}` - : `${sourceRoot}/${source}`; - const newSources = sourceMap.sources.map(source => - contextifySourceUrl(context, mapper(source), associatedObjectForCache) - ); - return { - ...sourceMap, - file: "x", - sourceRoot: undefined, - sources: newSources - }; -}; - -/** - * @param {string | Buffer} input the input - * @returns {string} the converted string - */ -const asString = input => { - if (Buffer.isBuffer(input)) { - return input.toString("utf-8"); - } - return input; -}; - -/** - * @param {string | Buffer} input the input - * @returns {Buffer} the converted buffer - */ -const asBuffer = input => { - if (!Buffer.isBuffer(input)) { - return Buffer.from(input, "utf-8"); - } - return input; -}; - -class NonErrorEmittedError extends WebpackError { - /** - * @param {any} error value which is not an instance of Error - */ - constructor(error) { - super(); - - this.name = "NonErrorEmittedError"; - this.message = `(Emitted value instead of an instance of Error) ${error}`; - } -} - -makeSerializable( - NonErrorEmittedError, - "webpack/lib/NormalModule", - "NonErrorEmittedError" -); - -/** - * @typedef {object} NormalModuleCompilationHooks - * @property {SyncHook<[LoaderContext<any>, NormalModule]>} loader - * @property {SyncHook<[LoaderItem[], NormalModule, LoaderContext<any>]>} beforeLoaders - * @property {SyncHook<[NormalModule]>} beforeParse - * @property {SyncHook<[NormalModule]>} beforeSnapshot - * @property {HookMap<FakeHook<AsyncSeriesBailHook<[string, NormalModule], string | Buffer | null>>>} readResourceForScheme - * @property {HookMap<AsyncSeriesBailHook<[LoaderContext<any>], string | Buffer | null>>} readResource - * @property {AsyncSeriesBailHook<[NormalModule, NeedBuildContext], boolean>} needBuild - */ - -/** - * @typedef {object} NormalModuleCreateData - * @property {string=} layer an optional layer in which the module is - * @property {JavaScriptModuleTypes | ""} type module type. When deserializing, this is set to an empty string "". - * @property {string} request request string - * @property {string} userRequest request intended by user (without loaders from config) - * @property {string} rawRequest request without resolving - * @property {LoaderItem[]} loaders list of loaders - * @property {string} resource path + query of the real resource - * @property {Record<string, any>=} resourceResolveData resource resolve data - * @property {string} context context directory for resolving - * @property {string=} matchResource path + query of the matched resource (virtual) - * @property {Parser} parser the parser used - * @property {ParserOptions=} parserOptions the options of the parser used - * @property {Generator} generator the generator used - * @property {GeneratorOptions=} generatorOptions the options of the generator used - * @property {ResolveOptions=} resolveOptions options used for resolving requests from this module - */ - -/** @type {WeakMap<Compilation, NormalModuleCompilationHooks>} */ -const compilationHooksMap = new WeakMap(); - -class NormalModule extends Module { - /** - * @param {Compilation} compilation the compilation - * @returns {NormalModuleCompilationHooks} the attached hooks - */ - static getCompilationHooks(compilation) { - if (!(compilation instanceof Compilation)) { - throw new TypeError( - "The 'compilation' argument must be an instance of Compilation" - ); - } - let hooks = compilationHooksMap.get(compilation); - if (hooks === undefined) { - hooks = { - loader: new SyncHook(["loaderContext", "module"]), - beforeLoaders: new SyncHook(["loaders", "module", "loaderContext"]), - beforeParse: new SyncHook(["module"]), - beforeSnapshot: new SyncHook(["module"]), - // TODO webpack 6 deprecate - readResourceForScheme: new HookMap(scheme => { - const hook = - /** @type {NormalModuleCompilationHooks} */ - (hooks).readResource.for(scheme); - return createFakeHook( - /** @type {AsyncSeriesBailHook<[string, NormalModule], string | Buffer | null>} */ ({ - tap: (options, fn) => - hook.tap(options, loaderContext => - fn( - loaderContext.resource, - /** @type {NormalModule} */ (loaderContext._module) - ) - ), - tapAsync: (options, fn) => - hook.tapAsync(options, (loaderContext, callback) => - fn( - loaderContext.resource, - /** @type {NormalModule} */ (loaderContext._module), - callback - ) - ), - tapPromise: (options, fn) => - hook.tapPromise(options, loaderContext => - fn( - loaderContext.resource, - /** @type {NormalModule} */ (loaderContext._module) - ) - ) - }) - ); - }), - readResource: new HookMap( - () => new AsyncSeriesBailHook(["loaderContext"]) - ), - needBuild: new AsyncSeriesBailHook(["module", "context"]) - }; - compilationHooksMap.set( - compilation, - /** @type {NormalModuleCompilationHooks} */ (hooks) - ); - } - return /** @type {NormalModuleCompilationHooks} */ (hooks); - } - - /** - * @param {NormalModuleCreateData} options options object - */ - constructor({ - layer, - type, - request, - userRequest, - rawRequest, - loaders, - resource, - resourceResolveData, - context, - matchResource, - parser, - parserOptions, - generator, - generatorOptions, - resolveOptions - }) { - super(type, context || getContext(resource), layer); - - // Info from Factory - /** @type {string} */ - this.request = request; - /** @type {string} */ - this.userRequest = userRequest; - /** @type {string} */ - this.rawRequest = rawRequest; - /** @type {boolean} */ - this.binary = /^(asset|webassembly)\b/.test(type); - /** @type {undefined | Parser} */ - this.parser = parser; - /** @type {undefined | ParserOptions} */ - this.parserOptions = parserOptions; - /** @type {undefined | Generator} */ - this.generator = generator; - /** @type {undefined | GeneratorOptions} */ - this.generatorOptions = generatorOptions; - /** @type {string} */ - this.resource = resource; - this.resourceResolveData = resourceResolveData; - /** @type {string | undefined} */ - this.matchResource = matchResource; - /** @type {LoaderItem[]} */ - this.loaders = loaders; - if (resolveOptions !== undefined) { - // already declared in super class - this.resolveOptions = resolveOptions; - } - - // Info from Build - /** @type {WebpackError | null} */ - this.error = null; - /** - * @private - * @type {Source | null} - */ - this._source = null; - /** - * @private - * @type {Map<string | undefined, number> | undefined} - */ - this._sourceSizes = undefined; - /** - * @private - * @type {undefined | SourceTypes} - */ - this._sourceTypes = undefined; - - // Cache - this._lastSuccessfulBuildMeta = {}; - this._forceBuild = true; - this._isEvaluatingSideEffects = false; - /** @type {WeakSet<ModuleGraph> | undefined} */ - this._addedSideEffectsBailout = undefined; - /** @type {Map<string, any>} */ - this._codeGeneratorData = new Map(); - } - - /** - * @returns {string} a unique identifier of the module - */ - identifier() { - if (this.layer === null) { - if (this.type === JAVASCRIPT_MODULE_TYPE_AUTO) { - return this.request; - } - return `${this.type}|${this.request}`; - } - return `${this.type}|${this.request}|${this.layer}`; - } - - /** - * @param {RequestShortener} requestShortener the request shortener - * @returns {string} a user readable identifier of the module - */ - readableIdentifier(requestShortener) { - return /** @type {string} */ (requestShortener.shorten(this.userRequest)); - } - - /** - * @param {LibIdentOptions} options options - * @returns {string | null} an identifier for library inclusion - */ - libIdent(options) { - let ident = contextify( - options.context, - this.userRequest, - options.associatedObjectForCache - ); - if (this.layer) ident = `(${this.layer})/${ident}`; - return ident; - } - - /** - * @returns {string | null} absolute path which should be used for condition matching (usually the resource path) - */ - nameForCondition() { - const resource = this.matchResource || this.resource; - const idx = resource.indexOf("?"); - if (idx >= 0) return resource.slice(0, idx); - return resource; - } - - /** - * Assuming this module is in the cache. Update the (cached) module with - * the fresh module from the factory. Usually updates internal references - * and properties. - * @param {Module} module fresh module - * @returns {void} - */ - updateCacheModule(module) { - super.updateCacheModule(module); - const m = /** @type {NormalModule} */ (module); - this.binary = m.binary; - this.request = m.request; - this.userRequest = m.userRequest; - this.rawRequest = m.rawRequest; - this.parser = m.parser; - this.parserOptions = m.parserOptions; - this.generator = m.generator; - this.generatorOptions = m.generatorOptions; - this.resource = m.resource; - this.resourceResolveData = m.resourceResolveData; - this.context = m.context; - this.matchResource = m.matchResource; - this.loaders = m.loaders; - } - - /** - * Assuming this module is in the cache. Remove internal references to allow freeing some memory. - */ - cleanupForCache() { - // Make sure to cache types and sizes before cleanup when this module has been built - // They are accessed by the stats and we don't want them to crash after cleanup - // TODO reconsider this for webpack 6 - if (this.buildInfo) { - if (this._sourceTypes === undefined) this.getSourceTypes(); - for (const type of /** @type {SourceTypes} */ (this._sourceTypes)) { - this.size(type); - } - } - super.cleanupForCache(); - this.parser = undefined; - this.parserOptions = undefined; - this.generator = undefined; - this.generatorOptions = undefined; - } - - /** - * Module should be unsafe cached. Get data that's needed for that. - * This data will be passed to restoreFromUnsafeCache later. - * @returns {UnsafeCacheData} cached data - */ - getUnsafeCacheData() { - const data = - /** @type {NormalModuleUnsafeCacheData} */ - (super.getUnsafeCacheData()); - data.parserOptions = this.parserOptions; - data.generatorOptions = this.generatorOptions; - return data; - } - - /** - * restore unsafe cache data - * @param {NormalModuleUnsafeCacheData} unsafeCacheData data from getUnsafeCacheData - * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching - */ - restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) { - this._restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory); - } - - /** - * restore unsafe cache data - * @param {object} unsafeCacheData data from getUnsafeCacheData - * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching - */ - _restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) { - super._restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory); - this.parserOptions = unsafeCacheData.parserOptions; - this.parser = normalModuleFactory.getParser(this.type, this.parserOptions); - this.generatorOptions = unsafeCacheData.generatorOptions; - this.generator = normalModuleFactory.getGenerator( - this.type, - this.generatorOptions - ); - // we assume the generator behaves identically and keep cached sourceTypes/Sizes - } - - /** - * @param {string} context the compilation context - * @param {string} name the asset name - * @param {string | Buffer} content the content - * @param {(string | SourceMap)=} sourceMap an optional source map - * @param {object=} associatedObjectForCache object for caching - * @returns {Source} the created source - */ - createSourceForAsset( - context, - name, - content, - sourceMap, - associatedObjectForCache - ) { - if (sourceMap) { - if ( - typeof sourceMap === "string" && - (this.useSourceMap || this.useSimpleSourceMap) - ) { - return new OriginalSource( - content, - contextifySourceUrl(context, sourceMap, associatedObjectForCache) - ); - } - - if (this.useSourceMap) { - return new SourceMapSource( - content, - name, - contextifySourceMap( - context, - /** @type {SourceMap} */ (sourceMap), - associatedObjectForCache - ) - ); - } - } - - return new RawSource(content); - } - - /** - * @private - * @template T - * @param {ResolverWithOptions} resolver a resolver - * @param {WebpackOptions} options webpack options - * @param {Compilation} compilation the compilation - * @param {InputFileSystem} fs file system from reading - * @param {NormalModuleCompilationHooks} hooks the hooks - * @returns {import("../declarations/LoaderContext").NormalModuleLoaderContext<T>} loader context - */ - _createLoaderContext(resolver, options, compilation, fs, hooks) { - const { requestShortener } = compilation.runtimeTemplate; - const getCurrentLoaderName = () => { - const currentLoader = this.getCurrentLoader(loaderContext); - if (!currentLoader) return "(not in loader scope)"; - return requestShortener.shorten(currentLoader.loader); - }; - /** - * @returns {ResolveContext} resolve context - */ - const getResolveContext = () => ({ - fileDependencies: { - add: d => /** @type {TODO} */ (loaderContext).addDependency(d) - }, - contextDependencies: { - add: d => /** @type {TODO} */ (loaderContext).addContextDependency(d) - }, - missingDependencies: { - add: d => /** @type {TODO} */ (loaderContext).addMissingDependency(d) - } - }); - const getAbsolutify = memoize(() => - absolutify.bindCache(compilation.compiler.root) - ); - const getAbsolutifyInContext = memoize(() => - absolutify.bindContextCache( - /** @type {string} */ - (this.context), - compilation.compiler.root - ) - ); - const getContextify = memoize(() => - contextify.bindCache(compilation.compiler.root) - ); - const getContextifyInContext = memoize(() => - contextify.bindContextCache( - /** @type {string} */ - (this.context), - compilation.compiler.root - ) - ); - const utils = { - /** - * @param {string} context context - * @param {string} request request - * @returns {string} result - */ - absolutify: (context, request) => - context === this.context - ? getAbsolutifyInContext()(request) - : getAbsolutify()(context, request), - /** - * @param {string} context context - * @param {string} request request - * @returns {string} result - */ - contextify: (context, request) => - context === this.context - ? getContextifyInContext()(request) - : getContextify()(context, request), - /** - * @param {(string | typeof import("./util/Hash"))=} type type - * @returns {Hash} hash - */ - createHash: type => - createHash( - type || - /** @type {Algorithm} */ - (compilation.outputOptions.hashFunction) - ) - }; - /** @type {import("../declarations/LoaderContext").NormalModuleLoaderContext<T>} */ - const loaderContext = { - version: 2, - getOptions: schema => { - const loader = this.getCurrentLoader(loaderContext); - - let { options } = /** @type {LoaderItem} */ (loader); - - if (typeof options === "string") { - if (options.startsWith("{") && options.endsWith("}")) { - try { - options = parseJson(options); - } catch (err) { - throw new Error( - `Cannot parse string options: ${/** @type {Error} */ (err).message}` - ); - } - } else { - options = querystring.parse(options, "&", "=", { - maxKeys: 0 - }); - } - } - - if (options === null || options === undefined) { - options = {}; - } - - if (schema) { - let name = "Loader"; - let baseDataPath = "options"; - let match; - if (schema.title && (match = /^(.+) (.+)$/.exec(schema.title))) { - [, name, baseDataPath] = match; - } - getValidate()(schema, options, { - name, - baseDataPath - }); - } - - return options; - }, - emitWarning: warning => { - if (!(warning instanceof Error)) { - warning = new NonErrorEmittedError(warning); - } - this.addWarning( - new ModuleWarning(warning, { - from: getCurrentLoaderName() - }) - ); - }, - emitError: error => { - if (!(error instanceof Error)) { - error = new NonErrorEmittedError(error); - } - this.addError( - new ModuleError(error, { - from: getCurrentLoaderName() - }) - ); - }, - getLogger: name => { - const currentLoader = this.getCurrentLoader(loaderContext); - return compilation.getLogger(() => - [currentLoader && currentLoader.loader, name, this.identifier()] - .filter(Boolean) - .join("|") - ); - }, - resolve(context, request, callback) { - resolver.resolve({}, context, request, getResolveContext(), callback); - }, - getResolve(options) { - const child = options ? resolver.withOptions(options) : resolver; - return (context, request, callback) => { - if (callback) { - child.resolve({}, context, request, getResolveContext(), callback); - } else { - return new Promise((resolve, reject) => { - child.resolve( - {}, - context, - request, - getResolveContext(), - (err, result) => { - if (err) reject(err); - else resolve(result); - } - ); - }); - } - }; - }, - emitFile: (name, content, sourceMap, assetInfo) => { - const buildInfo = /** @type {BuildInfo} */ (this.buildInfo); - - if (!buildInfo.assets) { - buildInfo.assets = Object.create(null); - buildInfo.assetsInfo = new Map(); - } - - const assets = - /** @type {NonNullable<KnownBuildInfo["assets"]>} */ - (buildInfo.assets); - const assetsInfo = - /** @type {NonNullable<KnownBuildInfo["assetsInfo"]>} */ - (buildInfo.assetsInfo); - - assets[name] = this.createSourceForAsset( - /** @type {string} */ (options.context), - name, - content, - sourceMap, - compilation.compiler.root - ); - assetsInfo.set(name, assetInfo); - }, - addBuildDependency: dep => { - const buildInfo = /** @type {BuildInfo} */ (this.buildInfo); - - if (buildInfo.buildDependencies === undefined) { - buildInfo.buildDependencies = new LazySet(); - } - buildInfo.buildDependencies.add(dep); - }, - utils, - rootContext: /** @type {string} */ (options.context), - webpack: true, - sourceMap: Boolean(this.useSourceMap), - mode: options.mode || "production", - _module: this, - _compilation: compilation, - _compiler: compilation.compiler, - fs - }; - - Object.assign(loaderContext, options.loader); - - hooks.loader.call(/** @type {LoaderContext<any>} */ (loaderContext), this); - - return loaderContext; - } - - // TODO remove `loaderContext` in webpack@6 - /** - * @param {TODO} loaderContext loader context - * @param {number} index index - * @returns {LoaderItem | null} loader - */ - getCurrentLoader(loaderContext, index = loaderContext.loaderIndex) { - if ( - this.loaders && - this.loaders.length && - index < this.loaders.length && - index >= 0 && - this.loaders[index] - ) { - return this.loaders[index]; - } - return null; - } - - /** - * @param {string} context the compilation context - * @param {string | Buffer} content the content - * @param {(string | SourceMapSource | null)=} sourceMap an optional source map - * @param {object=} associatedObjectForCache object for caching - * @returns {Source} the created source - */ - createSource(context, content, sourceMap, associatedObjectForCache) { - if (Buffer.isBuffer(content)) { - return new RawSource(content); - } - - // if there is no identifier return raw source - if (!this.identifier) { - return new RawSource(content); - } - - // from here on we assume we have an identifier - const identifier = this.identifier(); - - if (this.useSourceMap && sourceMap) { - return new SourceMapSource( - content, - contextifySourceUrl(context, identifier, associatedObjectForCache), - contextifySourceMap( - context, - /** @type {TODO} */ (sourceMap), - associatedObjectForCache - ) - ); - } - - if (this.useSourceMap || this.useSimpleSourceMap) { - return new OriginalSource( - content, - contextifySourceUrl(context, identifier, associatedObjectForCache) - ); - } - - return new RawSource(content); - } - - /** - * @param {WebpackOptions} options webpack options - * @param {Compilation} compilation the compilation - * @param {ResolverWithOptions} resolver the resolver - * @param {InputFileSystem} fs the file system - * @param {NormalModuleCompilationHooks} hooks the hooks - * @param {function((WebpackError | null)=): void} callback callback function - * @returns {void} - */ - _doBuild(options, compilation, resolver, fs, hooks, callback) { - const loaderContext = this._createLoaderContext( - resolver, - options, - compilation, - fs, - hooks - ); - - /** @typedef {[string | Buffer, string | SourceMapSource, Record<string, any>]} Result */ - - /** - * @param {Error | null} err err - * @param {(Result | null)=} _result result - * @returns {void} - */ - const processResult = (err, _result) => { - if (err) { - if (!(err instanceof Error)) { - err = new NonErrorEmittedError(err); - } - const currentLoader = this.getCurrentLoader(loaderContext); - const error = new ModuleBuildError(err, { - from: - currentLoader && - compilation.runtimeTemplate.requestShortener.shorten( - currentLoader.loader - ) - }); - return callback(error); - } - - const result = /** @type {Result} */ (_result); - const source = result[0]; - const sourceMap = result.length >= 1 ? result[1] : null; - const extraInfo = result.length >= 2 ? result[2] : null; - - if (!Buffer.isBuffer(source) && typeof source !== "string") { - const currentLoader = this.getCurrentLoader(loaderContext, 0); - const err = new Error( - `Final loader (${ - currentLoader - ? compilation.runtimeTemplate.requestShortener.shorten( - currentLoader.loader - ) - : "unknown" - }) didn't return a Buffer or String` - ); - const error = new ModuleBuildError(err); - return callback(error); - } - - const isBinaryModule = - this.generatorOptions && this.generatorOptions.binary !== undefined - ? this.generatorOptions.binary - : this.binary; - - this._source = this.createSource( - /** @type {string} */ (options.context), - isBinaryModule ? asBuffer(source) : asString(source), - sourceMap, - compilation.compiler.root - ); - if (this._sourceSizes !== undefined) this._sourceSizes.clear(); - this._ast = - typeof extraInfo === "object" && - extraInfo !== null && - extraInfo.webpackAST !== undefined - ? extraInfo.webpackAST - : null; - return callback(); - }; - - const buildInfo = /** @type {BuildInfo} */ (this.buildInfo); - - buildInfo.fileDependencies = new LazySet(); - buildInfo.contextDependencies = new LazySet(); - buildInfo.missingDependencies = new LazySet(); - buildInfo.cacheable = true; - - try { - hooks.beforeLoaders.call( - this.loaders, - this, - /** @type {LoaderContext<any>} */ (loaderContext) - ); - } catch (err) { - processResult(err); - return; - } - - if (this.loaders.length > 0) { - /** @type {BuildInfo} */ - (this.buildInfo).buildDependencies = new LazySet(); - } - - runLoaders( - { - resource: this.resource, - loaders: this.loaders, - context: loaderContext, - processResource: (loaderContext, resourcePath, callback) => { - const resource = loaderContext.resource; - const scheme = getScheme(resource); - hooks.readResource - .for(scheme) - .callAsync(loaderContext, (err, result) => { - if (err) return callback(err); - if (typeof result !== "string" && !result) { - return callback( - new UnhandledSchemeError( - /** @type {string} */ - (scheme), - resource - ) - ); - } - return callback(null, result); - }); - } - }, - (err, result) => { - // Cleanup loaderContext to avoid leaking memory in ICs - loaderContext._compilation = - loaderContext._compiler = - loaderContext._module = - // eslint-disable-next-line no-warning-comments - // @ts-ignore - loaderContext.fs = - undefined; - - if (!result) { - /** @type {BuildInfo} */ - (this.buildInfo).cacheable = false; - return processResult( - err || new Error("No result from loader-runner processing"), - null - ); - } - - const buildInfo = /** @type {BuildInfo} */ (this.buildInfo); - - const fileDependencies = - /** @type {NonNullable<KnownBuildInfo["fileDependencies"]>} */ - (buildInfo.fileDependencies); - const contextDependencies = - /** @type {NonNullable<KnownBuildInfo["contextDependencies"]>} */ - (buildInfo.contextDependencies); - const missingDependencies = - /** @type {NonNullable<KnownBuildInfo["missingDependencies"]>} */ - (buildInfo.missingDependencies); - - fileDependencies.addAll(result.fileDependencies); - contextDependencies.addAll(result.contextDependencies); - missingDependencies.addAll(result.missingDependencies); - for (const loader of this.loaders) { - const buildDependencies = - /** @type {NonNullable<KnownBuildInfo["buildDependencies"]>} */ - (buildInfo.buildDependencies); - - buildDependencies.add(loader.loader); - } - buildInfo.cacheable = buildInfo.cacheable && result.cacheable; - processResult(err, result.result); - } - ); - } - - /** - * @param {WebpackError} error the error - * @returns {void} - */ - markModuleAsErrored(error) { - // Restore build meta from successful build to keep importing state - this.buildMeta = { ...this._lastSuccessfulBuildMeta }; - this.error = error; - this.addError(error); - } - - /** - * @param {TODO} rule rule - * @param {string} content content - * @returns {boolean} result - */ - applyNoParseRule(rule, content) { - // must start with "rule" if rule is a string - if (typeof rule === "string") { - return content.startsWith(rule); - } - - if (typeof rule === "function") { - return rule(content); - } - // we assume rule is a regexp - return rule.test(content); - } - - /** - * @param {TODO} noParseRule no parse rule - * @param {string} request request - * @returns {boolean} check if module should not be parsed, returns "true" if the module should !not! be parsed, returns "false" if the module !must! be parsed - */ - shouldPreventParsing(noParseRule, request) { - // if no noParseRule exists, return false - // the module !must! be parsed. - if (!noParseRule) { - return false; - } - - // we only have one rule to check - if (!Array.isArray(noParseRule)) { - // returns "true" if the module is !not! to be parsed - return this.applyNoParseRule(noParseRule, request); - } - - for (let i = 0; i < noParseRule.length; i++) { - const rule = noParseRule[i]; - // early exit on first truthy match - // this module is !not! to be parsed - if (this.applyNoParseRule(rule, request)) { - return true; - } - } - // no match found, so this module !should! be parsed - return false; - } - - /** - * @param {Compilation} compilation compilation - * @private - */ - _initBuildHash(compilation) { - const hash = createHash( - /** @type {Algorithm} */ - (compilation.outputOptions.hashFunction) - ); - if (this._source) { - hash.update("source"); - this._source.updateHash(hash); - } - hash.update("meta"); - hash.update(JSON.stringify(this.buildMeta)); - /** @type {BuildInfo} */ - (this.buildInfo).hash = /** @type {string} */ (hash.digest("hex")); - } - - /** - * @param {WebpackOptions} options webpack options - * @param {Compilation} compilation the compilation - * @param {ResolverWithOptions} resolver the resolver - * @param {InputFileSystem} fs the file system - * @param {function(WebpackError=): void} callback callback function - * @returns {void} - */ - build(options, compilation, resolver, fs, callback) { - this._forceBuild = false; - this._source = null; - if (this._sourceSizes !== undefined) this._sourceSizes.clear(); - this._sourceTypes = undefined; - this._ast = null; - this.error = null; - this.clearWarningsAndErrors(); - this.clearDependenciesAndBlocks(); - this.buildMeta = {}; - this.buildInfo = { - cacheable: false, - parsed: true, - fileDependencies: undefined, - contextDependencies: undefined, - missingDependencies: undefined, - buildDependencies: undefined, - valueDependencies: undefined, - hash: undefined, - assets: undefined, - assetsInfo: undefined - }; - - const startTime = compilation.compiler.fsStartTime || Date.now(); - - const hooks = NormalModule.getCompilationHooks(compilation); - - return this._doBuild(options, compilation, resolver, fs, hooks, err => { - // if we have an error mark module as failed and exit - if (err) { - this.markModuleAsErrored(err); - this._initBuildHash(compilation); - return callback(); - } - - /** - * @param {Error} e error - * @returns {void} - */ - const handleParseError = e => { - const source = /** @type {Source} */ (this._source).source(); - const loaders = this.loaders.map(item => - contextify( - /** @type {string} */ (options.context), - item.loader, - compilation.compiler.root - ) - ); - const error = new ModuleParseError(source, e, loaders, this.type); - this.markModuleAsErrored(error); - this._initBuildHash(compilation); - return callback(); - }; - - const handleParseResult = () => { - this.dependencies.sort( - concatComparators( - compareSelect(a => a.loc, compareLocations), - keepOriginalOrder(this.dependencies) - ) - ); - this._initBuildHash(compilation); - this._lastSuccessfulBuildMeta = - /** @type {BuildMeta} */ - (this.buildMeta); - return handleBuildDone(); - }; - - const handleBuildDone = () => { - try { - hooks.beforeSnapshot.call(this); - } catch (err) { - this.markModuleAsErrored(/** @type {WebpackError} */ (err)); - return callback(); - } - - const snapshotOptions = compilation.options.snapshot.module; - const { cacheable } = /** @type {BuildInfo} */ (this.buildInfo); - if (!cacheable || !snapshotOptions) { - return callback(); - } - // add warning for all non-absolute paths in fileDependencies, etc - // This makes it easier to find problems with watching and/or caching - /** @type {undefined | Set<string>} */ - let nonAbsoluteDependencies; - /** - * @param {LazySet<string>} deps deps - */ - const checkDependencies = deps => { - for (const dep of deps) { - if (!ABSOLUTE_PATH_REGEX.test(dep)) { - if (nonAbsoluteDependencies === undefined) - nonAbsoluteDependencies = new Set(); - nonAbsoluteDependencies.add(dep); - deps.delete(dep); - try { - const depWithoutGlob = dep.replace(/[\\/]?\*.*$/, ""); - const absolute = join( - compilation.fileSystemInfo.fs, - /** @type {string} */ - (this.context), - depWithoutGlob - ); - if (absolute !== dep && ABSOLUTE_PATH_REGEX.test(absolute)) { - (depWithoutGlob !== dep - ? /** @type {NonNullable<KnownBuildInfo["contextDependencies"]>} */ - ( - /** @type {BuildInfo} */ (this.buildInfo) - .contextDependencies - ) - : deps - ).add(absolute); - } - } catch (_err) { - // ignore - } - } - } - }; - const buildInfo = /** @type {BuildInfo} */ (this.buildInfo); - const fileDependencies = - /** @type {NonNullable<KnownBuildInfo["fileDependencies"]>} */ - (buildInfo.fileDependencies); - const contextDependencies = - /** @type {NonNullable<KnownBuildInfo["contextDependencies"]>} */ - (buildInfo.contextDependencies); - const missingDependencies = - /** @type {NonNullable<KnownBuildInfo["missingDependencies"]>} */ - (buildInfo.missingDependencies); - checkDependencies(fileDependencies); - checkDependencies(missingDependencies); - checkDependencies(contextDependencies); - if (nonAbsoluteDependencies !== undefined) { - const InvalidDependenciesModuleWarning = - getInvalidDependenciesModuleWarning(); - this.addWarning( - new InvalidDependenciesModuleWarning(this, nonAbsoluteDependencies) - ); - } - // convert file/context/missingDependencies into filesystem snapshot - compilation.fileSystemInfo.createSnapshot( - startTime, - fileDependencies, - contextDependencies, - missingDependencies, - snapshotOptions, - (err, snapshot) => { - if (err) { - this.markModuleAsErrored(err); - return; - } - buildInfo.fileDependencies = undefined; - buildInfo.contextDependencies = undefined; - buildInfo.missingDependencies = undefined; - buildInfo.snapshot = snapshot; - return callback(); - } - ); - }; - - try { - hooks.beforeParse.call(this); - } catch (err) { - this.markModuleAsErrored(/** @type {WebpackError} */ (err)); - this._initBuildHash(compilation); - return callback(); - } - - // check if this module should !not! be parsed. - // if so, exit here; - const noParseRule = options.module && options.module.noParse; - if (this.shouldPreventParsing(noParseRule, this.request)) { - // We assume that we need module and exports - /** @type {BuildInfo} */ - (this.buildInfo).parsed = false; - this._initBuildHash(compilation); - return handleBuildDone(); - } - - try { - const source = /** @type {Source} */ (this._source).source(); - /** @type {Parser} */ - (this.parser).parse(this._ast || source, { - source, - current: this, - module: this, - compilation, - options - }); - } catch (parseErr) { - handleParseError(/** @type {Error} */ (parseErr)); - return; - } - handleParseResult(); - }); - } - - /** - * @param {ConcatenationBailoutReasonContext} context context - * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated - */ - getConcatenationBailoutReason(context) { - return /** @type {Generator} */ ( - this.generator - ).getConcatenationBailoutReason(this, context); - } - - /** - * @param {ModuleGraph} moduleGraph the module graph - * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only - */ - getSideEffectsConnectionState(moduleGraph) { - if (this.factoryMeta !== undefined) { - if (this.factoryMeta.sideEffectFree) return false; - if (this.factoryMeta.sideEffectFree === false) return true; - } - if (this.buildMeta !== undefined && this.buildMeta.sideEffectFree) { - if (this._isEvaluatingSideEffects) - return ModuleGraphConnection.CIRCULAR_CONNECTION; - this._isEvaluatingSideEffects = true; - /** @type {ConnectionState} */ - let current = false; - for (const dep of this.dependencies) { - const state = dep.getModuleEvaluationSideEffectsState(moduleGraph); - if (state === true) { - if ( - this._addedSideEffectsBailout === undefined - ? ((this._addedSideEffectsBailout = new WeakSet()), true) - : !this._addedSideEffectsBailout.has(moduleGraph) - ) { - this._addedSideEffectsBailout.add(moduleGraph); - moduleGraph - .getOptimizationBailout(this) - .push( - () => - `Dependency (${ - dep.type - }) with side effects at ${formatLocation(dep.loc)}` - ); - } - this._isEvaluatingSideEffects = false; - return true; - } else if (state !== ModuleGraphConnection.CIRCULAR_CONNECTION) { - current = ModuleGraphConnection.addConnectionStates(current, state); - } - } - this._isEvaluatingSideEffects = false; - // When caching is implemented here, make sure to not cache when - // at least one circular connection was in the loop above - return current; - } - return true; - } - - /** - * @returns {SourceTypes} types available (do not mutate) - */ - getSourceTypes() { - if (this._sourceTypes === undefined) { - this._sourceTypes = /** @type {Generator} */ (this.generator).getTypes( - this - ); - } - return this._sourceTypes; - } - - /** - * @param {CodeGenerationContext} context context for code generation - * @returns {CodeGenerationResult} result - */ - codeGeneration({ - dependencyTemplates, - runtimeTemplate, - moduleGraph, - chunkGraph, - runtime, - concatenationScope, - codeGenerationResults, - sourceTypes - }) { - /** @type {Set<string>} */ - const runtimeRequirements = new Set(); - - const { parsed } = /** @type {BuildInfo} */ (this.buildInfo); - - if (!parsed) { - runtimeRequirements.add(RuntimeGlobals.module); - runtimeRequirements.add(RuntimeGlobals.exports); - runtimeRequirements.add(RuntimeGlobals.thisAsExports); - } - - /** @type {function(): Map<string, any>} */ - const getData = () => this._codeGeneratorData; - - const sources = new Map(); - for (const type of sourceTypes || chunkGraph.getModuleSourceTypes(this)) { - const source = this.error - ? new RawSource( - `throw new Error(${JSON.stringify(this.error.message)});` - ) - : /** @type {Generator} */ (this.generator).generate(this, { - dependencyTemplates, - runtimeTemplate, - moduleGraph, - chunkGraph, - runtimeRequirements, - runtime, - concatenationScope, - codeGenerationResults, - getData, - type - }); - - if (source) { - sources.set(type, new CachedSource(source)); - } - } - - /** @type {CodeGenerationResult} */ - const resultEntry = { - sources, - runtimeRequirements, - data: this._codeGeneratorData - }; - return resultEntry; - } - - /** - * @returns {Source | null} the original source for the module before webpack transformation - */ - originalSource() { - return this._source; - } - - /** - * @returns {void} - */ - invalidateBuild() { - this._forceBuild = true; - } - - /** - * @param {NeedBuildContext} context context info - * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild - * @returns {void} - */ - needBuild(context, callback) { - const { fileSystemInfo, compilation, valueCacheVersions } = context; - // build if enforced - if (this._forceBuild) return callback(null, true); - - // always try to build in case of an error - if (this.error) return callback(null, true); - - const { cacheable, snapshot, valueDependencies } = - /** @type {BuildInfo} */ (this.buildInfo); - - // always build when module is not cacheable - if (!cacheable) return callback(null, true); - - // build when there is no snapshot to check - if (!snapshot) return callback(null, true); - - // build when valueDependencies have changed - if (valueDependencies) { - if (!valueCacheVersions) return callback(null, true); - for (const [key, value] of valueDependencies) { - if (value === undefined) return callback(null, true); - const current = valueCacheVersions.get(key); - if ( - value !== current && - (typeof value === "string" || - typeof current === "string" || - current === undefined || - !isSubset(value, current)) - ) { - return callback(null, true); - } - } - } - - // check snapshot for validity - fileSystemInfo.checkSnapshotValid(snapshot, (err, valid) => { - if (err) return callback(err); - if (!valid) return callback(null, true); - const hooks = NormalModule.getCompilationHooks(compilation); - hooks.needBuild.callAsync(this, context, (err, needBuild) => { - if (err) { - return callback( - HookWebpackError.makeWebpackError( - err, - "NormalModule.getCompilationHooks().needBuild" - ) - ); - } - callback(null, Boolean(needBuild)); - }); - }); - } - - /** - * @param {string=} type the source type for which the size should be estimated - * @returns {number} the estimated size of the module (must be non-zero) - */ - size(type) { - const cachedSize = - this._sourceSizes === undefined ? undefined : this._sourceSizes.get(type); - if (cachedSize !== undefined) { - return cachedSize; - } - const size = Math.max( - 1, - /** @type {Generator} */ (this.generator).getSize(this, type) - ); - if (this._sourceSizes === undefined) { - this._sourceSizes = new Map(); - } - this._sourceSizes.set(type, size); - return size; - } - - /** - * @param {LazySet<string>} fileDependencies set where file dependencies are added to - * @param {LazySet<string>} contextDependencies set where context dependencies are added to - * @param {LazySet<string>} missingDependencies set where missing dependencies are added to - * @param {LazySet<string>} buildDependencies set where build dependencies are added to - */ - addCacheDependencies( - fileDependencies, - contextDependencies, - missingDependencies, - buildDependencies - ) { - const { snapshot, buildDependencies: buildDeps } = - /** @type {BuildInfo} */ (this.buildInfo); - if (snapshot) { - fileDependencies.addAll(snapshot.getFileIterable()); - contextDependencies.addAll(snapshot.getContextIterable()); - missingDependencies.addAll(snapshot.getMissingIterable()); - } else { - const { - fileDependencies: fileDeps, - contextDependencies: contextDeps, - missingDependencies: missingDeps - } = /** @type {BuildInfo} */ (this.buildInfo); - if (fileDeps !== undefined) fileDependencies.addAll(fileDeps); - if (contextDeps !== undefined) contextDependencies.addAll(contextDeps); - if (missingDeps !== undefined) missingDependencies.addAll(missingDeps); - } - if (buildDeps !== undefined) { - buildDependencies.addAll(buildDeps); - } - } - - /** - * @param {Hash} hash the hash used to track dependencies - * @param {UpdateHashContext} context context - * @returns {void} - */ - updateHash(hash, context) { - hash.update(/** @type {BuildInfo} */ (this.buildInfo).hash); - /** @type {Generator} */ - (this.generator).updateHash(hash, { - module: this, - ...context - }); - super.updateHash(hash, context); - } - - /** - * @param {ObjectSerializerContext} context context - */ - serialize(context) { - const { write } = context; - // deserialize - write(this._source); - write(this.error); - write(this._lastSuccessfulBuildMeta); - write(this._forceBuild); - write(this._codeGeneratorData); - super.serialize(context); - } - - static deserialize(context) { - const obj = new NormalModule({ - // will be deserialized by Module - layer: null, - type: "", - // will be filled by updateCacheModule - resource: "", - context: "", - request: null, - userRequest: null, - rawRequest: null, - loaders: null, - matchResource: null, - parser: null, - parserOptions: null, - generator: null, - generatorOptions: null, - resolveOptions: null - }); - obj.deserialize(context); - return obj; - } - - /** - * @param {ObjectDeserializerContext} context context - */ - deserialize(context) { - const { read } = context; - this._source = read(); - this.error = read(); - this._lastSuccessfulBuildMeta = read(); - this._forceBuild = read(); - this._codeGeneratorData = read(); - super.deserialize(context); - } -} - -makeSerializable(NormalModule, "webpack/lib/NormalModule"); - -module.exports = NormalModule; |
