2013-01-31 01:49:25 +08:00
/ *
MIT License http : //www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @ sokra
* /
2018-07-30 23:08:51 +08:00
2017-02-11 11:16:18 +08:00
"use strict" ;
2013-01-31 01:49:25 +08:00
2025-07-03 17:06:45 +08:00
const querystring = require ( "querystring" ) ;
2022-04-16 20:01:53 +08:00
const parseJson = require ( "json-parse-even-better-errors" ) ;
2018-07-30 23:08:51 +08:00
const { getContext , runLoaders } = require ( "loader-runner" ) ;
2025-03-05 02:05:18 +08:00
const {
2025-07-03 17:06:45 +08:00
AsyncSeriesBailHook ,
2025-03-05 02:05:18 +08:00
HookMap ,
SyncHook ,
2025-07-03 17:06:45 +08:00
SyncWaterfallHook
2025-03-05 02:05:18 +08:00
} = require ( "tapable" ) ;
2018-03-22 19:05:58 +08:00
const {
CachedSource ,
OriginalSource ,
RawSource ,
SourceMapSource
} = require ( "webpack-sources" ) ;
2018-11-12 21:13:55 +08:00
const Compilation = require ( "./Compilation" ) ;
2021-08-04 21:55:58 +08:00
const HookWebpackError = require ( "./HookWebpackError" ) ;
2017-02-12 21:08:41 +08:00
const Module = require ( "./Module" ) ;
2017-02-11 11:16:18 +08:00
const ModuleBuildError = require ( "./ModuleBuildError" ) ;
const ModuleError = require ( "./ModuleError" ) ;
2020-10-05 22:57:31 +08:00
const ModuleGraphConnection = require ( "./ModuleGraphConnection" ) ;
2018-07-30 23:08:51 +08:00
const ModuleParseError = require ( "./ModuleParseError" ) ;
2023-04-01 01:56:32 +08:00
const { JAVASCRIPT _MODULE _TYPE _AUTO } = require ( "./ModuleTypeConstants" ) ;
2017-02-11 11:16:18 +08:00
const ModuleWarning = require ( "./ModuleWarning" ) ;
2018-11-17 01:11:51 +08:00
const RuntimeGlobals = require ( "./RuntimeGlobals" ) ;
2020-07-03 20:45:49 +08:00
const UnhandledSchemeError = require ( "./UnhandledSchemeError" ) ;
2018-07-30 23:08:51 +08:00
const WebpackError = require ( "./WebpackError" ) ;
2020-11-29 00:30:32 +08:00
const formatLocation = require ( "./formatLocation" ) ;
2020-08-23 03:54:34 +08:00
const LazySet = require ( "./util/LazySet" ) ;
2021-04-12 18:21:49 +08:00
const { isSubset } = require ( "./util/SetHelpers" ) ;
2020-06-29 17:24:44 +08:00
const { getScheme } = require ( "./util/URLAbsoluteSpecifier" ) ;
2018-10-18 15:20:59 +08:00
const {
2018-12-20 15:51:54 +08:00
compareLocations ,
2025-07-14 18:56:27 +08:00
compareNumbers ,
2018-10-18 15:20:59 +08:00
compareSelect ,
2025-07-03 17:06:45 +08:00
concatComparators ,
2018-10-18 15:20:59 +08:00
keepOriginalOrder
} = require ( "./util/comparators" ) ;
2018-04-27 20:24:43 +08:00
const createHash = require ( "./util/createHash" ) ;
2021-10-07 16:25:10 +08:00
const { createFakeHook } = require ( "./util/deprecation" ) ;
2021-01-07 20:06:44 +08:00
const { join } = require ( "./util/fs" ) ;
2021-08-19 20:01:44 +08:00
const {
absolutify ,
2025-07-03 17:06:45 +08:00
contextify ,
2021-08-19 20:01:44 +08:00
makePathsRelative
} = require ( "./util/identifier" ) ;
2018-10-09 20:30:59 +08:00
const makeSerializable = require ( "./util/makeSerializable" ) ;
2021-01-07 20:06:44 +08:00
const memoize = require ( "./util/memoize" ) ;
2017-02-11 11:16:18 +08:00
2018-07-30 23:08:51 +08:00
/** @typedef {import("webpack-sources").Source} Source */
2025-06-03 01:18:59 +08:00
/** @typedef {import("webpack-sources").RawSourceMap} RawSourceMap */
2021-04-17 02:28:30 +08:00
/** @typedef {import("../declarations/WebpackOptions").Mode} Mode */
2022-02-15 22:37:57 +08:00
/** @typedef {import("../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
2020-02-17 17:27:46 +08:00
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
2025-05-01 22:36:51 +08:00
/** @typedef {import("../declarations/WebpackOptions").NoParse} NoParse */
2018-08-23 01:23:48 +08:00
/** @typedef {import("./ChunkGraph")} ChunkGraph */
2021-04-17 02:28:30 +08:00
/** @typedef {import("./Compiler")} Compiler */
2020-07-28 00:09:48 +08:00
/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
2018-07-30 23:08:51 +08:00
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
2019-11-20 17:58:58 +08:00
/** @typedef {import("./Generator")} Generator */
2025-04-05 22:37:35 +08:00
/** @typedef {import("./Generator").GenerateErrorFn} GenerateErrorFn */
2025-07-09 18:59:21 +08:00
/** @typedef {import("./Generator").GenerateContextData} GenerateContextData */
2024-02-17 01:39:12 +08:00
/** @typedef {import("./Module").BuildInfo} BuildInfo */
/** @typedef {import("./Module").BuildMeta} BuildMeta */
2019-10-09 04:29:46 +08:00
/** @typedef {import("./Module").CodeGenerationContext} CodeGenerationContext */
/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
2020-09-15 16:07:04 +08:00
/** @typedef {import("./Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
2024-02-17 01:39:12 +08:00
/** @typedef {import("./Module").KnownBuildInfo} KnownBuildInfo */
2018-07-20 22:24:35 +08:00
/** @typedef {import("./Module").LibIdentOptions} LibIdentOptions */
2018-09-26 15:14:44 +08:00
/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
2025-03-12 09:56:14 +08:00
/** @typedef {import("./Module").NeedBuildCallback} NeedBuildCallback */
/** @typedef {import("./Module").BuildCallback} BuildCallback */
2024-11-01 04:19:07 +08:00
/** @typedef {import("./Generator").SourceTypes} SourceTypes */
2024-02-17 01:39:12 +08:00
/** @typedef {import("./Module").UnsafeCacheData} UnsafeCacheData */
2020-10-05 22:57:31 +08:00
/** @typedef {import("./ModuleGraph")} ModuleGraph */
/** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
2025-07-09 18:59:21 +08:00
/** @typedef {import("./ModuleTypeConstants").ModuleTypes} ModuleTypes */
2021-03-15 17:29:51 +08:00
/** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */
2024-10-24 04:30:31 +08:00
/** @typedef {import("./NormalModuleFactory").ResourceDataWithData} ResourceDataWithData */
2025-05-13 21:03:58 +08:00
/** @typedef {import("./NormalModuleFactory").ResourceSchemeData} ResourceSchemeData */
2019-11-30 03:24:13 +08:00
/** @typedef {import("./Parser")} Parser */
2025-04-04 21:38:51 +08:00
/** @typedef {import("./Parser").PreparsedAst} PreparsedAst */
2018-07-25 18:12:17 +08:00
/** @typedef {import("./RequestShortener")} RequestShortener */
2024-02-17 01:39:12 +08:00
/** @typedef {import("./ResolverFactory").ResolveContext} ResolveContext */
2019-11-11 22:25:03 +08:00
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
2025-05-13 21:03:58 +08:00
/** @typedef {import("./ResolverFactory").ResolveRequest} ResolveRequest */
2018-07-25 18:12:17 +08:00
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
2021-04-17 02:28:30 +08:00
/** @typedef {import("./logging/Logger").Logger} WebpackLogger */
2023-04-12 02:57:43 +08:00
/** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
2019-07-17 22:02:33 +08:00
/** @typedef {import("./util/Hash")} Hash */
2019-11-11 22:25:03 +08:00
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
2020-07-28 00:09:48 +08:00
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
2025-04-26 01:43:01 +08:00
/** @typedef {import("../declarations/WebpackOptions").HashFunction} HashFunction */
2025-04-03 00:02:22 +08:00
/** @typedef {import("./util/identifier").AssociatedObjectForCache} AssociatedObjectForCache */
2025-07-14 18:56:27 +08:00
/** @typedef {import("./dependencies/HarmonyImportSideEffectDependency")} HarmonyImportSideEffectDependency */
/** @typedef {import("./dependencies/HarmonyImportSpecifierDependency")} HarmonyImportSpecifierDependency */
2024-08-07 23:22:25 +08:00
/ * *
* @ template T
* @ typedef { import ( "./util/deprecation" ) . FakeHook < T > } FakeHook
* /
2018-07-11 19:05:13 +08:00
2025-04-04 21:38:51 +08:00
/** @typedef {{ [k: string]: EXPECTED_ANY }} ParserOptions */
/** @typedef {{ [k: string]: EXPECTED_ANY }} GeneratorOptions */
2024-02-17 01:39:12 +08:00
2024-08-06 11:08:48 +08:00
/ * *
* @ template T
* @ typedef { import ( "../declarations/LoaderContext" ) . LoaderContext < T > } LoaderContext
* /
/ * *
* @ template T
* @ typedef { import ( "../declarations/LoaderContext" ) . NormalModuleLoaderContext < T > } NormalModuleLoaderContext
* /
2021-01-07 20:06:44 +08:00
const getInvalidDependenciesModuleWarning = memoize ( ( ) =>
require ( "./InvalidDependenciesModuleWarning" )
) ;
2021-04-16 21:35:18 +08:00
const getValidate = memoize ( ( ) => require ( "schema-utils" ) . validate ) ;
2021-01-07 20:06:44 +08:00
const ABSOLUTE _PATH _REGEX = /^([a-zA-Z]:\\|\\\\|\/)/ ;
2020-01-16 21:48:52 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } LoaderItem
2020-01-16 21:48:52 +08:00
* @ property { string } loader
2025-04-04 21:38:51 +08:00
* @ property { string | null | undefined | Record < string , EXPECTED _ANY > } options
2020-01-16 21:48:52 +08:00
* @ property { string ? } ident
2020-07-31 23:38:33 +08:00
* @ property { string ? } type
2020-01-16 21:48:52 +08:00
* /
2019-11-11 22:25:03 +08:00
/ * *
* @ param { string } context absolute context path
* @ param { string } source a source path
2025-04-03 00:02:22 +08:00
* @ param { AssociatedObjectForCache = } associatedObjectForCache an object to which the cache will be attached
2019-11-11 22:25:03 +08:00
* @ returns { string } new source path
* /
const contextifySourceUrl = ( context , source , associatedObjectForCache ) => {
2019-12-27 22:14:59 +08:00
if ( source . startsWith ( "webpack://" ) ) return source ;
2021-08-19 20:01:44 +08:00
return ` webpack:// ${ makePathsRelative (
context ,
source ,
associatedObjectForCache
) } ` ;
2019-11-11 22:25:03 +08:00
} ;
/ * *
* @ param { string } context absolute context path
2025-07-09 18:59:21 +08:00
* @ param { string | RawSourceMap } sourceMap a source map
2025-04-03 00:02:22 +08:00
* @ param { AssociatedObjectForCache = } associatedObjectForCache an object to which the cache will be attached
2025-07-09 18:59:21 +08:00
* @ returns { string | RawSourceMap } new source map
2019-11-11 22:25:03 +08:00
* /
const contextifySourceMap = ( context , sourceMap , associatedObjectForCache ) => {
2025-07-09 18:59:21 +08:00
if ( typeof sourceMap === "string" || ! Array . isArray ( sourceMap . sources ) ) {
return sourceMap ;
}
2020-01-19 15:58:22 +08:00
const { sourceRoot } = sourceMap ;
2025-03-12 09:56:14 +08:00
/** @type {(source: string) => string} */
2019-12-27 22:14:59 +08:00
const mapper = ! sourceRoot
? source => source
: sourceRoot . endsWith ( "/" )
2024-07-31 05:43:19 +08:00
? source =>
source . startsWith ( "/" )
? ` ${ sourceRoot . slice ( 0 , - 1 ) } ${ source } `
: ` ${ sourceRoot } ${ source } `
: source =>
source . startsWith ( "/" )
? ` ${ sourceRoot } ${ source } `
: ` ${ sourceRoot } / ${ source } ` ;
2019-11-11 22:25:03 +08:00
const newSources = sourceMap . sources . map ( source =>
2019-12-27 22:14:59 +08:00
contextifySourceUrl ( context , mapper ( source ) , associatedObjectForCache )
2019-11-11 22:25:03 +08:00
) ;
return {
... sourceMap ,
2019-12-27 22:14:59 +08:00
file : "x" ,
sourceRoot : undefined ,
2019-11-11 22:25:03 +08:00
sources : newSources
} ;
} ;
2018-11-07 21:03:25 +08:00
/ * *
* @ param { string | Buffer } input the input
* @ returns { string } the converted string
* /
const asString = input => {
if ( Buffer . isBuffer ( input ) ) {
2025-07-02 20:10:54 +08:00
return input . toString ( "utf8" ) ;
2016-01-04 04:42:56 +08:00
}
2018-11-07 21:03:25 +08:00
return input ;
2017-11-08 18:32:05 +08:00
} ;
2016-01-04 04:42:56 +08:00
2018-11-07 21:03:25 +08:00
/ * *
* @ param { string | Buffer } input the input
* @ returns { Buffer } the converted buffer
* /
const asBuffer = input => {
if ( ! Buffer . isBuffer ( input ) ) {
2025-07-02 20:10:54 +08:00
return Buffer . from ( input , "utf8" ) ;
2017-10-30 20:56:57 +08:00
}
2018-11-07 21:03:25 +08:00
return input ;
2017-10-30 20:56:57 +08:00
} ;
2017-03-25 05:17:47 +08:00
class NonErrorEmittedError extends WebpackError {
2024-08-06 11:08:48 +08:00
/ * *
2025-04-04 21:38:51 +08:00
* @ param { EXPECTED _ANY } error value which is not an instance of Error
2024-08-06 11:08:48 +08:00
* /
2017-03-22 20:00:57 +08:00
constructor ( error ) {
super ( ) ;
this . name = "NonErrorEmittedError" ;
2024-07-31 10:39:30 +08:00
this . message = ` (Emitted value instead of an instance of Error) ${ error } ` ;
2017-03-22 20:00:57 +08:00
}
}
2018-10-25 16:49:51 +08:00
makeSerializable (
NonErrorEmittedError ,
"webpack/lib/NormalModule" ,
"NonErrorEmittedError"
) ;
2025-07-09 18:59:21 +08:00
/** @typedef {[string | Buffer, string | RawSourceMap | undefined, PreparsedAst | undefined]} Result */
2025-03-05 02:05:18 +08:00
2018-11-12 21:13:55 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } NormalModuleCompilationHooks
2025-04-04 21:38:51 +08:00
* @ property { SyncHook < [ LoaderContext < EXPECTED _ANY > , NormalModule ] > } loader
* @ property { SyncHook < [ LoaderItem [ ] , NormalModule , LoaderContext < EXPECTED _ANY > ] > } beforeLoaders
2021-10-19 05:08:24 +08:00
* @ property { SyncHook < [ NormalModule ] > } beforeParse
* @ property { SyncHook < [ NormalModule ] > } beforeSnapshot
2024-08-07 23:22:25 +08:00
* @ property { HookMap < FakeHook < AsyncSeriesBailHook < [ string , NormalModule ] , string | Buffer | null >>> } readResourceForScheme
2025-04-04 21:38:51 +08:00
* @ property { HookMap < AsyncSeriesBailHook < [ LoaderContext < EXPECTED _ANY > ] , string | Buffer | null >> } readResource
2025-03-05 02:05:18 +08:00
* @ property { SyncWaterfallHook < [ Result , NormalModule ] > } processResult
2021-08-04 21:55:58 +08:00
* @ property { AsyncSeriesBailHook < [ NormalModule , NeedBuildContext ] , boolean > } needBuild
2018-11-12 21:13:55 +08:00
* /
2022-02-15 22:37:57 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } NormalModuleCreateData
2022-02-15 22:37:57 +08:00
* @ property { string = } layer an optional layer in which the module is
2025-07-09 18:59:21 +08:00
* @ property { ModuleTypes | "" } type module type . When deserializing , this is set to an empty string "" .
2022-02-15 22:37:57 +08:00
* @ 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
2025-05-13 21:03:58 +08:00
* @ property { ( ResourceSchemeData & Partial < ResolveRequest > ) = } resourceResolveData resource resolve data
2022-02-15 22:37:57 +08:00
* @ property { string } context context directory for resolving
* @ property { string = } matchResource path + query of the matched resource ( virtual )
* @ property { Parser } parser the parser used
2024-02-17 01:39:12 +08:00
* @ property { ParserOptions = } parserOptions the options of the parser used
2022-02-15 22:37:57 +08:00
* @ property { Generator } generator the generator used
2024-02-17 01:39:12 +08:00
* @ property { GeneratorOptions = } generatorOptions the options of the generator used
2022-02-15 22:37:57 +08:00
* @ property { ResolveOptions = } resolveOptions options used for resolving requests from this module
* /
2018-11-12 21:13:55 +08:00
/** @type {WeakMap<Compilation, NormalModuleCompilationHooks>} */
const compilationHooksMap = new WeakMap ( ) ;
2017-02-11 11:16:18 +08:00
class NormalModule extends Module {
2018-11-12 21:13:55 +08:00
/ * *
* @ 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 = {
2020-07-03 20:45:49 +08:00
loader : new SyncHook ( [ "loaderContext" , "module" ] ) ,
2020-07-31 23:38:33 +08:00
beforeLoaders : new SyncHook ( [ "loaders" , "module" , "loaderContext" ] ) ,
2021-10-19 05:08:24 +08:00
beforeParse : new SyncHook ( [ "module" ] ) ,
beforeSnapshot : new SyncHook ( [ "module" ] ) ,
2021-10-07 16:25:10 +08:00
// TODO webpack 6 deprecate
readResourceForScheme : new HookMap ( scheme => {
2024-08-06 11:08:48 +08:00
const hook =
/** @type {NormalModuleCompilationHooks} */
( hooks ) . readResource . for ( scheme ) ;
2021-10-07 16:25:10 +08:00
return createFakeHook (
2024-08-07 23:22:25 +08:00
/** @type {AsyncSeriesBailHook<[string, NormalModule], string | Buffer | null>} */ ( {
2021-10-07 16:25:10 +08:00
tap : ( options , fn ) =>
hook . tap ( options , loaderContext =>
2024-08-06 11:08:48 +08:00
fn (
loaderContext . resource ,
/** @type {NormalModule} */ ( loaderContext . _module )
)
2021-10-07 16:25:10 +08:00
) ,
tapAsync : ( options , fn ) =>
hook . tapAsync ( options , ( loaderContext , callback ) =>
2024-08-06 11:08:48 +08:00
fn (
loaderContext . resource ,
/** @type {NormalModule} */ ( loaderContext . _module ) ,
callback
)
2021-10-07 16:25:10 +08:00
) ,
tapPromise : ( options , fn ) =>
hook . tapPromise ( options , loaderContext =>
2024-08-06 11:08:48 +08:00
fn (
loaderContext . resource ,
/** @type {NormalModule} */ ( loaderContext . _module )
)
2021-10-07 16:25:10 +08:00
)
} )
) ;
} ) ,
readResource : new HookMap (
( ) => new AsyncSeriesBailHook ( [ "loaderContext" ] )
2021-08-04 21:55:58 +08:00
) ,
2025-03-05 02:05:18 +08:00
processResult : new SyncWaterfallHook ( [ "result" , "module" ] ) ,
2021-08-04 21:55:58 +08:00
needBuild : new AsyncSeriesBailHook ( [ "module" , "context" ] )
2018-11-12 21:13:55 +08:00
} ;
2024-02-17 01:39:12 +08:00
compilationHooksMap . set (
compilation ,
/** @type {NormalModuleCompilationHooks} */ ( hooks )
) ;
2018-11-12 21:13:55 +08:00
}
2024-02-17 01:39:12 +08:00
return /** @type {NormalModuleCompilationHooks} */ ( hooks ) ;
2018-11-12 21:13:55 +08:00
}
2019-11-20 17:58:58 +08:00
/ * *
2022-02-15 22:37:57 +08:00
* @ param { NormalModuleCreateData } options options object
2019-11-20 17:58:58 +08:00
* /
2018-01-24 06:09:26 +08:00
constructor ( {
2020-12-22 21:51:09 +08:00
layer ,
2018-01-24 06:09:26 +08:00
type ,
request ,
userRequest ,
rawRequest ,
loaders ,
resource ,
2021-05-19 14:48:10 +08:00
resourceResolveData ,
2021-08-06 00:47:24 +08:00
context ,
2018-06-01 20:54:54 +08:00
matchResource ,
2018-01-24 06:09:26 +08:00
parser ,
2021-03-15 17:29:51 +08:00
parserOptions ,
2018-01-24 06:09:26 +08:00
generator ,
2021-03-15 17:29:51 +08:00
generatorOptions ,
2020-07-03 20:45:49 +08:00
resolveOptions
2018-01-24 06:09:26 +08:00
} ) {
2021-08-06 00:47:24 +08:00
super ( type , context || getContext ( resource ) , layer ) ;
2017-11-06 20:02:35 +08:00
// Info from Factory
2018-11-07 21:03:25 +08:00
/** @type {string} */
2017-02-11 11:16:18 +08:00
this . request = request ;
2018-11-07 21:03:25 +08:00
/** @type {string} */
2017-02-11 11:16:18 +08:00
this . userRequest = userRequest ;
2018-11-07 21:03:25 +08:00
/** @type {string} */
2017-02-11 11:16:18 +08:00
this . rawRequest = rawRequest ;
2018-11-07 21:03:25 +08:00
/** @type {boolean} */
2019-07-16 19:16:27 +08:00
this . binary = /^(asset|webassembly)\b/ . test ( type ) ;
2024-02-17 01:39:12 +08:00
/** @type {undefined | Parser} */
2017-02-11 11:16:18 +08:00
this . parser = parser ;
2024-02-17 01:39:12 +08:00
/** @type {undefined | ParserOptions} */
2021-03-15 17:29:51 +08:00
this . parserOptions = parserOptions ;
2024-02-17 01:39:12 +08:00
/** @type {undefined | Generator} */
2018-01-24 06:09:26 +08:00
this . generator = generator ;
2024-02-17 01:39:12 +08:00
/** @type {undefined | GeneratorOptions} */
2021-03-15 17:29:51 +08:00
this . generatorOptions = generatorOptions ;
2019-11-20 17:58:58 +08:00
/** @type {string} */
2017-02-11 11:16:18 +08:00
this . resource = resource ;
2021-05-19 14:48:10 +08:00
this . resourceResolveData = resourceResolveData ;
2019-11-20 17:58:58 +08:00
/** @type {string | undefined} */
2018-06-01 20:54:54 +08:00
this . matchResource = matchResource ;
2020-01-16 21:48:52 +08:00
/** @type {LoaderItem[]} */
2017-02-11 11:16:18 +08:00
this . loaders = loaders ;
2018-11-07 21:03:25 +08:00
if ( resolveOptions !== undefined ) {
2019-11-20 17:58:58 +08:00
// already declared in super class
2018-11-07 21:03:25 +08:00
this . resolveOptions = resolveOptions ;
}
2017-11-06 20:02:35 +08:00
// Info from Build
2024-02-17 01:39:12 +08:00
/** @type {WebpackError | null} */
2017-02-11 11:16:18 +08:00
this . error = null ;
2024-02-17 01:39:12 +08:00
/ * *
* @ private
* @ type { Source | null }
* /
2017-02-11 11:16:18 +08:00
this . _source = null ;
2024-02-17 01:39:12 +08:00
/ * *
* @ private
2024-08-09 23:42:37 +08:00
* @ type { Map < string | undefined , number > | undefined }
2024-06-11 20:32:02 +08:00
* /
2019-11-08 19:46:37 +08:00
this . _sourceSizes = undefined ;
2024-02-17 01:39:12 +08:00
/ * *
* @ private
* @ type { undefined | SourceTypes }
2024-06-11 20:32:02 +08:00
* /
2021-05-18 22:54:16 +08:00
this . _sourceTypes = undefined ;
2017-11-06 20:02:35 +08:00
2017-12-07 00:26:02 +08:00
// Cache
this . _lastSuccessfulBuildMeta = { } ;
2018-09-12 00:47:55 +08:00
this . _forceBuild = true ;
2020-10-05 22:57:31 +08:00
this . _isEvaluatingSideEffects = false ;
2021-01-27 20:36:03 +08:00
/** @type {WeakSet<ModuleGraph> | undefined} */
this . _addedSideEffectsBailout = undefined ;
2025-07-09 18:59:21 +08:00
/** @type {GenerateContextData} */
2023-02-08 06:54:09 +08:00
this . _codeGeneratorData = new Map ( ) ;
2017-02-11 11:16:18 +08:00
}
2016-09-14 18:04:42 +08:00
2018-07-25 18:12:17 +08:00
/ * *
* @ returns { string } a unique identifier of the module
* /
2017-02-11 11:16:18 +08:00
identifier ( ) {
2020-12-22 21:51:09 +08:00
if ( this . layer === null ) {
2023-04-01 01:56:32 +08:00
if ( this . type === JAVASCRIPT _MODULE _TYPE _AUTO ) {
2021-07-17 04:16:06 +08:00
return this . request ;
}
2024-07-31 04:21:27 +08:00
return ` ${ this . type } | ${ this . request } ` ;
2020-12-22 21:51:09 +08:00
}
2024-07-31 04:21:27 +08:00
return ` ${ this . type } | ${ this . request } | ${ this . layer } ` ;
2017-02-11 11:16:18 +08:00
}
2016-01-04 04:42:56 +08:00
2018-07-25 18:12:17 +08:00
/ * *
* @ param { RequestShortener } requestShortener the request shortener
* @ returns { string } a user readable identifier of the module
* /
2017-02-11 11:16:18 +08:00
readableIdentifier ( requestShortener ) {
2024-08-09 23:42:37 +08:00
return /** @type {string} */ ( requestShortener . shorten ( this . userRequest ) ) ;
2017-02-11 11:16:18 +08:00
}
2016-01-04 04:42:56 +08:00
2018-07-20 22:24:35 +08:00
/ * *
* @ param { LibIdentOptions } options options
* @ returns { string | null } an identifier for library inclusion
* /
2017-02-11 11:16:18 +08:00
libIdent ( options ) {
2022-01-14 19:05:28 +08:00
let ident = contextify (
2019-01-19 20:12:43 +08:00
options . context ,
this . userRequest ,
options . associatedObjectForCache
) ;
2022-01-14 19:05:28 +08:00
if ( this . layer ) ident = ` ( ${ this . layer } )/ ${ ident } ` ;
return ident ;
2017-02-11 11:16:18 +08:00
}
2016-01-04 04:42:56 +08:00
2018-07-25 18:12:17 +08:00
/ * *
* @ returns { string | null } absolute path which should be used for condition matching ( usually the resource path )
* /
2017-02-11 11:16:18 +08:00
nameForCondition ( ) {
2018-06-01 20:54:54 +08:00
const resource = this . matchResource || this . resource ;
const idx = resource . indexOf ( "?" ) ;
2022-03-14 05:54:18 +08:00
if ( idx >= 0 ) return resource . slice ( 0 , idx ) ;
2018-06-01 20:54:54 +08:00
return resource ;
2017-02-11 11:16:18 +08:00
}
2013-01-31 01:49:25 +08:00
2018-07-25 18:12:17 +08:00
/ * *
* 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 }
* /
2018-03-28 22:19:15 +08:00
updateCacheModule ( module ) {
2018-10-09 20:30:59 +08:00
super . updateCacheModule ( module ) ;
2018-07-25 18:12:17 +08:00
const m = /** @type {NormalModule} */ ( module ) ;
2020-07-03 20:45:49 +08:00
this . binary = m . binary ;
2018-07-25 18:12:17 +08:00
this . request = m . request ;
this . userRequest = m . userRequest ;
this . rawRequest = m . rawRequest ;
this . parser = m . parser ;
2021-03-15 17:29:51 +08:00
this . parserOptions = m . parserOptions ;
2018-07-25 18:12:17 +08:00
this . generator = m . generator ;
2021-03-15 17:29:51 +08:00
this . generatorOptions = m . generatorOptions ;
2018-07-25 18:12:17 +08:00
this . resource = m . resource ;
2021-10-18 15:25:00 +08:00
this . resourceResolveData = m . resourceResolveData ;
2021-08-06 00:47:24 +08:00
this . context = m . context ;
2018-07-25 18:12:17 +08:00
this . matchResource = m . matchResource ;
this . loaders = m . loaders ;
2018-03-28 22:19:15 +08:00
}
2021-03-15 17:29:51 +08:00
/ * *
* Assuming this module is in the cache . Remove internal references to allow freeing some memory .
* /
cleanupForCache ( ) {
2021-07-22 15:32:55 +08:00
// 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 ( ) ;
2024-02-17 01:39:12 +08:00
for ( const type of /** @type {SourceTypes} */ ( this . _sourceTypes ) ) {
2021-07-22 15:32:55 +08:00
this . size ( type ) ;
}
2021-05-18 22:54:16 +08:00
}
2021-03-15 17:29:51 +08:00
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 .
2024-02-17 01:39:12 +08:00
* @ returns { UnsafeCacheData } cached data
2021-03-15 17:29:51 +08:00
* /
getUnsafeCacheData ( ) {
2025-03-11 10:03:41 +08:00
const data = super . getUnsafeCacheData ( ) ;
2021-03-15 17:29:51 +08:00
data . parserOptions = this . parserOptions ;
data . generatorOptions = this . generatorOptions ;
return data ;
}
2024-02-17 01:39:12 +08:00
/ * *
* restore unsafe cache data
2025-03-11 10:03:41 +08:00
* @ param { UnsafeCacheData } unsafeCacheData data from getUnsafeCacheData
2024-02-17 01:39:12 +08:00
* @ param { NormalModuleFactory } normalModuleFactory the normal module factory handling the unsafe caching
* /
2021-03-15 17:29:51 +08:00
restoreFromUnsafeCache ( unsafeCacheData , normalModuleFactory ) {
this . _restoreFromUnsafeCache ( unsafeCacheData , normalModuleFactory ) ;
}
/ * *
* restore unsafe cache data
2025-03-11 10:03:41 +08:00
* @ param { UnsafeCacheData } unsafeCacheData data from getUnsafeCacheData
2021-03-15 17:29:51 +08:00
* @ param { NormalModuleFactory } normalModuleFactory the normal module factory handling the unsafe caching
* /
_restoreFromUnsafeCache ( unsafeCacheData , normalModuleFactory ) {
2021-03-24 06:54:46 +08:00
super . _restoreFromUnsafeCache ( unsafeCacheData , normalModuleFactory ) ;
2021-03-15 17:29:51 +08:00
this . parserOptions = unsafeCacheData . parserOptions ;
this . parser = normalModuleFactory . getParser ( this . type , this . parserOptions ) ;
this . generatorOptions = unsafeCacheData . generatorOptions ;
this . generator = normalModuleFactory . getGenerator (
this . type ,
this . generatorOptions
) ;
2021-05-18 22:54:16 +08:00
// we assume the generator behaves identically and keep cached sourceTypes/Sizes
2021-03-15 17:29:51 +08:00
}
2018-11-07 21:03:25 +08:00
/ * *
2019-11-11 22:25:03 +08:00
* @ param { string } context the compilation context
2018-11-07 21:03:25 +08:00
* @ param { string } name the asset name
2024-02-17 01:39:12 +08:00
* @ param { string | Buffer } content the content
2025-06-03 01:18:59 +08:00
* @ param { ( string | RawSourceMap ) = } sourceMap an optional source map
2025-04-03 00:02:22 +08:00
* @ param { AssociatedObjectForCache = } associatedObjectForCache object for caching
2018-11-07 21:03:25 +08:00
* @ returns { Source } the created source
* /
2019-11-11 22:25:03 +08:00
createSourceForAsset (
context ,
name ,
content ,
sourceMap ,
associatedObjectForCache
) {
2020-10-26 21:41:46 +08:00
if ( sourceMap ) {
if (
typeof sourceMap === "string" &&
( this . useSourceMap || this . useSimpleSourceMap )
) {
return new OriginalSource (
content ,
contextifySourceUrl ( context , sourceMap , associatedObjectForCache )
) ;
}
2017-02-11 14:07:01 +08:00
2020-10-26 21:41:46 +08:00
if ( this . useSourceMap ) {
return new SourceMapSource (
content ,
name ,
2024-02-17 01:39:12 +08:00
contextifySourceMap (
context ,
2025-06-03 01:18:59 +08:00
/** @type {RawSourceMap} */
( sourceMap ) ,
2024-02-17 01:39:12 +08:00
associatedObjectForCache
)
2020-10-26 21:41:46 +08:00
) ;
}
2017-02-11 14:07:01 +08:00
}
2020-10-26 21:41:46 +08:00
return new RawSource ( content ) ;
2017-02-11 14:07:01 +08:00
}
2019-11-11 22:25:03 +08:00
/ * *
2024-02-17 01:39:12 +08:00
* @ private
* @ template T
2019-11-11 22:25:03 +08:00
* @ param { ResolverWithOptions } resolver a resolver
* @ param { WebpackOptions } options webpack options
* @ param { Compilation } compilation the compilation
* @ param { InputFileSystem } fs file system from reading
2021-10-19 05:08:24 +08:00
* @ param { NormalModuleCompilationHooks } hooks the hooks
2025-05-13 21:03:58 +08:00
* @ returns { import ( "../declarations/LoaderContext" ) . LoaderContext < T > } loader context
2019-11-11 22:25:03 +08:00
* /
2021-10-19 05:08:24 +08:00
_createLoaderContext ( resolver , options , compilation , fs , hooks ) {
2020-02-08 05:38:53 +08:00
const { requestShortener } = compilation . runtimeTemplate ;
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
const getCurrentLoaderName = ( ) => {
2025-05-13 21:03:58 +08:00
const currentLoader = this . getCurrentLoader (
/** @type {LoaderContext<EXPECTED_ANY>} */ ( loaderContext )
) ;
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
if ( ! currentLoader ) return "(not in loader scope)" ;
return requestShortener . shorten ( currentLoader . loader ) ;
} ;
2024-02-17 01:39:12 +08:00
/ * *
* @ returns { ResolveContext } resolve context
* /
2024-07-31 11:31:11 +08:00
const getResolveContext = ( ) => ( {
fileDependencies : {
2025-05-13 21:03:58 +08:00
add : d =>
/** @type {LoaderContext<EXPECTED_ANY>} */ (
loaderContext
) . addDependency ( d )
2024-07-31 11:31:11 +08:00
} ,
contextDependencies : {
2025-05-13 21:03:58 +08:00
add : d =>
/** @type {LoaderContext<EXPECTED_ANY>} */ (
loaderContext
) . addContextDependency ( d )
2024-07-31 11:31:11 +08:00
} ,
missingDependencies : {
2025-05-13 21:03:58 +08:00
add : d =>
/** @type {LoaderContext<EXPECTED_ANY>} */ (
loaderContext
) . addMissingDependency ( d )
2024-07-31 11:31:11 +08:00
}
} ) ;
2021-03-19 17:59:10 +08:00
const getAbsolutify = memoize ( ( ) =>
absolutify . bindCache ( compilation . compiler . root )
) ;
const getAbsolutifyInContext = memoize ( ( ) =>
2024-08-09 23:42:37 +08:00
absolutify . bindContextCache (
/** @type {string} */
( this . context ) ,
compilation . compiler . root
)
2021-03-19 17:59:10 +08:00
) ;
const getContextify = memoize ( ( ) =>
contextify . bindCache ( compilation . compiler . root )
) ;
const getContextifyInContext = memoize ( ( ) =>
2024-08-09 23:42:37 +08:00
contextify . bindContextCache (
/** @type {string} */
( this . context ) ,
compilation . compiler . root
)
2021-03-19 17:59:10 +08:00
) ;
const utils = {
2024-02-17 01:39:12 +08:00
/ * *
* @ param { string } context context
* @ param { string } request request
* @ returns { string } result
* /
2024-07-31 11:31:11 +08:00
absolutify : ( context , request ) =>
context === this . context
2021-03-19 17:59:10 +08:00
? getAbsolutifyInContext ( ) ( request )
2024-07-31 11:31:11 +08:00
: getAbsolutify ( ) ( context , request ) ,
2024-02-17 01:39:12 +08:00
/ * *
* @ param { string } context context
* @ param { string } request request
* @ returns { string } result
* /
2024-07-31 11:31:11 +08:00
contextify : ( context , request ) =>
context === this . context
2021-03-19 17:59:10 +08:00
? getContextifyInContext ( ) ( request )
2024-07-31 11:31:11 +08:00
: getContextify ( ) ( context , request ) ,
2024-02-17 01:39:12 +08:00
/ * *
2025-04-26 01:43:01 +08:00
* @ param { HashFunction = } type type
2024-02-17 01:39:12 +08:00
* @ returns { Hash } hash
* /
2024-07-31 11:31:11 +08:00
createHash : type =>
2024-08-09 23:42:37 +08:00
createHash (
type ||
2025-04-26 01:43:01 +08:00
/** @type {HashFunction} */
2024-08-09 23:42:37 +08:00
( compilation . outputOptions . hashFunction )
)
2021-03-19 17:59:10 +08:00
} ;
2024-02-17 02:03:51 +08:00
/** @type {import("../declarations/LoaderContext").NormalModuleLoaderContext<T>} */
2017-02-11 11:16:18 +08:00
const loaderContext = {
version : 2 ,
2025-02-27 18:00:17 +08:00
/ * *
2025-04-16 22:04:11 +08:00
* @ param { import ( "../declarations/LoaderContext" ) . Schema = } schema schema
2025-02-27 18:00:17 +08:00
* @ returns { T } options
* /
2020-01-16 21:48:52 +08:00
getOptions : schema => {
2025-05-13 21:03:58 +08:00
const loader = this . getCurrentLoader (
/** @type {LoaderContext<EXPECTED_ANY>} */ ( loaderContext )
) ;
2019-11-21 21:36:31 +08:00
2024-02-17 01:39:12 +08:00
let { options } = /** @type {LoaderItem} */ ( loader ) ;
2019-11-21 21:36:31 +08:00
2020-01-16 21:48:52 +08:00
if ( typeof options === "string" ) {
2022-03-14 05:54:18 +08:00
if ( options . startsWith ( "{" ) && options . endsWith ( "}" ) ) {
2019-11-21 21:36:31 +08:00
try {
2020-01-16 21:48:52 +08:00
options = parseJson ( options ) ;
2024-07-31 15:37:05 +08:00
} catch ( err ) {
2024-08-09 23:42:37 +08:00
throw new Error (
` Cannot parse string options: ${ /** @type {Error} */ ( err ) . message } `
) ;
2019-11-21 21:36:31 +08:00
}
} else {
2020-01-16 21:48:52 +08:00
options = querystring . parse ( options , "&" , "=" , {
maxKeys : 0
} ) ;
2019-11-21 21:36:31 +08:00
}
}
2020-01-16 21:48:52 +08:00
if ( options === null || options === undefined ) {
options = { } ;
2019-11-21 21:36:31 +08:00
}
2020-01-16 21:48:52 +08:00
if ( schema ) {
2020-01-17 19:17:53 +08:00
let name = "Loader" ;
let baseDataPath = "options" ;
let match ;
if ( schema . title && ( match = /^(.+) (.+)$/ . exec ( schema . title ) ) ) {
[ , name , baseDataPath ] = match ;
}
2025-04-04 21:38:51 +08:00
getValidate ( ) ( schema , /** @type {EXPECTED_OBJECT} */ ( options ) , {
2020-01-17 19:17:53 +08:00
name ,
baseDataPath
2020-01-16 21:48:52 +08:00
} ) ;
}
2019-11-21 21:36:31 +08:00
2025-04-04 21:38:51 +08:00
return /** @type {T} */ ( options ) ;
2019-11-21 21:36:31 +08:00
} ,
2018-02-25 09:00:20 +08:00
emitWarning : warning => {
2018-05-29 20:50:40 +08:00
if ( ! ( warning instanceof Error ) ) {
2017-03-22 20:00:57 +08:00
warning = new NonErrorEmittedError ( warning ) ;
2018-05-29 20:50:40 +08:00
}
2019-11-08 19:43:05 +08:00
this . addWarning (
2018-10-30 05:18:08 +08:00
new ModuleWarning ( warning , {
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
from : getCurrentLoaderName ( )
2018-03-02 17:57:46 +08:00
} )
) ;
2017-02-11 11:16:18 +08:00
} ,
2018-02-25 09:00:20 +08:00
emitError : error => {
2018-05-29 20:50:40 +08:00
if ( ! ( error instanceof Error ) ) {
error = new NonErrorEmittedError ( error ) ;
}
2019-11-08 19:43:05 +08:00
this . addError (
2018-10-30 05:18:08 +08:00
new ModuleError ( error , {
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
from : getCurrentLoaderName ( )
2018-03-02 17:57:46 +08:00
} )
) ;
2017-02-11 11:16:18 +08:00
} ,
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
getLogger : name => {
2025-05-13 21:03:58 +08:00
const currentLoader = this . getCurrentLoader (
/** @type {LoaderContext<EXPECTED_ANY>} */ ( loaderContext )
) ;
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
return compilation . getLogger ( ( ) =>
[ currentLoader && currentLoader . loader , name , this . identifier ( ) ]
. filter ( Boolean )
2019-07-23 15:28:06 +08:00
. join ( "|" )
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
) ;
} ,
2017-02-12 21:08:41 +08:00
resolve ( context , request , callback ) {
2019-11-26 05:10:47 +08:00
resolver . resolve ( { } , context , request , getResolveContext ( ) , callback ) ;
2017-02-11 11:16:18 +08:00
} ,
2018-12-03 19:42:28 +08:00
getResolve ( options ) {
const child = options ? resolver . withOptions ( options ) : resolver ;
2025-02-27 18:00:17 +08:00
return /** @type {ReturnType<import("../declarations/LoaderContext").NormalModuleLoaderContext<T>["getResolve"]>} */ (
( context , request , callback ) => {
if ( callback ) {
2019-11-26 05:10:47 +08:00
child . resolve (
{ } ,
context ,
request ,
getResolveContext ( ) ,
2025-02-27 18:00:17 +08:00
callback
2019-11-26 05:10:47 +08:00
) ;
2025-02-27 18:00:17 +08:00
} else {
return new Promise ( ( resolve , reject ) => {
child . resolve (
{ } ,
context ,
request ,
getResolveContext ( ) ,
( err , result ) => {
if ( err ) reject ( err ) ;
else resolve ( result ) ;
}
) ;
} ) ;
}
2018-12-03 19:42:28 +08:00
}
2025-02-27 18:00:17 +08:00
) ;
2018-12-03 19:42:28 +08:00
} ,
2019-09-11 17:13:46 +08:00
emitFile : ( name , content , sourceMap , assetInfo ) => {
2024-02-17 01:39:12 +08:00
const buildInfo = /** @type {BuildInfo} */ ( this . buildInfo ) ;
if ( ! buildInfo . assets ) {
buildInfo . assets = Object . create ( null ) ;
buildInfo . assetsInfo = new Map ( ) ;
2018-05-29 20:50:40 +08:00
}
2024-02-17 01:39:12 +08:00
const assets =
/** @type {NonNullable<KnownBuildInfo["assets"]>} */
( buildInfo . assets ) ;
const assetsInfo =
/** @type {NonNullable<KnownBuildInfo["assetsInfo"]>} */
( buildInfo . assetsInfo ) ;
assets [ name ] = this . createSourceForAsset (
/** @type {string} */ ( options . context ) ,
2018-02-25 09:00:20 +08:00
name ,
content ,
2019-11-11 22:25:03 +08:00
sourceMap ,
compilation . compiler . root
2018-02-25 09:00:20 +08:00
) ;
2024-02-17 01:39:12 +08:00
assetsInfo . set ( name , assetInfo ) ;
2017-02-11 12:32:48 +08:00
} ,
2020-08-23 03:54:34 +08:00
addBuildDependency : dep => {
2024-02-17 01:39:12 +08:00
const buildInfo = /** @type {BuildInfo} */ ( this . buildInfo ) ;
if ( buildInfo . buildDependencies === undefined ) {
buildInfo . buildDependencies = new LazySet ( ) ;
2020-08-23 03:54:34 +08:00
}
2024-02-17 01:39:12 +08:00
buildInfo . buildDependencies . add ( dep ) ;
2020-08-23 03:54:34 +08:00
} ,
2021-03-19 17:59:10 +08:00
utils ,
2024-02-17 01:39:12 +08:00
rootContext : /** @type {string} */ ( options . context ) ,
2017-02-11 12:32:48 +08:00
webpack : true ,
2024-07-31 11:11:11 +08:00
sourceMap : Boolean ( this . useSourceMap ) ,
2019-05-17 03:50:31 +08:00
mode : options . mode || "production" ,
2025-04-26 01:43:01 +08:00
hashFunction : /** @type {string} */ ( options . output . hashFunction ) ,
2024-10-02 05:18:10 +08:00
hashDigest : /** @type {string} */ ( options . output . hashDigest ) ,
hashDigestLength : /** @type {number} */ ( options . output . hashDigestLength ) ,
hashSalt : /** @type {string} */ ( options . output . hashSalt ) ,
2017-02-11 12:32:48 +08:00
_module : this ,
_compilation : compilation ,
_compiler : compilation . compiler ,
2024-07-31 04:09:42 +08:00
fs
2017-02-11 11:16:18 +08:00
} ;
2017-02-11 12:32:48 +08:00
2020-09-09 21:54:13 +08:00
Object . assign ( loaderContext , options . loader ) ;
2025-05-13 21:03:58 +08:00
// After `hooks.loader.call` is called, the loaderContext is typed as LoaderContext<EXPECTED_ANY>
2025-04-04 21:38:51 +08:00
hooks . loader . call (
/** @type {LoaderContext<EXPECTED_ANY>} */
( loaderContext ) ,
this
) ;
2018-11-12 21:13:55 +08:00
2025-05-13 21:03:58 +08:00
return /** @type {LoaderContext<EXPECTED_ANY>} */ ( loaderContext ) ;
2017-02-11 12:32:48 +08:00
}
2024-02-17 01:39:12 +08:00
// TODO remove `loaderContext` in webpack@6
/ * *
2025-05-13 21:03:58 +08:00
* @ param { LoaderContext < EXPECTED _ANY > } loaderContext loader context
2024-02-17 01:39:12 +08:00
* @ param { number } index index
* @ returns { LoaderItem | null } loader
* /
2018-06-05 17:58:10 +08:00
getCurrentLoader ( loaderContext , index = loaderContext . loaderIndex ) {
2018-03-02 17:57:46 +08:00
if (
this . loaders &&
this . loaders . length &&
2018-06-05 17:58:10 +08:00
index < this . loaders . length &&
index >= 0 &&
this . loaders [ index ]
2018-03-02 17:57:46 +08:00
) {
2018-06-05 17:58:10 +08:00
return this . loaders [ index ] ;
2018-03-02 17:57:46 +08:00
}
return null ;
}
2018-11-07 21:03:25 +08:00
/ * *
2019-11-11 22:25:03 +08:00
* @ param { string } context the compilation context
2018-11-07 21:03:25 +08:00
* @ param { string | Buffer } content the content
2025-07-09 18:59:21 +08:00
* @ param { ( string | RawSourceMap | null ) = } sourceMap an optional source map
2025-04-03 00:02:22 +08:00
* @ param { AssociatedObjectForCache = } associatedObjectForCache object for caching
2018-11-07 21:03:25 +08:00
* @ returns { Source } the created source
* /
2019-11-11 22:25:03 +08:00
createSource ( context , content , sourceMap , associatedObjectForCache ) {
2018-11-07 21:03:25 +08:00
if ( Buffer . isBuffer ( content ) ) {
return new RawSource ( content ) ;
}
2017-02-11 12:57:52 +08:00
// if there is no identifier return raw source
2018-02-25 09:00:20 +08:00
if ( ! this . identifier ) {
2018-11-07 21:03:25 +08:00
return new RawSource ( content ) ;
2017-02-11 12:57:52 +08:00
}
// from here on we assume we have an identifier
const identifier = this . identifier ( ) ;
2018-02-25 09:00:20 +08:00
if ( this . useSourceMap && sourceMap ) {
2019-11-11 22:25:03 +08:00
return new SourceMapSource (
content ,
contextifySourceUrl ( context , identifier , associatedObjectForCache ) ,
2025-07-09 18:59:21 +08:00
contextifySourceMap ( context , sourceMap , associatedObjectForCache )
2019-11-11 22:25:03 +08:00
) ;
2017-02-11 12:57:52 +08:00
}
2020-10-26 21:41:46 +08:00
if ( this . useSourceMap || this . useSimpleSourceMap ) {
return new OriginalSource (
content ,
contextifySourceUrl ( context , identifier , associatedObjectForCache )
) ;
}
return new RawSource ( content ) ;
2017-02-11 12:57:52 +08:00
}
2019-11-11 22:25:03 +08:00
/ * *
* @ param { WebpackOptions } options webpack options
* @ param { Compilation } compilation the compilation
* @ param { ResolverWithOptions } resolver the resolver
* @ param { InputFileSystem } fs the file system
2021-10-19 05:08:24 +08:00
* @ param { NormalModuleCompilationHooks } hooks the hooks
2025-03-12 09:56:14 +08:00
* @ param { BuildCallback } callback callback function
2019-11-11 22:25:03 +08:00
* @ returns { void }
* /
2021-10-19 05:08:24 +08:00
_doBuild ( options , compilation , resolver , fs , hooks , callback ) {
const loaderContext = this . _createLoaderContext (
2018-02-25 09:00:20 +08:00
resolver ,
options ,
compilation ,
2021-10-19 05:08:24 +08:00
fs ,
hooks
2018-02-25 09:00:20 +08:00
) ;
2024-08-09 23:42:37 +08:00
/ * *
* @ param { Error | null } err err
2025-07-09 18:59:21 +08:00
* @ param { ( Result | null ) = } result _ result
2024-08-09 23:42:37 +08:00
* @ returns { void }
* /
2025-07-09 18:59:21 +08:00
const processResult = ( err , result _ ) => {
2019-01-09 20:23:26 +08:00
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 ) ;
}
2025-03-05 02:05:18 +08:00
const result = hooks . processResult . call (
2025-07-09 18:59:21 +08:00
/** @type {Result} */
( result _ ) ,
2025-03-05 02:05:18 +08:00
this
) ;
2019-01-09 20:23:26 +08:00
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
2024-07-31 05:43:19 +08:00
)
2019-01-09 20:23:26 +08:00
: "unknown"
} ) didn ' t return a Buffer or String `
) ;
const error = new ModuleBuildError ( err ) ;
return callback ( error ) ;
}
2024-06-20 00:33:28 +08:00
const isBinaryModule =
this . generatorOptions && this . generatorOptions . binary !== undefined
? this . generatorOptions . binary
: this . binary ;
2024-06-05 04:05:28 +08:00
2019-01-09 20:23:26 +08:00
this . _source = this . createSource (
2024-02-17 01:39:12 +08:00
/** @type {string} */ ( options . context ) ,
2024-06-05 04:05:28 +08:00
isBinaryModule ? asBuffer ( source ) : asString ( source ) ,
2019-11-11 22:25:03 +08:00
sourceMap ,
compilation . compiler . root
2019-01-09 20:23:26 +08:00
) ;
2019-11-08 19:46:37 +08:00
if ( this . _sourceSizes !== undefined ) this . _sourceSizes . clear ( ) ;
2019-01-09 20:23:26 +08:00
this . _ast =
typeof extraInfo === "object" &&
extraInfo !== null &&
extraInfo . webpackAST !== undefined
? extraInfo . webpackAST
: null ;
return callback ( ) ;
} ;
2024-02-17 01:39:12 +08:00
const buildInfo = /** @type {BuildInfo} */ ( this . buildInfo ) ;
buildInfo . fileDependencies = new LazySet ( ) ;
buildInfo . contextDependencies = new LazySet ( ) ;
buildInfo . missingDependencies = new LazySet ( ) ;
buildInfo . cacheable = true ;
2021-10-01 16:24:52 +08:00
2021-03-22 17:17:17 +08:00
try {
2024-08-06 11:08:48 +08:00
hooks . beforeLoaders . call (
this . loaders ,
this ,
2025-04-04 21:38:51 +08:00
/** @type {LoaderContext<EXPECTED_ANY>} */
( loaderContext )
2024-08-06 11:08:48 +08:00
) ;
2021-03-22 17:17:17 +08:00
} catch ( err ) {
2024-10-02 05:18:10 +08:00
processResult ( /** @type {Error} */ ( err ) ) ;
2021-03-22 17:17:17 +08:00
return ;
}
2021-10-01 16:24:52 +08:00
if ( this . loaders . length > 0 ) {
2024-02-17 01:39:12 +08:00
/** @type {BuildInfo} */
( this . buildInfo ) . buildDependencies = new LazySet ( ) ;
2021-10-01 16:24:52 +08:00
}
2018-02-25 09:00:20 +08:00
runLoaders (
{
resource : this . resource ,
loaders : this . loaders ,
context : loaderContext ,
2024-10-02 05:18:10 +08:00
/ * *
2025-05-13 21:03:58 +08:00
* @ param { LoaderContext < EXPECTED _ANY > } loaderContext the loader context
2024-10-02 05:18:10 +08:00
* @ param { string } resourcePath the resource Path
* @ param { ( err : Error | null , result ? : string | Buffer ) => void } callback callback
* /
2021-08-04 21:55:58 +08:00
processResource : ( loaderContext , resourcePath , callback ) => {
const resource = loaderContext . resource ;
2020-07-03 20:45:49 +08:00
const scheme = getScheme ( resource ) ;
2021-10-07 16:25:10 +08:00
hooks . readResource
. for ( scheme )
. callAsync ( loaderContext , ( err , result ) => {
if ( err ) return callback ( err ) ;
if ( typeof result !== "string" && ! result ) {
2024-08-09 23:42:37 +08:00
return callback (
new UnhandledSchemeError (
/** @type {string} */
( scheme ) ,
resource
)
) ;
2021-10-07 16:25:10 +08:00
}
return callback ( null , result ) ;
} ) ;
2020-07-03 20:45:49 +08:00
}
2018-02-25 09:00:20 +08:00
} ,
( err , result ) => {
2021-03-25 21:52:12 +08:00
// Cleanup loaderContext to avoid leaking memory in ICs
2021-05-11 15:31:46 +08:00
loaderContext . _compilation =
loaderContext . _compiler =
loaderContext . _module =
loaderContext . fs =
2025-04-03 00:02:22 +08:00
/** @type {EXPECTED_ANY} */
( undefined ) ;
2021-03-25 21:52:12 +08:00
2019-01-09 20:23:26 +08:00
if ( ! result ) {
2024-02-17 01:39:12 +08:00
/** @type {BuildInfo} */
( this . buildInfo ) . cacheable = false ;
2021-03-15 17:29:51 +08:00
return processResult (
2019-01-09 20:23:26 +08:00
err || new Error ( "No result from loader-runner processing" ) ,
null
2018-02-25 09:00:20 +08:00
) ;
}
2024-02-17 01:39:12 +08:00
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 ) ;
2020-08-23 03:54:34 +08:00
for ( const loader of this . loaders ) {
2024-02-17 01:39:12 +08:00
const buildDependencies =
/** @type {NonNullable<KnownBuildInfo["buildDependencies"]>} */
( buildInfo . buildDependencies ) ;
buildDependencies . add ( loader . loader ) ;
2018-02-25 09:00:20 +08:00
}
2024-02-17 01:39:12 +08:00
buildInfo . cacheable = buildInfo . cacheable && result . cacheable ;
2020-08-23 03:54:34 +08:00
processResult ( err , result . result ) ;
2017-02-11 11:16:18 +08:00
}
2018-02-25 09:00:20 +08:00
) ;
2014-05-17 06:31:52 +08:00
}
2015-07-13 06:20:09 +08:00
2018-11-07 21:03:25 +08:00
/ * *
* @ param { WebpackError } error the error
* @ returns { void }
* /
2017-02-13 18:38:55 +08:00
markModuleAsErrored ( error ) {
2018-02-26 10:48:51 +08:00
// Restore build meta from successful build to keep importing state
2019-06-19 19:16:05 +08:00
this . buildMeta = { ... this . _lastSuccessfulBuildMeta } ;
2017-02-13 18:38:55 +08:00
this . error = error ;
2019-11-08 19:43:05 +08:00
this . addError ( error ) ;
2017-02-11 11:41:26 +08:00
}
2024-02-17 01:39:12 +08:00
/ * *
2025-05-01 22:36:51 +08:00
* @ param { Exclude < NoParse , EXPECTED _ANY [ ] > } rule rule
2024-02-17 01:39:12 +08:00
* @ param { string } content content
* @ returns { boolean } result
* /
2017-02-14 18:14:57 +08:00
applyNoParseRule ( rule , content ) {
2017-02-11 13:59:58 +08:00
// must start with "rule" if rule is a string
2018-02-25 09:00:20 +08:00
if ( typeof rule === "string" ) {
2020-01-19 15:59:39 +08:00
return content . startsWith ( rule ) ;
2017-02-11 13:59:58 +08:00
}
2017-06-03 08:28:54 +08:00
2018-02-25 09:00:20 +08:00
if ( typeof rule === "function" ) {
2017-06-03 08:28:54 +08:00
return rule ( content ) ;
}
2017-02-11 13:59:58 +08:00
// we assume rule is a regexp
2017-02-14 18:14:57 +08:00
return rule . test ( content ) ;
2017-02-11 13:59:58 +08:00
}
2024-02-17 01:39:12 +08:00
/ * *
2025-05-01 22:36:51 +08:00
* @ param { undefined | NoParse } noParseRule no parse rule
2024-02-17 01:39:12 +08:00
* @ 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
* /
2017-02-16 05:01:09 +08:00
shouldPreventParsing ( noParseRule , request ) {
2017-02-11 13:59:58 +08:00
// if no noParseRule exists, return false
// the module !must! be parsed.
2018-02-25 09:00:20 +08:00
if ( ! noParseRule ) {
2017-02-11 13:59:58 +08:00
return false ;
}
// we only have one rule to check
2018-02-25 09:00:20 +08:00
if ( ! Array . isArray ( noParseRule ) ) {
2017-02-11 13:59:58 +08:00
// returns "true" if the module is !not! to be parsed
return this . applyNoParseRule ( noParseRule , request ) ;
}
2018-02-25 09:00:20 +08:00
for ( let i = 0 ; i < noParseRule . length ; i ++ ) {
2017-02-11 13:59:58 +08:00
const rule = noParseRule [ i ] ;
// early exit on first truthy match
// this module is !not! to be parsed
2018-02-25 09:00:20 +08:00
if ( this . applyNoParseRule ( rule , request ) ) {
2017-02-11 13:59:58 +08:00
return true ;
}
}
// no match found, so this module !should! be parsed
return false ;
}
2024-02-17 01:39:12 +08:00
/ * *
* @ param { Compilation } compilation compilation
* @ private
* /
2018-04-27 20:24:43 +08:00
_initBuildHash ( compilation ) {
2024-08-09 23:42:37 +08:00
const hash = createHash (
2025-04-26 01:43:01 +08:00
/** @type {HashFunction} */
2024-08-09 23:42:37 +08:00
( compilation . outputOptions . hashFunction )
) ;
2018-04-27 20:24:43 +08:00
if ( this . _source ) {
hash . update ( "source" ) ;
2020-08-03 02:09:36 +08:00
this . _source . updateHash ( hash ) ;
2018-04-27 20:24:43 +08:00
}
hash . update ( "meta" ) ;
hash . update ( JSON . stringify ( this . buildMeta ) ) ;
2024-02-17 01:39:12 +08:00
/** @type {BuildInfo} */
( this . buildInfo ) . hash = /** @type {string} */ ( hash . digest ( "hex" ) ) ;
2018-04-27 20:24:43 +08:00
}
2018-07-25 18:12:17 +08:00
/ * *
2019-11-11 22:25:03 +08:00
* @ param { WebpackOptions } options webpack options
2018-07-25 18:12:17 +08:00
* @ param { Compilation } compilation the compilation
2019-11-11 22:25:03 +08:00
* @ param { ResolverWithOptions } resolver the resolver
* @ param { InputFileSystem } fs the file system
2025-03-12 09:56:14 +08:00
* @ param { BuildCallback } callback callback function
2018-07-25 18:12:17 +08:00
* @ returns { void }
* /
2017-02-11 11:16:18 +08:00
build ( options , compilation , resolver , fs , callback ) {
2018-09-12 00:47:55 +08:00
this . _forceBuild = false ;
2017-02-11 11:16:18 +08:00
this . _source = null ;
2019-11-08 19:46:37 +08:00
if ( this . _sourceSizes !== undefined ) this . _sourceSizes . clear ( ) ;
2021-05-18 22:54:16 +08:00
this . _sourceTypes = undefined ;
2017-11-03 18:12:45 +08:00
this . _ast = null ;
2017-02-11 11:16:18 +08:00
this . error = null ;
2019-11-08 19:43:05 +08:00
this . clearWarningsAndErrors ( ) ;
2019-11-08 22:39:44 +08:00
this . clearDependenciesAndBlocks ( ) ;
2017-12-06 19:09:17 +08:00
this . buildMeta = { } ;
this . buildInfo = {
cacheable : false ,
2018-11-17 01:18:44 +08:00
parsed : true ,
2018-12-31 19:50:45 +08:00
fileDependencies : undefined ,
contextDependencies : undefined ,
2019-01-09 20:23:26 +08:00
missingDependencies : undefined ,
2020-08-23 03:54:34 +08:00
buildDependencies : undefined ,
2021-03-15 21:28:49 +08:00
valueDependencies : undefined ,
2018-12-31 19:50:45 +08:00
hash : undefined ,
2019-09-11 17:13:46 +08:00
assets : undefined ,
assetsInfo : undefined
2017-12-06 19:09:17 +08:00
} ;
2016-06-21 03:46:27 +08:00
2021-05-19 22:18:37 +08:00
const startTime = compilation . compiler . fsStartTime || Date . now ( ) ;
2020-08-23 03:54:34 +08:00
2021-10-19 05:08:24 +08:00
const hooks = NormalModule . getCompilationHooks ( compilation ) ;
return this . _doBuild ( options , compilation , resolver , fs , hooks , err => {
2017-02-11 13:59:58 +08:00
// if we have an error mark module as failed and exit
2018-02-25 09:00:20 +08:00
if ( err ) {
2017-02-13 18:38:55 +08:00
this . markModuleAsErrored ( err ) ;
2018-04-27 20:24:43 +08:00
this . _initBuildHash ( compilation ) ;
2017-02-11 11:41:26 +08:00
return callback ( ) ;
}
2017-02-11 13:59:58 +08:00
2024-02-17 01:39:12 +08:00
/ * *
* @ param { Error } e error
* @ returns { void }
* /
2017-12-14 08:21:44 +08:00
const handleParseError = e => {
2024-02-17 01:39:12 +08:00
const source = /** @type {Source} */ ( this . _source ) . source ( ) ;
2019-06-03 21:23:13 +08:00
const loaders = this . loaders . map ( item =>
2024-02-17 01:39:12 +08:00
contextify (
/** @type {string} */ ( options . context ) ,
item . loader ,
compilation . compiler . root
)
2019-06-03 21:23:13 +08:00
) ;
2020-04-29 02:22:50 +08:00
const error = new ModuleParseError ( source , e , loaders , this . type ) ;
2017-12-14 08:21:44 +08:00
this . markModuleAsErrored ( error ) ;
2018-04-27 20:24:43 +08:00
this . _initBuildHash ( compilation ) ;
2017-12-14 08:21:44 +08:00
return callback ( ) ;
} ;
2024-02-17 01:39:12 +08:00
const handleParseResult = ( ) => {
2018-10-18 15:20:59 +08:00
this . dependencies . sort (
concatComparators (
2025-07-14 18:56:27 +08:00
// For HarmonyImportSideEffectDependency and HarmonyImportSpecifierDependency, we should prioritize import order to match the behavior of running modules directly in a JS engine without a bundler.
// For other types like ConstDependency, we can instead prioritize usage order.
// https://github.com/webpack/webpack/pull/19686
compareSelect (
a =>
/** @type {HarmonyImportSideEffectDependency | HarmonyImportSpecifierDependency} */ (
a
) . sourceOrder ,
compareNumbers
) ,
2018-10-18 15:20:59 +08:00
compareSelect ( a => a . loc , compareLocations ) ,
keepOriginalOrder ( this . dependencies )
)
) ;
2018-04-27 20:24:43 +08:00
this . _initBuildHash ( compilation ) ;
2024-02-17 01:39:12 +08:00
this . _lastSuccessfulBuildMeta =
/** @type {BuildMeta} */
( this . buildMeta ) ;
2020-08-23 03:54:34 +08:00
return handleBuildDone ( ) ;
} ;
const handleBuildDone = ( ) => {
2021-10-19 05:08:24 +08:00
try {
hooks . beforeSnapshot . call ( this ) ;
} catch ( err ) {
2024-08-07 23:22:25 +08:00
this . markModuleAsErrored ( /** @type {WebpackError} */ ( err ) ) ;
2021-10-19 05:08:24 +08:00
return callback ( ) ;
}
2020-08-26 06:36:16 +08:00
const snapshotOptions = compilation . options . snapshot . module ;
2024-02-17 01:39:12 +08:00
const { cacheable } = /** @type {BuildInfo} */ ( this . buildInfo ) ;
if ( ! cacheable || ! snapshotOptions ) {
2020-08-23 03:54:34 +08:00
return callback ( ) ;
}
2021-01-07 20:06:44 +08:00
// add warning for all non-absolute paths in fileDependencies, etc
// This makes it easier to find problems with watching and/or caching
2024-02-17 01:39:12 +08:00
/** @type {undefined | Set<string>} */
2024-07-31 06:15:03 +08:00
let nonAbsoluteDependencies ;
2024-02-17 01:39:12 +08:00
/ * *
* @ param { LazySet < string > } deps deps
* /
2021-01-07 20:06:44 +08:00
const checkDependencies = deps => {
for ( const dep of deps ) {
if ( ! ABSOLUTE _PATH _REGEX . test ( dep ) ) {
2025-07-02 20:10:54 +08:00
if ( nonAbsoluteDependencies === undefined ) {
2021-01-07 20:06:44 +08:00
nonAbsoluteDependencies = new Set ( ) ;
2025-07-02 20:10:54 +08:00
}
2021-01-07 20:06:44 +08:00
nonAbsoluteDependencies . add ( dep ) ;
deps . delete ( dep ) ;
try {
const depWithoutGlob = dep . replace ( /[\\/]?\*.*$/ , "" ) ;
const absolute = join (
compilation . fileSystemInfo . fs ,
2024-08-09 23:42:37 +08:00
/** @type {string} */
( this . context ) ,
2021-01-07 20:06:44 +08:00
depWithoutGlob
) ;
if ( absolute !== dep && ABSOLUTE _PATH _REGEX . test ( absolute ) ) {
( depWithoutGlob !== dep
2024-02-17 01:39:12 +08:00
? /** @type {NonNullable<KnownBuildInfo["contextDependencies"]>} */
2024-07-31 05:43:19 +08:00
(
2025-03-05 02:05:18 +08:00
/** @type {BuildInfo} */
( this . buildInfo ) . contextDependencies
2024-07-31 05:43:19 +08:00
)
2021-01-07 20:06:44 +08:00
: deps
) . add ( absolute ) ;
}
2024-07-31 15:37:05 +08:00
} catch ( _err ) {
2021-01-07 20:06:44 +08:00
// ignore
}
}
}
} ;
2024-02-17 01:39:12 +08:00
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 ) ;
2021-01-07 20:06:44 +08:00
if ( nonAbsoluteDependencies !== undefined ) {
2021-05-11 15:31:46 +08:00
const InvalidDependenciesModuleWarning =
getInvalidDependenciesModuleWarning ( ) ;
2021-01-07 20:06:44 +08:00
this . addWarning (
new InvalidDependenciesModuleWarning ( this , nonAbsoluteDependencies )
) ;
}
2020-08-23 03:54:34 +08:00
// convert file/context/missingDependencies into filesystem snapshot
compilation . fileSystemInfo . createSnapshot (
startTime ,
2024-02-17 01:39:12 +08:00
fileDependencies ,
contextDependencies ,
missingDependencies ,
2020-08-26 06:36:16 +08:00
snapshotOptions ,
2020-08-23 03:54:34 +08:00
( err , snapshot ) => {
if ( err ) {
this . markModuleAsErrored ( err ) ;
return ;
}
2024-02-17 01:39:12 +08:00
buildInfo . fileDependencies = undefined ;
buildInfo . contextDependencies = undefined ;
buildInfo . missingDependencies = undefined ;
buildInfo . snapshot = snapshot ;
2020-08-23 03:54:34 +08:00
return callback ( ) ;
}
) ;
2017-12-14 08:21:44 +08:00
} ;
2021-10-19 05:08:24 +08:00
try {
hooks . beforeParse . call ( this ) ;
} catch ( err ) {
2024-08-07 23:22:25 +08:00
this . markModuleAsErrored ( /** @type {WebpackError} */ ( err ) ) ;
2021-10-19 05:08:24 +08:00
this . _initBuildHash ( compilation ) ;
return callback ( ) ;
}
2020-08-26 16:03:00 +08:00
// 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
2024-02-17 01:39:12 +08:00
/** @type {BuildInfo} */
( this . buildInfo ) . parsed = false ;
2020-08-26 16:03:00 +08:00
this . _initBuildHash ( compilation ) ;
return handleBuildDone ( ) ;
}
2017-02-11 11:16:18 +08:00
try {
2024-02-17 01:39:12 +08:00
const source = /** @type {Source} */ ( this . _source ) . source ( ) ;
2024-02-17 01:51:18 +08:00
/** @type {Parser} */
( this . parser ) . parse ( this . _ast || source , {
2021-08-10 17:23:30 +08:00
source ,
2019-11-30 03:24:13 +08:00
current : this ,
module : this ,
2024-07-31 04:09:42 +08:00
compilation ,
options
2019-11-30 03:24:13 +08:00
} ) ;
2024-07-31 15:37:05 +08:00
} catch ( parseErr ) {
handleParseError ( /** @type {Error} */ ( parseErr ) ) ;
2019-11-30 03:24:13 +08:00
return ;
2017-02-11 11:16:18 +08:00
}
2024-02-17 01:39:12 +08:00
handleParseResult ( ) ;
2015-07-13 06:20:09 +08:00
} ) ;
2013-01-31 01:49:25 +08:00
}
2015-07-13 06:20:09 +08:00
2020-09-12 04:37:57 +08:00
/ * *
2020-09-15 16:07:04 +08:00
* @ param { ConcatenationBailoutReasonContext } context context
2020-09-12 04:37:57 +08:00
* @ returns { string | undefined } reason why this module can ' t be concatenated , undefined when it can be concatenated
* /
2020-09-15 16:07:04 +08:00
getConcatenationBailoutReason ( context ) {
2024-02-17 01:51:18 +08:00
return /** @type {Generator} */ (
this . generator
) . getConcatenationBailoutReason ( this , context ) ;
2020-09-12 04:37:57 +08:00
}
2020-10-05 22:57:31 +08:00
/ * *
* @ 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 ) {
2020-12-15 21:40:54 +08:00
if ( this . factoryMeta !== undefined ) {
if ( this . factoryMeta . sideEffectFree ) return false ;
if ( this . factoryMeta . sideEffectFree === false ) return true ;
}
2020-10-05 22:57:31 +08:00
if ( this . buildMeta !== undefined && this . buildMeta . sideEffectFree ) {
2025-07-02 20:10:54 +08:00
if ( this . _isEvaluatingSideEffects ) {
2020-10-05 22:57:31 +08:00
return ModuleGraphConnection . CIRCULAR _CONNECTION ;
2025-07-02 20:10:54 +08:00
}
2020-10-05 22:57:31 +08:00
this . _isEvaluatingSideEffects = true ;
/** @type {ConnectionState} */
let current = false ;
for ( const dep of this . dependencies ) {
const state = dep . getModuleEvaluationSideEffectsState ( moduleGraph ) ;
if ( state === true ) {
2021-01-27 20:36:03 +08:00
if (
this . _addedSideEffectsBailout === undefined
? ( ( this . _addedSideEffectsBailout = new WeakSet ( ) ) , true )
: ! this . _addedSideEffectsBailout . has ( moduleGraph )
) {
2020-11-29 00:30:32 +08:00
this . _addedSideEffectsBailout . add ( moduleGraph ) ;
moduleGraph
. getOptimizationBailout ( this )
. push (
( ) =>
` Dependency ( ${
dep . type
} ) with side effects at $ { formatLocation ( dep . loc ) } `
) ;
}
2020-10-05 22:57:31 +08:00
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 ;
}
2024-07-31 04:21:27 +08:00
return true ;
2020-10-05 22:57:31 +08:00
}
2018-12-03 22:00:32 +08:00
/ * *
2024-02-17 01:39:12 +08:00
* @ returns { SourceTypes } types available ( do not mutate )
2018-12-03 22:00:32 +08:00
* /
getSourceTypes ( ) {
2021-05-18 22:54:16 +08:00
if ( this . _sourceTypes === undefined ) {
2024-02-17 01:51:18 +08:00
this . _sourceTypes = /** @type {Generator} */ ( this . generator ) . getTypes (
this
) ;
2021-05-18 22:54:16 +08:00
}
return this . _sourceTypes ;
2018-12-03 22:00:32 +08:00
}
2018-11-15 00:31:32 +08:00
/ * *
2019-10-09 04:29:46 +08:00
* @ param { CodeGenerationContext } context context for code generation
* @ returns { CodeGenerationResult } result
2018-11-15 00:31:32 +08:00
* /
2019-10-09 04:29:46 +08:00
codeGeneration ( {
2018-07-24 23:35:36 +08:00
dependencyTemplates ,
runtimeTemplate ,
moduleGraph ,
2020-07-28 00:09:48 +08:00
chunkGraph ,
2020-09-11 15:06:24 +08:00
runtime ,
2021-11-30 19:55:51 +08:00
concatenationScope ,
2022-03-17 16:44:50 +08:00
codeGenerationResults ,
sourceTypes
2018-07-24 23:35:36 +08:00
} ) {
2018-11-15 00:31:32 +08:00
/** @type {Set<string>} */
const runtimeRequirements = new Set ( ) ;
2024-02-17 01:39:12 +08:00
const { parsed } = /** @type {BuildInfo} */ ( this . buildInfo ) ;
if ( ! parsed ) {
2018-11-17 01:18:44 +08:00
runtimeRequirements . add ( RuntimeGlobals . module ) ;
runtimeRequirements . add ( RuntimeGlobals . exports ) ;
2019-08-27 02:21:07 +08:00
runtimeRequirements . add ( RuntimeGlobals . thisAsExports ) ;
2018-11-17 01:18:44 +08:00
}
2024-07-31 11:31:11 +08:00
const getData = ( ) => this . _codeGeneratorData ;
2020-10-11 07:17:03 +08:00
2019-10-09 04:29:46 +08:00
const sources = new Map ( ) ;
2022-03-17 16:44:50 +08:00
for ( const type of sourceTypes || chunkGraph . getModuleSourceTypes ( this ) ) {
2025-04-05 22:37:35 +08:00
// TODO webpack@6 make generateError required
const generator =
/** @type {Generator & { generateError?: GenerateErrorFn }} */
( this . generator ) ;
2019-10-09 04:29:46 +08:00
const source = this . error
2025-04-05 22:37:35 +08:00
? generator . generateError
? generator . generateError ( this . error , this , {
dependencyTemplates ,
runtimeTemplate ,
moduleGraph ,
chunkGraph ,
runtimeRequirements ,
runtime ,
concatenationScope ,
codeGenerationResults ,
getData ,
type
} )
: new RawSource (
` throw new Error( ${ JSON . stringify ( this . error . message ) } ); `
)
: generator . generate ( this , {
2019-10-09 04:29:46 +08:00
dependencyTemplates ,
runtimeTemplate ,
moduleGraph ,
chunkGraph ,
runtimeRequirements ,
2020-07-28 00:09:48 +08:00
runtime ,
2020-09-11 15:06:24 +08:00
concatenationScope ,
2021-11-30 19:55:51 +08:00
codeGenerationResults ,
2020-10-11 07:17:03 +08:00
getData ,
2019-10-09 04:29:46 +08:00
type
2024-07-31 05:43:19 +08:00
} ) ;
2019-10-09 04:29:46 +08:00
2019-11-20 17:48:38 +08:00
if ( source ) {
sources . set ( type , new CachedSource ( source ) ) ;
}
2019-10-09 04:29:46 +08:00
}
/** @type {CodeGenerationResult} */
2018-11-15 00:31:32 +08:00
const resultEntry = {
2019-10-09 04:29:46 +08:00
sources ,
2020-10-11 07:17:03 +08:00
runtimeRequirements ,
2023-02-08 07:11:50 +08:00
data : this . _codeGeneratorData
2019-10-09 04:29:46 +08:00
} ;
2018-11-15 00:31:32 +08:00
return resultEntry ;
2013-01-31 01:49:25 +08:00
}
2018-07-25 18:20:35 +08:00
/ * *
* @ returns { Source | null } the original source for the module before webpack transformation
* /
2017-04-03 15:48:55 +08:00
originalSource ( ) {
return this . _source ;
}
2017-04-03 15:33:11 +08:00
2018-09-12 00:47:55 +08:00
/ * *
* @ returns { void }
* /
invalidateBuild ( ) {
this . _forceBuild = true ;
}
2018-07-25 18:38:34 +08:00
/ * *
2018-09-26 15:14:44 +08:00
* @ param { NeedBuildContext } context context info
2025-03-12 09:56:14 +08:00
* @ param { NeedBuildCallback } callback callback function , returns true , if the module needs a rebuild
2018-09-26 15:14:44 +08:00
* @ returns { void }
2018-07-25 18:38:34 +08:00
* /
2021-08-04 21:55:58 +08:00
needBuild ( context , callback ) {
const { fileSystemInfo , compilation , valueCacheVersions } = context ;
2018-09-12 00:47:55 +08:00
// build if enforced
2018-09-26 15:14:44 +08:00
if ( this . _forceBuild ) return callback ( null , true ) ;
2018-09-12 00:47:55 +08:00
2018-09-26 15:14:44 +08:00
// always try to build in case of an error
if ( this . error ) return callback ( null , true ) ;
2017-11-06 20:02:35 +08:00
2024-02-17 01:39:12 +08:00
const { cacheable , snapshot , valueDependencies } =
/** @type {BuildInfo} */ ( this . buildInfo ) ;
2018-09-26 15:14:44 +08:00
// always build when module is not cacheable
2024-02-17 01:39:12 +08:00
if ( ! cacheable ) return callback ( null , true ) ;
2018-09-26 15:14:44 +08:00
2020-01-28 21:01:19 +08:00
// build when there is no snapshot to check
2024-02-17 01:39:12 +08:00
if ( ! snapshot ) return callback ( null , true ) ;
2020-01-28 21:01:19 +08:00
2021-03-15 21:28:49 +08:00
// build when valueDependencies have changed
2021-04-12 18:21:49 +08:00
if ( valueDependencies ) {
2021-03-15 21:28:49 +08:00
if ( ! valueCacheVersions ) return callback ( null , true ) ;
2021-04-12 18:21:49 +08:00
for ( const [ key , value ] of valueDependencies ) {
2021-03-15 21:28:49 +08:00
if ( value === undefined ) return callback ( null , true ) ;
const current = valueCacheVersions . get ( key ) ;
2021-04-12 18:21:49 +08:00
if (
value !== current &&
( typeof value === "string" ||
typeof current === "string" ||
current === undefined ||
! isSubset ( value , current ) )
) {
return callback ( null , true ) ;
}
2021-03-15 21:28:49 +08:00
}
}
2019-01-09 20:23:26 +08:00
// check snapshot for validity
2024-02-17 01:39:12 +08:00
fileSystemInfo . checkSnapshotValid ( snapshot , ( err , valid ) => {
2021-08-04 21:55:58 +08:00
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"
)
) ;
}
2024-07-31 11:11:11 +08:00
callback ( null , Boolean ( needBuild ) ) ;
2021-08-04 21:55:58 +08:00
} ) ;
2019-01-09 20:23:26 +08:00
} ) ;
2017-02-11 11:16:18 +08:00
}
2013-01-31 01:49:25 +08:00
2018-07-25 18:12:17 +08:00
/ * *
2018-12-04 18:23:40 +08:00
* @ param { string = } type the source type for which the size should be estimated
2019-05-13 18:29:29 +08:00
* @ returns { number } the estimated size of the module ( must be non - zero )
2018-07-25 18:12:17 +08:00
* /
2018-12-04 18:23:40 +08:00
size ( type ) {
2019-11-08 19:46:37 +08:00
const cachedSize =
this . _sourceSizes === undefined ? undefined : this . _sourceSizes . get ( type ) ;
2019-09-26 05:51:38 +08:00
if ( cachedSize !== undefined ) {
return cachedSize ;
2019-09-20 08:44:49 +08:00
}
2024-02-17 01:51:18 +08:00
const size = Math . max (
1 ,
/** @type {Generator} */ ( this . generator ) . getSize ( this , type )
) ;
2019-11-08 19:46:37 +08:00
if ( this . _sourceSizes === undefined ) {
this . _sourceSizes = new Map ( ) ;
}
2019-09-26 05:51:38 +08:00
this . _sourceSizes . set ( type , size ) ;
return size ;
2017-02-11 11:16:18 +08:00
}
2020-08-23 03:54:34 +08:00
/ * *
* @ 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
) {
2024-02-17 01:39:12 +08:00
const { snapshot , buildDependencies : buildDeps } =
/** @type {BuildInfo} */ ( this . buildInfo ) ;
2020-08-23 03:54:34 +08:00
if ( snapshot ) {
fileDependencies . addAll ( snapshot . getFileIterable ( ) ) ;
contextDependencies . addAll ( snapshot . getContextIterable ( ) ) ;
missingDependencies . addAll ( snapshot . getMissingIterable ( ) ) ;
} else {
const {
fileDependencies : fileDeps ,
contextDependencies : contextDeps ,
missingDependencies : missingDeps
2024-02-17 01:39:12 +08:00
} = /** @type {BuildInfo} */ ( this . buildInfo ) ;
2020-08-25 02:37:12 +08:00
if ( fileDeps !== undefined ) fileDependencies . addAll ( fileDeps ) ;
if ( contextDeps !== undefined ) contextDependencies . addAll ( contextDeps ) ;
if ( missingDeps !== undefined ) missingDependencies . addAll ( missingDeps ) ;
2020-08-23 03:54:34 +08:00
}
2020-08-25 02:37:12 +08:00
if ( buildDeps !== undefined ) {
2020-08-23 03:54:34 +08:00
buildDependencies . addAll ( buildDeps ) ;
}
}
2018-07-21 00:17:51 +08:00
/ * *
* @ param { Hash } hash the hash used to track dependencies
2020-07-28 00:09:48 +08:00
* @ param { UpdateHashContext } context context
2018-07-21 00:17:51 +08:00
* @ returns { void }
* /
2020-07-28 00:09:48 +08:00
updateHash ( hash , context ) {
2025-04-23 10:06:20 +08:00
const buildInfo = /** @type {BuildInfo} */ ( this . buildInfo ) ;
hash . update (
/** @type {string} */
( buildInfo . hash )
) ;
2024-08-06 11:08:48 +08:00
/** @type {Generator} */
( this . generator ) . updateHash ( hash , {
2020-07-28 01:36:06 +08:00
module : this ,
... context
} ) ;
2020-07-28 00:09:48 +08:00
super . updateHash ( hash , context ) ;
2017-02-11 11:16:18 +08:00
}
2018-10-09 20:30:59 +08:00
2023-04-12 02:57:43 +08:00
/ * *
* @ param { ObjectSerializerContext } context context
* /
2018-10-09 20:30:59 +08:00
serialize ( context ) {
const { write } = context ;
// deserialize
write ( this . _source ) ;
write ( this . error ) ;
write ( this . _lastSuccessfulBuildMeta ) ;
write ( this . _forceBuild ) ;
2023-02-08 06:54:09 +08:00
write ( this . _codeGeneratorData ) ;
2018-10-09 20:30:59 +08:00
super . serialize ( context ) ;
}
2024-10-24 11:02:20 +08:00
/ * *
* @ param { ObjectDeserializerContext } context context
2025-05-13 21:03:58 +08:00
* @ returns { NormalModule } module
2024-10-24 11:02:20 +08:00
* /
2018-10-09 20:30:59 +08:00
static deserialize ( context ) {
const obj = new NormalModule ( {
2020-12-22 21:51:09 +08:00
// will be deserialized by Module
2024-10-24 11:02:20 +08:00
layer : /** @type {EXPECTED_ANY} */ ( null ) ,
2020-07-03 20:45:49 +08:00
type : "" ,
2020-12-22 21:51:09 +08:00
// will be filled by updateCacheModule
2020-07-03 20:45:49 +08:00
resource : "" ,
2021-08-06 00:47:24 +08:00
context : "" ,
2024-10-24 11:02:20 +08:00
request : /** @type {EXPECTED_ANY} */ ( null ) ,
userRequest : /** @type {EXPECTED_ANY} */ ( null ) ,
rawRequest : /** @type {EXPECTED_ANY} */ ( null ) ,
loaders : /** @type {EXPECTED_ANY} */ ( null ) ,
matchResource : /** @type {EXPECTED_ANY} */ ( null ) ,
parser : /** @type {EXPECTED_ANY} */ ( null ) ,
parserOptions : /** @type {EXPECTED_ANY} */ ( null ) ,
generator : /** @type {EXPECTED_ANY} */ ( null ) ,
generatorOptions : /** @type {EXPECTED_ANY} */ ( null ) ,
resolveOptions : /** @type {EXPECTED_ANY} */ ( null )
2018-10-09 20:30:59 +08:00
} ) ;
obj . deserialize ( context ) ;
return obj ;
}
2023-04-12 02:57:43 +08:00
/ * *
* @ param { ObjectDeserializerContext } context context
* /
2018-10-09 20:30:59 +08:00
deserialize ( context ) {
const { read } = context ;
this . _source = read ( ) ;
this . error = read ( ) ;
this . _lastSuccessfulBuildMeta = read ( ) ;
this . _forceBuild = read ( ) ;
2023-02-08 06:54:09 +08:00
this . _codeGeneratorData = read ( ) ;
2018-10-09 20:30:59 +08:00
super . deserialize ( context ) ;
}
2017-02-11 11:16:18 +08:00
}
2018-10-09 20:30:59 +08:00
makeSerializable ( NormalModule , "webpack/lib/NormalModule" ) ;
2017-02-11 11:16:18 +08:00
module . exports = NormalModule ;