12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const vm = require("vm");
- const eslintScope = require("eslint-scope");
- const { SyncBailHook, SyncHook, SyncWaterfallHook } = require("tapable");
- const {
- CachedSource,
- ConcatSource,
- OriginalSource,
- PrefixSource,
- RawSource,
- ReplaceSource
- } = require("webpack-sources");
- const Compilation = require("../Compilation");
- const { tryRunOrWebpackError } = require("../HookWebpackError");
- const HotUpdateChunk = require("../HotUpdateChunk");
- const InitFragment = require("../InitFragment");
- const {
- JAVASCRIPT_MODULE_TYPE_AUTO,
- JAVASCRIPT_MODULE_TYPE_DYNAMIC,
- JAVASCRIPT_MODULE_TYPE_ESM,
- WEBPACK_MODULE_TYPE_RUNTIME
- } = require("../ModuleTypeConstants");
- const NormalModule = require("../NormalModule");
- const RuntimeGlobals = require("../RuntimeGlobals");
- const Template = require("../Template");
- const { last, someInIterable } = require("../util/IterableHelpers");
- const StringXor = require("../util/StringXor");
- const { compareModulesByIdOrIdentifier } = require("../util/comparators");
- const {
- RESERVED_NAMES,
- addScopeSymbols,
- findNewName,
- getAllReferences,
- getPathInAst,
- getUsedNamesInScopeInfo
- } = require("../util/concatenate");
- const createHash = require("../util/createHash");
- const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
- const removeBOM = require("../util/removeBOM");
- const { intersectRuntime } = require("../util/runtime");
- const JavascriptGenerator = require("./JavascriptGenerator");
- const JavascriptParser = require("./JavascriptParser");
- /** @typedef {import("eslint-scope").Reference} Reference */
- /** @typedef {import("eslint-scope").Scope} Scope */
- /** @typedef {import("eslint-scope").Variable} Variable */
- /** @typedef {import("estree").Program} Program */
- /** @typedef {import("webpack-sources").Source} Source */
- /** @typedef {import("../../declarations/WebpackOptions").HashFunction} HashFunction */
- /** @typedef {import("../../declarations/WebpackOptions").Output} OutputOptions */
- /** @typedef {import("../Chunk")} Chunk */
- /** @typedef {import("../ChunkGraph")} ChunkGraph */
- /** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
- /** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
- /** @typedef {import("../Compilation").ExecuteModuleObject} ExecuteModuleObject */
- /** @typedef {import("../Compiler")} Compiler */
- /** @typedef {import("../DependencyTemplates")} DependencyTemplates */
- /** @typedef {import("../Entrypoint")} Entrypoint */
- /** @typedef {import("../Module")} Module */
- /** @typedef {import("../Module").BuildInfo} BuildInfo */
- /** @typedef {import("../ModuleGraph")} ModuleGraph */
- /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
- /** @typedef {import("../TemplatedPathPlugin").TemplatePath} TemplatePath */
- /** @typedef {import("../WebpackError")} WebpackError */
- /** @typedef {import("../javascript/JavascriptParser").Range} Range */
- /** @typedef {import("../util/Hash")} Hash */
- /**
- * @param {Chunk} chunk a chunk
- * @param {ChunkGraph} chunkGraph the chunk graph
- * @returns {boolean} true, when a JS file is needed for this chunk
- */
- const chunkHasJs = (chunk, chunkGraph) => {
- if (chunkGraph.getNumberOfEntryModules(chunk) > 0) return true;
- return Boolean(
- chunkGraph.getChunkModulesIterableBySourceType(chunk, "javascript")
- );
- };
- /**
- * @param {Chunk} chunk a chunk
- * @param {ChunkGraph} chunkGraph the chunk graph
- * @returns {boolean} true, when a JS file is needed for this chunk
- */
- const chunkHasRuntimeOrJs = (chunk, chunkGraph) => {
- if (
- chunkGraph.getChunkModulesIterableBySourceType(
- chunk,
- WEBPACK_MODULE_TYPE_RUNTIME
- )
- ) {
- return true;
- }
- return Boolean(
- chunkGraph.getChunkModulesIterableBySourceType(chunk, "javascript")
- );
- };
- /**
- * @param {Module} module a module
- * @param {string} code the code
- * @returns {string} generated code for the stack
- */
- const printGeneratedCodeForStack = (module, code) => {
- const lines = code.split("\n");
- const n = `${lines.length}`.length;
- return `\n\nGenerated code for ${module.identifier()}\n${lines
- .map(
- /**
- * @param {string} line the line
- * @param {number} i the index
- * @param {string[]} _lines the lines
- * @returns {string} the line with line number
- */
- (line, i, _lines) => {
- const iStr = `${i + 1}`;
- return `${" ".repeat(n - iStr.length)}${iStr} | ${line}`;
- }
- )
- .join("\n")}`;
- };
- /**
- * @typedef {object} RenderContext
- * @property {Chunk} chunk the chunk
- * @property {DependencyTemplates} dependencyTemplates the dependency templates
- * @property {RuntimeTemplate} runtimeTemplate the runtime template
- * @property {ModuleGraph} moduleGraph the module graph
- * @property {ChunkGraph} chunkGraph the chunk graph
- * @property {CodeGenerationResults} codeGenerationResults results of code generation
- * @property {boolean | undefined} strictMode rendering in strict context
- */
- /**
- * @typedef {object} MainRenderContext
- * @property {Chunk} chunk the chunk
- * @property {DependencyTemplates} dependencyTemplates the dependency templates
- * @property {RuntimeTemplate} runtimeTemplate the runtime template
- * @property {ModuleGraph} moduleGraph the module graph
- * @property {ChunkGraph} chunkGraph the chunk graph
- * @property {CodeGenerationResults} codeGenerationResults results of code generation
- * @property {string} hash hash to be used for render call
- * @property {boolean | undefined} strictMode rendering in strict context
- */
- /**
- * @typedef {object} ChunkRenderContext
- * @property {Chunk} chunk the chunk
- * @property {DependencyTemplates} dependencyTemplates the dependency templates
- * @property {RuntimeTemplate} runtimeTemplate the runtime template
- * @property {ModuleGraph} moduleGraph the module graph
- * @property {ChunkGraph} chunkGraph the chunk graph
- * @property {CodeGenerationResults} codeGenerationResults results of code generation
- * @property {InitFragment<ChunkRenderContext>[]} chunkInitFragments init fragments for the chunk
- * @property {boolean | undefined} strictMode rendering in strict context
- */
- /**
- * @typedef {object} RenderBootstrapContext
- * @property {Chunk} chunk the chunk
- * @property {CodeGenerationResults} codeGenerationResults results of code generation
- * @property {RuntimeTemplate} runtimeTemplate the runtime template
- * @property {ModuleGraph} moduleGraph the module graph
- * @property {ChunkGraph} chunkGraph the chunk graph
- * @property {string} hash hash to be used for render call
- */
- /** @typedef {RenderContext & { inlined: boolean }} StartupRenderContext */
- /**
- * @typedef {object} CompilationHooks
- * @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModuleContent
- * @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModuleContainer
- * @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModulePackage
- * @property {SyncWaterfallHook<[Source, RenderContext]>} renderChunk
- * @property {SyncWaterfallHook<[Source, RenderContext]>} renderMain
- * @property {SyncWaterfallHook<[Source, RenderContext]>} renderContent
- * @property {SyncWaterfallHook<[Source, RenderContext]>} render
- * @property {SyncWaterfallHook<[Source, Module, StartupRenderContext]>} renderStartup
- * @property {SyncWaterfallHook<[string, RenderBootstrapContext]>} renderRequire
- * @property {SyncBailHook<[Module, RenderBootstrapContext], string | void>} inlineInRuntimeBailout
- * @property {SyncBailHook<[Module, RenderContext], string | void>} embedInRuntimeBailout
- * @property {SyncBailHook<[RenderContext], string | void>} strictRuntimeBailout
- * @property {SyncHook<[Chunk, Hash, ChunkHashContext]>} chunkHash
- * @property {SyncBailHook<[Chunk, RenderContext], boolean | void>} useSourceMap
- */
- /** @type {WeakMap<Compilation, CompilationHooks>} */
- const compilationHooksMap = new WeakMap();
- const PLUGIN_NAME = "JavascriptModulesPlugin";
- /** @typedef {{ header: string[], beforeStartup: string[], startup: string[], afterStartup: string[], allowInlineStartup: boolean }} Bootstrap */
- class JavascriptModulesPlugin {
- /**
- * @param {Compilation} compilation the compilation
- * @returns {CompilationHooks} 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 = {
- renderModuleContent: new SyncWaterfallHook([
- "source",
- "module",
- "renderContext"
- ]),
- renderModuleContainer: new SyncWaterfallHook([
- "source",
- "module",
- "renderContext"
- ]),
- renderModulePackage: new SyncWaterfallHook([
- "source",
- "module",
- "renderContext"
- ]),
- render: new SyncWaterfallHook(["source", "renderContext"]),
- renderContent: new SyncWaterfallHook(["source", "renderContext"]),
- renderStartup: new SyncWaterfallHook([
- "source",
- "module",
- "startupRenderContext"
- ]),
- renderChunk: new SyncWaterfallHook(["source", "renderContext"]),
- renderMain: new SyncWaterfallHook(["source", "renderContext"]),
- renderRequire: new SyncWaterfallHook(["code", "renderContext"]),
- inlineInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
- embedInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
- strictRuntimeBailout: new SyncBailHook(["renderContext"]),
- chunkHash: new SyncHook(["chunk", "hash", "context"]),
- useSourceMap: new SyncBailHook(["chunk", "renderContext"])
- };
- compilationHooksMap.set(compilation, hooks);
- }
- return hooks;
- }
- constructor(options = {}) {
- this.options = options;
- /** @type {WeakMap<Source, { source: Source, needModule:boolean, needExports: boolean, needRequire: boolean, needThisAsExports: boolean, needStrict: boolean | undefined }>} */
- this._moduleFactoryCache = new WeakMap();
- }
- /**
- * Apply the plugin
- * @param {Compiler} compiler the compiler instance
- * @returns {void}
- */
- apply(compiler) {
- compiler.hooks.compilation.tap(
- PLUGIN_NAME,
- (compilation, { normalModuleFactory }) => {
- const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
- for (const type of [
- JAVASCRIPT_MODULE_TYPE_AUTO,
- JAVASCRIPT_MODULE_TYPE_DYNAMIC,
- JAVASCRIPT_MODULE_TYPE_ESM
- ]) {
- normalModuleFactory.hooks.createParser
- .for(type)
- .tap(PLUGIN_NAME, _options => {
- switch (type) {
- case JAVASCRIPT_MODULE_TYPE_AUTO: {
- return new JavascriptParser("auto");
- }
- case JAVASCRIPT_MODULE_TYPE_DYNAMIC: {
- return new JavascriptParser("script");
- }
- case JAVASCRIPT_MODULE_TYPE_ESM: {
- return new JavascriptParser("module");
- }
- }
- });
- normalModuleFactory.hooks.createGenerator
- .for(type)
- .tap(PLUGIN_NAME, () => new JavascriptGenerator());
- NormalModule.getCompilationHooks(compilation).processResult.tap(
- PLUGIN_NAME,
- (result, module) => {
- if (module.type === type) {
- const [source, ...rest] = result;
- return [removeBOM(source), ...rest];
- }
- return result;
- }
- );
- }
- compilation.hooks.renderManifest.tap(PLUGIN_NAME, (result, options) => {
- const {
- hash,
- chunk,
- chunkGraph,
- moduleGraph,
- runtimeTemplate,
- dependencyTemplates,
- outputOptions,
- codeGenerationResults
- } = options;
- const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null;
- const filenameTemplate =
- JavascriptModulesPlugin.getChunkFilenameTemplate(
- chunk,
- outputOptions
- );
- let render;
- if (hotUpdateChunk) {
- render = () =>
- this.renderChunk(
- {
- chunk,
- dependencyTemplates,
- runtimeTemplate,
- moduleGraph,
- chunkGraph,
- codeGenerationResults,
- strictMode: runtimeTemplate.isModule()
- },
- hooks
- );
- } else if (chunk.hasRuntime()) {
- if (!chunkHasRuntimeOrJs(chunk, chunkGraph)) {
- return result;
- }
- render = () =>
- this.renderMain(
- {
- hash,
- chunk,
- dependencyTemplates,
- runtimeTemplate,
- moduleGraph,
- chunkGraph,
- codeGenerationResults,
- strictMode: runtimeTemplate.isModule()
- },
- hooks,
- compilation
- );
- } else {
- if (!chunkHasJs(chunk, chunkGraph)) {
- return result;
- }
- render = () =>
- this.renderChunk(
- {
- chunk,
- dependencyTemplates,
- runtimeTemplate,
- moduleGraph,
- chunkGraph,
- codeGenerationResults,
- strictMode: runtimeTemplate.isModule()
- },
- hooks
- );
- }
- result.push({
- render,
- filenameTemplate,
- pathOptions: {
- hash,
- runtime: chunk.runtime,
- chunk,
- contentHashType: "javascript"
- },
- info: {
- javascriptModule: compilation.runtimeTemplate.isModule()
- },
- identifier: hotUpdateChunk
- ? `hotupdatechunk${chunk.id}`
- : `chunk${chunk.id}`,
- hash: chunk.contentHash.javascript
- });
- return result;
- });
- compilation.hooks.chunkHash.tap(PLUGIN_NAME, (chunk, hash, context) => {
- hooks.chunkHash.call(chunk, hash, context);
- if (chunk.hasRuntime()) {
- this.updateHashWithBootstrap(
- hash,
- {
- hash: "0000",
- chunk,
- codeGenerationResults: context.codeGenerationResults,
- chunkGraph: context.chunkGraph,
- moduleGraph: context.moduleGraph,
- runtimeTemplate: context.runtimeTemplate
- },
- hooks
- );
- }
- });
- compilation.hooks.contentHash.tap(PLUGIN_NAME, chunk => {
- const {
- chunkGraph,
- codeGenerationResults,
- moduleGraph,
- runtimeTemplate,
- outputOptions: {
- hashSalt,
- hashDigest,
- hashDigestLength,
- hashFunction
- }
- } = compilation;
- const hash = createHash(/** @type {HashFunction} */ (hashFunction));
- if (hashSalt) hash.update(hashSalt);
- if (chunk.hasRuntime()) {
- this.updateHashWithBootstrap(
- hash,
- {
- hash: "0000",
- chunk,
- codeGenerationResults,
- chunkGraph: compilation.chunkGraph,
- moduleGraph: compilation.moduleGraph,
- runtimeTemplate: compilation.runtimeTemplate
- },
- hooks
- );
- } else {
- hash.update(`${chunk.id} `);
- hash.update(chunk.ids ? chunk.ids.join(",") : "");
- }
- hooks.chunkHash.call(chunk, hash, {
- chunkGraph,
- codeGenerationResults,
- moduleGraph,
- runtimeTemplate
- });
- const modules = chunkGraph.getChunkModulesIterableBySourceType(
- chunk,
- "javascript"
- );
- if (modules) {
- const xor = new StringXor();
- for (const m of modules) {
- xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
- }
- xor.updateHash(hash);
- }
- const runtimeModules = chunkGraph.getChunkModulesIterableBySourceType(
- chunk,
- WEBPACK_MODULE_TYPE_RUNTIME
- );
- if (runtimeModules) {
- const xor = new StringXor();
- for (const m of runtimeModules) {
- xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
- }
- xor.updateHash(hash);
- }
- const digest = /** @type {string} */ (hash.digest(hashDigest));
- chunk.contentHash.javascript = nonNumericOnlyHash(
- digest,
- /** @type {number} */
- (hashDigestLength)
- );
- });
- compilation.hooks.additionalTreeRuntimeRequirements.tap(
- PLUGIN_NAME,
- (chunk, set, { chunkGraph }) => {
- if (
- !set.has(RuntimeGlobals.startupNoDefault) &&
- chunkGraph.hasChunkEntryDependentChunks(chunk)
- ) {
- set.add(RuntimeGlobals.onChunksLoaded);
- set.add(RuntimeGlobals.exports);
- set.add(RuntimeGlobals.require);
- }
- }
- );
- compilation.hooks.executeModule.tap(PLUGIN_NAME, (options, context) => {
- const source = options.codeGenerationResult.sources.get("javascript");
- if (source === undefined) return;
- const { module } = options;
- const code = source.source();
- const fn = vm.runInThisContext(
- `(function(${module.moduleArgument}, ${module.exportsArgument}, ${RuntimeGlobals.require}) {\n${code}\n/**/})`,
- {
- filename: module.identifier(),
- lineOffset: -1
- }
- );
- const moduleObject =
- /** @type {ExecuteModuleObject} */
- (options.moduleObject);
- try {
- fn.call(
- moduleObject.exports,
- moduleObject,
- moduleObject.exports,
- context.__webpack_require__
- );
- } catch (err) {
- /** @type {Error} */
- (err).stack += printGeneratedCodeForStack(
- options.module,
- /** @type {string} */ (code)
- );
- throw err;
- }
- });
- compilation.hooks.executeModule.tap(PLUGIN_NAME, (options, context) => {
- const source = options.codeGenerationResult.sources.get("runtime");
- if (source === undefined) return;
- let code = source.source();
- if (typeof code !== "string") code = code.toString();
- const fn = vm.runInThisContext(
- `(function(${RuntimeGlobals.require}) {\n${code}\n/**/})`,
- {
- filename: options.module.identifier(),
- lineOffset: -1
- }
- );
- try {
- // eslint-disable-next-line no-useless-call
- fn.call(null, context.__webpack_require__);
- } catch (err) {
- /** @type {Error} */
- (err).stack += printGeneratedCodeForStack(options.module, code);
- throw err;
- }
- });
- }
- );
- }
- /**
- * @param {Chunk} chunk chunk
- * @param {OutputOptions} outputOptions output options
- * @returns {TemplatePath} used filename template
- */
- static getChunkFilenameTemplate(chunk, outputOptions) {
- if (chunk.filenameTemplate) {
- return chunk.filenameTemplate;
- } else if (chunk instanceof HotUpdateChunk) {
- return /** @type {TemplatePath} */ (outputOptions.hotUpdateChunkFilename);
- } else if (chunk.canBeInitial()) {
- return /** @type {TemplatePath} */ (outputOptions.filename);
- }
- return /** @type {TemplatePath} */ (outputOptions.chunkFilename);
- }
- /**
- * @param {Module} module the rendered module
- * @param {ChunkRenderContext} renderContext options object
- * @param {CompilationHooks} hooks hooks
- * @param {boolean} factory true: renders as factory method, false: pure module content
- * @returns {Source | null} the newly generated source from rendering
- */
- renderModule(module, renderContext, hooks, factory) {
- const {
- chunk,
- chunkGraph,
- runtimeTemplate,
- codeGenerationResults,
- strictMode
- } = renderContext;
- try {
- const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
- const moduleSource = codeGenResult.sources.get("javascript");
- if (!moduleSource) return null;
- if (codeGenResult.data !== undefined) {
- const chunkInitFragments = codeGenResult.data.get("chunkInitFragments");
- if (chunkInitFragments) {
- for (const i of chunkInitFragments) {
- renderContext.chunkInitFragments.push(i);
- }
- }
- }
- const moduleSourcePostContent = tryRunOrWebpackError(
- () =>
- hooks.renderModuleContent.call(moduleSource, module, renderContext),
- "JavascriptModulesPlugin.getCompilationHooks().renderModuleContent"
- );
- let moduleSourcePostContainer;
- if (factory) {
- const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
- module,
- chunk.runtime
- );
- const needModule = runtimeRequirements.has(RuntimeGlobals.module);
- const needExports = runtimeRequirements.has(RuntimeGlobals.exports);
- const needRequire =
- runtimeRequirements.has(RuntimeGlobals.require) ||
- runtimeRequirements.has(RuntimeGlobals.requireScope);
- const needThisAsExports = runtimeRequirements.has(
- RuntimeGlobals.thisAsExports
- );
- const needStrict =
- /** @type {BuildInfo} */
- (module.buildInfo).strict && !strictMode;
- const cacheEntry = this._moduleFactoryCache.get(
- moduleSourcePostContent
- );
- let source;
- if (
- cacheEntry &&
- cacheEntry.needModule === needModule &&
- cacheEntry.needExports === needExports &&
- cacheEntry.needRequire === needRequire &&
- cacheEntry.needThisAsExports === needThisAsExports &&
- cacheEntry.needStrict === needStrict
- ) {
- source = cacheEntry.source;
- } else {
- const factorySource = new ConcatSource();
- const args = [];
- if (needExports || needRequire || needModule) {
- args.push(
- needModule
- ? module.moduleArgument
- : `__unused_webpack_${module.moduleArgument}`
- );
- }
- if (needExports || needRequire) {
- args.push(
- needExports
- ? module.exportsArgument
- : `__unused_webpack_${module.exportsArgument}`
- );
- }
- if (needRequire) args.push(RuntimeGlobals.require);
- if (!needThisAsExports && runtimeTemplate.supportsArrowFunction()) {
- factorySource.add(`/***/ ((${args.join(", ")}) => {\n\n`);
- } else {
- factorySource.add(`/***/ (function(${args.join(", ")}) {\n\n`);
- }
- if (needStrict) {
- factorySource.add('"use strict";\n');
- }
- factorySource.add(moduleSourcePostContent);
- factorySource.add("\n\n/***/ })");
- source = new CachedSource(factorySource);
- this._moduleFactoryCache.set(moduleSourcePostContent, {
- source,
- needModule,
- needExports,
- needRequire,
- needThisAsExports,
- needStrict
- });
- }
- moduleSourcePostContainer = tryRunOrWebpackError(
- () => hooks.renderModuleContainer.call(source, module, renderContext),
- "JavascriptModulesPlugin.getCompilationHooks().renderModuleContainer"
- );
- } else {
- moduleSourcePostContainer = moduleSourcePostContent;
- }
- return tryRunOrWebpackError(
- () =>
- hooks.renderModulePackage.call(
- moduleSourcePostContainer,
- module,
- renderContext
- ),
- "JavascriptModulesPlugin.getCompilationHooks().renderModulePackage"
- );
- } catch (err) {
- /** @type {WebpackError} */
- (err).module = module;
- throw err;
- }
- }
- /**
- * @param {RenderContext} renderContext the render context
- * @param {CompilationHooks} hooks hooks
- * @returns {Source} the rendered source
- */
- renderChunk(renderContext, hooks) {
- const { chunk, chunkGraph } = renderContext;
- const modules = chunkGraph.getOrderedChunkModulesIterableBySourceType(
- chunk,
- "javascript",
- compareModulesByIdOrIdentifier(chunkGraph)
- );
- const allModules = modules ? [...modules] : [];
- let strictHeader;
- let allStrict = renderContext.strictMode;
- if (
- !allStrict &&
- allModules.every(m => /** @type {BuildInfo} */ (m.buildInfo).strict)
- ) {
- const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
- strictHeader = strictBailout
- ? `// runtime can't be in strict mode because ${strictBailout}.\n`
- : '"use strict";\n';
- if (!strictBailout) allStrict = true;
- }
- /** @type {ChunkRenderContext} */
- const chunkRenderContext = {
- ...renderContext,
- chunkInitFragments: [],
- strictMode: allStrict
- };
- const moduleSources =
- Template.renderChunkModules(chunkRenderContext, allModules, module =>
- this.renderModule(module, chunkRenderContext, hooks, true)
- ) || new RawSource("{}");
- let source = tryRunOrWebpackError(
- () => hooks.renderChunk.call(moduleSources, chunkRenderContext),
- "JavascriptModulesPlugin.getCompilationHooks().renderChunk"
- );
- source = tryRunOrWebpackError(
- () => hooks.renderContent.call(source, chunkRenderContext),
- "JavascriptModulesPlugin.getCompilationHooks().renderContent"
- );
- if (!source) {
- throw new Error(
- "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderContent plugins should return something"
- );
- }
- source = InitFragment.addToSource(
- source,
- chunkRenderContext.chunkInitFragments,
- chunkRenderContext
- );
- source = tryRunOrWebpackError(
- () => hooks.render.call(source, chunkRenderContext),
- "JavascriptModulesPlugin.getCompilationHooks().render"
- );
- if (!source) {
- throw new Error(
- "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().render plugins should return something"
- );
- }
- chunk.rendered = true;
- return strictHeader
- ? new ConcatSource(strictHeader, source, ";")
- : renderContext.runtimeTemplate.isModule()
- ? source
- : new ConcatSource(source, ";");
- }
- /**
- * @param {MainRenderContext} renderContext options object
- * @param {CompilationHooks} hooks hooks
- * @param {Compilation} compilation the compilation
- * @returns {Source} the newly generated source from rendering
- */
- renderMain(renderContext, hooks, compilation) {
- const { chunk, chunkGraph, runtimeTemplate } = renderContext;
- const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
- const iife = runtimeTemplate.isIIFE();
- const bootstrap = this.renderBootstrap(renderContext, hooks);
- const useSourceMap = hooks.useSourceMap.call(chunk, renderContext);
- /** @type {Module[]} */
- const allModules = [
- ...(chunkGraph.getOrderedChunkModulesIterableBySourceType(
- chunk,
- "javascript",
- compareModulesByIdOrIdentifier(chunkGraph)
- ) || [])
- ];
- const hasEntryModules = chunkGraph.getNumberOfEntryModules(chunk) > 0;
- /** @type {Set<Module> | undefined} */
- let inlinedModules;
- if (bootstrap.allowInlineStartup && hasEntryModules) {
- inlinedModules = new Set(chunkGraph.getChunkEntryModulesIterable(chunk));
- }
- const source = new ConcatSource();
- let prefix;
- if (iife) {
- if (runtimeTemplate.supportsArrowFunction()) {
- source.add("/******/ (() => { // webpackBootstrap\n");
- } else {
- source.add("/******/ (function() { // webpackBootstrap\n");
- }
- prefix = "/******/ \t";
- } else {
- prefix = "/******/ ";
- }
- let allStrict = renderContext.strictMode;
- if (
- !allStrict &&
- allModules.every(m => /** @type {BuildInfo} */ (m.buildInfo).strict)
- ) {
- const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
- if (strictBailout) {
- source.add(
- `${
- prefix
- }// runtime can't be in strict mode because ${strictBailout}.\n`
- );
- } else {
- allStrict = true;
- source.add(`${prefix}"use strict";\n`);
- }
- }
- /** @type {ChunkRenderContext} */
- const chunkRenderContext = {
- ...renderContext,
- chunkInitFragments: [],
- strictMode: allStrict
- };
- const chunkModules = Template.renderChunkModules(
- chunkRenderContext,
- inlinedModules
- ? allModules.filter(
- m => !(/** @type {Set<Module>} */ (inlinedModules).has(m))
- )
- : allModules,
- module => this.renderModule(module, chunkRenderContext, hooks, true),
- prefix
- );
- if (
- chunkModules ||
- runtimeRequirements.has(RuntimeGlobals.moduleFactories) ||
- runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly) ||
- runtimeRequirements.has(RuntimeGlobals.require)
- ) {
- source.add(`${prefix}var __webpack_modules__ = (`);
- source.add(chunkModules || "{}");
- source.add(");\n");
- source.add(
- "/************************************************************************/\n"
- );
- }
- if (bootstrap.header.length > 0) {
- const header = `${Template.asString(bootstrap.header)}\n`;
- source.add(
- new PrefixSource(
- prefix,
- useSourceMap
- ? new OriginalSource(header, "webpack/bootstrap")
- : new RawSource(header)
- )
- );
- source.add(
- "/************************************************************************/\n"
- );
- }
- const runtimeModules =
- renderContext.chunkGraph.getChunkRuntimeModulesInOrder(chunk);
- if (runtimeModules.length > 0) {
- source.add(
- new PrefixSource(
- prefix,
- Template.renderRuntimeModules(runtimeModules, chunkRenderContext)
- )
- );
- source.add(
- "/************************************************************************/\n"
- );
- // runtimeRuntimeModules calls codeGeneration
- for (const module of runtimeModules) {
- compilation.codeGeneratedModules.add(module);
- }
- }
- if (inlinedModules) {
- if (bootstrap.beforeStartup.length > 0) {
- const beforeStartup = `${Template.asString(bootstrap.beforeStartup)}\n`;
- source.add(
- new PrefixSource(
- prefix,
- useSourceMap
- ? new OriginalSource(beforeStartup, "webpack/before-startup")
- : new RawSource(beforeStartup)
- )
- );
- }
- const lastInlinedModule = /** @type {Module} */ (last(inlinedModules));
- const startupSource = new ConcatSource();
- if (runtimeRequirements.has(RuntimeGlobals.exports)) {
- startupSource.add(`var ${RuntimeGlobals.exports} = {};\n`);
- }
- const avoidEntryIife = compilation.options.optimization.avoidEntryIife;
- /** @type {Map<Module, Source> | false} */
- let renamedInlinedModule = false;
- if (avoidEntryIife) {
- renamedInlinedModule = this.getRenamedInlineModule(
- allModules,
- renderContext,
- inlinedModules,
- chunkRenderContext,
- hooks,
- allStrict,
- Boolean(chunkModules)
- );
- }
- for (const m of inlinedModules) {
- const renderedModule = renamedInlinedModule
- ? renamedInlinedModule.get(m)
- : this.renderModule(m, chunkRenderContext, hooks, false);
- if (renderedModule) {
- const innerStrict =
- !allStrict && /** @type {BuildInfo} */ (m.buildInfo).strict;
- const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
- m,
- chunk.runtime
- );
- const exports = runtimeRequirements.has(RuntimeGlobals.exports);
- const webpackExports =
- exports && m.exportsArgument === RuntimeGlobals.exports;
- const iife = innerStrict
- ? "it needs to be in strict mode."
- : inlinedModules.size > 1
- ? // TODO check globals and top-level declarations of other entries and chunk modules
- // to make a better decision
- "it needs to be isolated against other entry modules."
- : chunkModules && !renamedInlinedModule
- ? "it needs to be isolated against other modules in the chunk."
- : exports && !webpackExports
- ? `it uses a non-standard name for the exports (${m.exportsArgument}).`
- : hooks.embedInRuntimeBailout.call(m, renderContext);
- let footer;
- if (iife !== undefined) {
- startupSource.add(
- `// This entry needs to be wrapped in an IIFE because ${iife}\n`
- );
- const arrow = runtimeTemplate.supportsArrowFunction();
- if (arrow) {
- startupSource.add("(() => {\n");
- footer = "\n})();\n\n";
- } else {
- startupSource.add("!function() {\n");
- footer = "\n}();\n";
- }
- if (innerStrict) startupSource.add('"use strict";\n');
- } else {
- footer = "\n";
- }
- if (exports) {
- if (m !== lastInlinedModule) {
- startupSource.add(`var ${m.exportsArgument} = {};\n`);
- } else if (m.exportsArgument !== RuntimeGlobals.exports) {
- startupSource.add(
- `var ${m.exportsArgument} = ${RuntimeGlobals.exports};\n`
- );
- }
- }
- startupSource.add(renderedModule);
- startupSource.add(footer);
- }
- }
- if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
- startupSource.add(
- `${RuntimeGlobals.exports} = ${RuntimeGlobals.onChunksLoaded}(${RuntimeGlobals.exports});\n`
- );
- }
- source.add(
- hooks.renderStartup.call(startupSource, lastInlinedModule, {
- ...renderContext,
- inlined: true
- })
- );
- if (bootstrap.afterStartup.length > 0) {
- const afterStartup = `${Template.asString(bootstrap.afterStartup)}\n`;
- source.add(
- new PrefixSource(
- prefix,
- useSourceMap
- ? new OriginalSource(afterStartup, "webpack/after-startup")
- : new RawSource(afterStartup)
- )
- );
- }
- } else {
- const lastEntryModule =
- /** @type {Module} */
- (last(chunkGraph.getChunkEntryModulesIterable(chunk)));
- /** @type {(content: string[], name: string) => Source} */
- const toSource = useSourceMap
- ? (content, name) =>
- new OriginalSource(Template.asString(content), name)
- : content => new RawSource(Template.asString(content));
- source.add(
- new PrefixSource(
- prefix,
- new ConcatSource(
- toSource(bootstrap.beforeStartup, "webpack/before-startup"),
- "\n",
- hooks.renderStartup.call(
- toSource([...bootstrap.startup, ""], "webpack/startup"),
- lastEntryModule,
- {
- ...renderContext,
- inlined: false
- }
- ),
- toSource(bootstrap.afterStartup, "webpack/after-startup"),
- "\n"
- )
- )
- );
- }
- if (
- hasEntryModules &&
- runtimeRequirements.has(RuntimeGlobals.returnExportsFromRuntime)
- ) {
- source.add(`${prefix}return ${RuntimeGlobals.exports};\n`);
- }
- if (iife) {
- source.add("/******/ })()\n");
- }
- /** @type {Source} */
- let finalSource = tryRunOrWebpackError(
- () => hooks.renderMain.call(source, renderContext),
- "JavascriptModulesPlugin.getCompilationHooks().renderMain"
- );
- if (!finalSource) {
- throw new Error(
- "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderMain plugins should return something"
- );
- }
- finalSource = tryRunOrWebpackError(
- () => hooks.renderContent.call(finalSource, renderContext),
- "JavascriptModulesPlugin.getCompilationHooks().renderContent"
- );
- if (!finalSource) {
- throw new Error(
- "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderContent plugins should return something"
- );
- }
- finalSource = InitFragment.addToSource(
- finalSource,
- chunkRenderContext.chunkInitFragments,
- chunkRenderContext
- );
- finalSource = tryRunOrWebpackError(
- () => hooks.render.call(finalSource, renderContext),
- "JavascriptModulesPlugin.getCompilationHooks().render"
- );
- if (!finalSource) {
- throw new Error(
- "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().render plugins should return something"
- );
- }
- chunk.rendered = true;
- return iife ? new ConcatSource(finalSource, ";") : finalSource;
- }
- /**
- * @param {Hash} hash the hash to be updated
- * @param {RenderBootstrapContext} renderContext options object
- * @param {CompilationHooks} hooks hooks
- */
- updateHashWithBootstrap(hash, renderContext, hooks) {
- const bootstrap = this.renderBootstrap(renderContext, hooks);
- for (const _k of Object.keys(bootstrap)) {
- const key = /** @type {keyof Bootstrap} */ (_k);
- hash.update(key);
- if (Array.isArray(bootstrap[key])) {
- for (const line of bootstrap[key]) {
- hash.update(line);
- }
- } else {
- hash.update(JSON.stringify(bootstrap[key]));
- }
- }
- }
- /**
- * @param {RenderBootstrapContext} renderContext options object
- * @param {CompilationHooks} hooks hooks
- * @returns {Bootstrap} the generated source of the bootstrap code
- */
- renderBootstrap(renderContext, hooks) {
- const {
- chunkGraph,
- codeGenerationResults,
- moduleGraph,
- chunk,
- runtimeTemplate
- } = renderContext;
- const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
- const requireFunction = runtimeRequirements.has(RuntimeGlobals.require);
- const moduleCache = runtimeRequirements.has(RuntimeGlobals.moduleCache);
- const moduleFactories = runtimeRequirements.has(
- RuntimeGlobals.moduleFactories
- );
- const moduleUsed = runtimeRequirements.has(RuntimeGlobals.module);
- const requireScopeUsed = runtimeRequirements.has(
- RuntimeGlobals.requireScope
- );
- const interceptModuleExecution = runtimeRequirements.has(
- RuntimeGlobals.interceptModuleExecution
- );
- const useRequire =
- requireFunction || interceptModuleExecution || moduleUsed;
- /**
- * @type {{startup: string[], beforeStartup: string[], header: string[], afterStartup: string[], allowInlineStartup: boolean}}
- */
- const result = {
- header: [],
- beforeStartup: [],
- startup: [],
- afterStartup: [],
- allowInlineStartup: true
- };
- const { header: buf, startup, beforeStartup, afterStartup } = result;
- if (result.allowInlineStartup && moduleFactories) {
- startup.push(
- "// module factories are used so entry inlining is disabled"
- );
- result.allowInlineStartup = false;
- }
- if (result.allowInlineStartup && moduleCache) {
- startup.push("// module cache are used so entry inlining is disabled");
- result.allowInlineStartup = false;
- }
- if (result.allowInlineStartup && interceptModuleExecution) {
- startup.push(
- "// module execution is intercepted so entry inlining is disabled"
- );
- result.allowInlineStartup = false;
- }
- if (useRequire || moduleCache) {
- buf.push("// The module cache");
- buf.push("var __webpack_module_cache__ = {};");
- buf.push("");
- }
- if (runtimeRequirements.has(RuntimeGlobals.makeDeferredNamespaceObject)) {
- // in order to optimize of DeferredNamespaceObject, we remove all proxy handlers after the module initialize
- // (see MakeDeferredNamespaceObjectRuntimeModule)
- // This requires all deferred imports to a module can get the module export object before the module
- // is evaluated.
- buf.push("// The deferred module cache");
- buf.push("var __webpack_module_deferred_exports__ = {};");
- buf.push("");
- }
- if (useRequire) {
- buf.push("// The require function");
- buf.push(`function ${RuntimeGlobals.require}(moduleId) {`);
- buf.push(Template.indent(this.renderRequire(renderContext, hooks)));
- buf.push("}");
- buf.push("");
- } else if (runtimeRequirements.has(RuntimeGlobals.requireScope)) {
- buf.push("// The require scope");
- buf.push(`var ${RuntimeGlobals.require} = {};`);
- buf.push("");
- }
- if (
- moduleFactories ||
- runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly)
- ) {
- buf.push("// expose the modules object (__webpack_modules__)");
- buf.push(`${RuntimeGlobals.moduleFactories} = __webpack_modules__;`);
- buf.push("");
- }
- if (moduleCache) {
- buf.push("// expose the module cache");
- buf.push(`${RuntimeGlobals.moduleCache} = __webpack_module_cache__;`);
- buf.push("");
- }
- if (interceptModuleExecution) {
- buf.push("// expose the module execution interceptor");
- buf.push(`${RuntimeGlobals.interceptModuleExecution} = [];`);
- buf.push("");
- }
- if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
- if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
- /** @type {string[]} */
- const buf2 = [];
- const runtimeRequirements =
- chunkGraph.getTreeRuntimeRequirements(chunk);
- buf2.push("// Load entry module and return exports");
- let i = chunkGraph.getNumberOfEntryModules(chunk);
- for (const [
- entryModule,
- entrypoint
- ] of chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)) {
- if (!chunkGraph.getModuleSourceTypes(entryModule).has("javascript")) {
- i--;
- continue;
- }
- const chunks =
- /** @type {Entrypoint} */
- (entrypoint).chunks.filter(c => c !== chunk);
- if (result.allowInlineStartup && chunks.length > 0) {
- buf2.push(
- "// This entry module depends on other loaded chunks and execution need to be delayed"
- );
- result.allowInlineStartup = false;
- }
- if (
- result.allowInlineStartup &&
- someInIterable(
- moduleGraph.getIncomingConnectionsByOriginModule(entryModule),
- ([originModule, connections]) =>
- originModule &&
- connections.some(c => c.isTargetActive(chunk.runtime)) &&
- someInIterable(
- chunkGraph.getModuleRuntimes(originModule),
- runtime =>
- intersectRuntime(runtime, chunk.runtime) !== undefined
- )
- )
- ) {
- buf2.push(
- "// This entry module is referenced by other modules so it can't be inlined"
- );
- result.allowInlineStartup = false;
- }
- let data;
- if (codeGenerationResults.has(entryModule, chunk.runtime)) {
- const result = codeGenerationResults.get(
- entryModule,
- chunk.runtime
- );
- data = result.data;
- }
- if (
- result.allowInlineStartup &&
- (!data || !data.get("topLevelDeclarations")) &&
- (!entryModule.buildInfo ||
- !entryModule.buildInfo.topLevelDeclarations)
- ) {
- buf2.push(
- "// This entry module doesn't tell about it's top-level declarations so it can't be inlined"
- );
- result.allowInlineStartup = false;
- }
- if (result.allowInlineStartup) {
- const bailout = hooks.inlineInRuntimeBailout.call(
- entryModule,
- renderContext
- );
- if (bailout !== undefined) {
- buf2.push(
- `// This entry module can't be inlined because ${bailout}`
- );
- result.allowInlineStartup = false;
- }
- }
- i--;
- const moduleId = chunkGraph.getModuleId(entryModule);
- const entryRuntimeRequirements =
- chunkGraph.getModuleRuntimeRequirements(entryModule, chunk.runtime);
- let moduleIdExpr = JSON.stringify(moduleId);
- if (runtimeRequirements.has(RuntimeGlobals.entryModuleId)) {
- moduleIdExpr = `${RuntimeGlobals.entryModuleId} = ${moduleIdExpr}`;
- }
- if (
- result.allowInlineStartup &&
- entryRuntimeRequirements.has(RuntimeGlobals.module)
- ) {
- result.allowInlineStartup = false;
- buf2.push(
- "// This entry module used 'module' so it can't be inlined"
- );
- }
- if (chunks.length > 0) {
- buf2.push(
- `${i === 0 ? `var ${RuntimeGlobals.exports} = ` : ""}${
- RuntimeGlobals.onChunksLoaded
- }(undefined, ${JSON.stringify(
- chunks.map(c => c.id)
- )}, ${runtimeTemplate.returningFunction(
- `${RuntimeGlobals.require}(${moduleIdExpr})`
- )})`
- );
- } else if (useRequire) {
- buf2.push(
- `${i === 0 ? `var ${RuntimeGlobals.exports} = ` : ""}${
- RuntimeGlobals.require
- }(${moduleIdExpr});`
- );
- } else {
- if (i === 0) buf2.push(`var ${RuntimeGlobals.exports} = {};`);
- if (requireScopeUsed) {
- buf2.push(
- `__webpack_modules__[${moduleIdExpr}](0, ${
- i === 0 ? RuntimeGlobals.exports : "{}"
- }, ${RuntimeGlobals.require});`
- );
- } else if (entryRuntimeRequirements.has(RuntimeGlobals.exports)) {
- buf2.push(
- `__webpack_modules__[${moduleIdExpr}](0, ${
- i === 0 ? RuntimeGlobals.exports : "{}"
- });`
- );
- } else {
- buf2.push(`__webpack_modules__[${moduleIdExpr}]();`);
- }
- }
- }
- if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
- buf2.push(
- `${RuntimeGlobals.exports} = ${RuntimeGlobals.onChunksLoaded}(${RuntimeGlobals.exports});`
- );
- }
- if (
- runtimeRequirements.has(RuntimeGlobals.startup) ||
- (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) &&
- runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter))
- ) {
- result.allowInlineStartup = false;
- buf.push("// the startup function");
- buf.push(
- `${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction("", [
- ...buf2,
- `return ${RuntimeGlobals.exports};`
- ])};`
- );
- buf.push("");
- startup.push("// run startup");
- startup.push(
- `var ${RuntimeGlobals.exports} = ${RuntimeGlobals.startup}();`
- );
- } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) {
- buf.push("// the startup function");
- buf.push(
- `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
- );
- beforeStartup.push("// run runtime startup");
- beforeStartup.push(`${RuntimeGlobals.startup}();`);
- startup.push("// startup");
- startup.push(Template.asString(buf2));
- } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)) {
- buf.push("// the startup function");
- buf.push(
- `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
- );
- startup.push("// startup");
- startup.push(Template.asString(buf2));
- afterStartup.push("// run runtime startup");
- afterStartup.push(`${RuntimeGlobals.startup}();`);
- } else {
- startup.push("// startup");
- startup.push(Template.asString(buf2));
- }
- } else if (
- runtimeRequirements.has(RuntimeGlobals.startup) ||
- runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
- runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
- ) {
- buf.push(
- "// the startup function",
- "// It's empty as no entry modules are in this chunk",
- `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`,
- ""
- );
- }
- } else if (
- runtimeRequirements.has(RuntimeGlobals.startup) ||
- runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
- runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
- ) {
- result.allowInlineStartup = false;
- buf.push(
- "// the startup function",
- "// It's empty as some runtime module handles the default behavior",
- `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
- );
- startup.push("// run startup");
- startup.push(
- `var ${RuntimeGlobals.exports} = ${RuntimeGlobals.startup}();`
- );
- }
- return result;
- }
- /**
- * @param {RenderBootstrapContext} renderContext options object
- * @param {CompilationHooks} hooks hooks
- * @returns {string} the generated source of the require function
- */
- renderRequire(renderContext, hooks) {
- const {
- chunk,
- chunkGraph,
- runtimeTemplate: { outputOptions }
- } = renderContext;
- const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
- const moduleExecution = runtimeRequirements.has(
- RuntimeGlobals.interceptModuleExecution
- )
- ? Template.asString([
- `var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: ${RuntimeGlobals.require} };`,
- `${RuntimeGlobals.interceptModuleExecution}.forEach(function(handler) { handler(execOptions); });`,
- "module = execOptions.module;",
- "execOptions.factory.call(module.exports, module, module.exports, execOptions.require);"
- ])
- : runtimeRequirements.has(RuntimeGlobals.thisAsExports)
- ? Template.asString([
- `__webpack_modules__[moduleId].call(module.exports, module, module.exports, ${RuntimeGlobals.require});`
- ])
- : Template.asString([
- `__webpack_modules__[moduleId](module, module.exports, ${RuntimeGlobals.require});`
- ]);
- const needModuleId = runtimeRequirements.has(RuntimeGlobals.moduleId);
- const needModuleLoaded = runtimeRequirements.has(
- RuntimeGlobals.moduleLoaded
- );
- const needModuleDefer = runtimeRequirements.has(
- RuntimeGlobals.makeDeferredNamespaceObject
- );
- const content = Template.asString([
- "// Check if module is in cache",
- "var cachedModule = __webpack_module_cache__[moduleId];",
- "if (cachedModule !== undefined) {",
- outputOptions.strictModuleErrorHandling
- ? Template.indent([
- "if (cachedModule.error !== undefined) throw cachedModule.error;",
- "return cachedModule.exports;"
- ])
- : Template.indent("return cachedModule.exports;"),
- "}",
- "// Create a new module (and put it into the cache)",
- "var module = __webpack_module_cache__[moduleId] = {",
- Template.indent([
- needModuleId ? "id: moduleId," : "// no module.id needed",
- needModuleLoaded ? "loaded: false," : "// no module.loaded needed",
- needModuleDefer
- ? "exports: __webpack_module_deferred_exports__[moduleId] || {}"
- : "exports: {}"
- ]),
- "};",
- "",
- outputOptions.strictModuleExceptionHandling
- ? Template.asString([
- "// Execute the module function",
- "var threw = true;",
- "try {",
- Template.indent([
- moduleExecution,
- "threw = false;",
- ...(needModuleDefer
- ? ["delete __webpack_module_deferred_exports__[moduleId];"]
- : [])
- ]),
- "} finally {",
- Template.indent([
- "if(threw) delete __webpack_module_cache__[moduleId];"
- ]),
- "}"
- ])
- : outputOptions.strictModuleErrorHandling
- ? Template.asString([
- "// Execute the module function",
- "try {",
- Template.indent(
- needModuleDefer
- ? [
- moduleExecution,
- "delete __webpack_module_deferred_exports__[moduleId];"
- ]
- : moduleExecution
- ),
- "} catch(e) {",
- Template.indent(["module.error = e;", "throw e;"]),
- "}"
- ])
- : Template.asString([
- "// Execute the module function",
- moduleExecution,
- ...(needModuleDefer
- ? [
- "// delete __webpack_module_deferred_exports__[module];",
- "// skipped because strictModuleErrorHandling is not enabled."
- ]
- : [])
- ]),
- needModuleLoaded
- ? Template.asString([
- "",
- "// Flag the module as loaded",
- `${RuntimeGlobals.moduleLoaded} = true;`,
- ""
- ])
- : "",
- "// Return the exports of the module",
- "return module.exports;"
- ]);
- return tryRunOrWebpackError(
- () => hooks.renderRequire.call(content, renderContext),
- "JavascriptModulesPlugin.getCompilationHooks().renderRequire"
- );
- }
- /**
- * @param {Module[]} allModules allModules
- * @param {MainRenderContext} renderContext renderContext
- * @param {Set<Module>} inlinedModules inlinedModules
- * @param {ChunkRenderContext} chunkRenderContext chunkRenderContext
- * @param {CompilationHooks} hooks hooks
- * @param {boolean | undefined} allStrict allStrict
- * @param {boolean} hasChunkModules hasChunkModules
- * @returns {Map<Module, Source> | false} renamed inlined modules
- */
- getRenamedInlineModule(
- allModules,
- renderContext,
- inlinedModules,
- chunkRenderContext,
- hooks,
- allStrict,
- hasChunkModules
- ) {
- const innerStrict =
- !allStrict &&
- allModules.every(m => /** @type {BuildInfo} */ (m.buildInfo).strict);
- const isMultipleEntries = inlinedModules.size > 1;
- const singleEntryWithModules = inlinedModules.size === 1 && hasChunkModules;
- // TODO:
- // This step is before the IIFE reason calculation. Ideally, it should only be executed when this function can optimize the
- // IIFE reason. Otherwise, it should directly return false. There are four reasons now, we have skipped two already, the left
- // one is 'it uses a non-standard name for the exports'.
- if (isMultipleEntries || innerStrict || !singleEntryWithModules) {
- return false;
- }
- /** @type {Map<Module, Source>} */
- const renamedInlinedModules = new Map();
- const { runtimeTemplate } = renderContext;
- /** @typedef {{ source: Source, module: Module, ast: Program, variables: Set<Variable>, through: Set<Reference>, usedInNonInlined: Set<Variable>, moduleScope: Scope }} Info */
- /** @type {Map<Module, Info>} */
- const inlinedModulesToInfo = new Map();
- /** @type {Set<string>} */
- const nonInlinedModuleThroughIdentifiers = new Set();
- /** @type {Map<Module, Source>} */
- for (const m of allModules) {
- const isInlinedModule = inlinedModules && inlinedModules.has(m);
- const moduleSource = this.renderModule(
- m,
- chunkRenderContext,
- hooks,
- !isInlinedModule
- );
- if (!moduleSource) continue;
- const code = /** @type {string} */ (moduleSource.source());
- const ast = JavascriptParser._parse(code, {
- sourceType: "auto"
- });
- const scopeManager = eslintScope.analyze(ast, {
- ecmaVersion: 6,
- sourceType: "module",
- optimistic: true,
- ignoreEval: true
- });
- const globalScope = /** @type {Scope} */ (scopeManager.acquire(ast));
- if (inlinedModules && inlinedModules.has(m)) {
- const moduleScope = globalScope.childScopes[0];
- inlinedModulesToInfo.set(m, {
- source: moduleSource,
- ast,
- module: m,
- variables: new Set(moduleScope.variables),
- through: new Set(moduleScope.through),
- usedInNonInlined: new Set(),
- moduleScope
- });
- } else {
- for (const ref of globalScope.through) {
- nonInlinedModuleThroughIdentifiers.add(ref.identifier.name);
- }
- }
- }
- for (const [, { variables, usedInNonInlined }] of inlinedModulesToInfo) {
- for (const variable of variables) {
- if (
- nonInlinedModuleThroughIdentifiers.has(variable.name) ||
- RESERVED_NAMES.has(variable.name)
- ) {
- usedInNonInlined.add(variable);
- }
- }
- }
- for (const [m, moduleInfo] of inlinedModulesToInfo) {
- const { ast, source: _source, usedInNonInlined } = moduleInfo;
- const source = new ReplaceSource(_source);
- if (usedInNonInlined.size === 0) {
- renamedInlinedModules.set(m, source);
- continue;
- }
- const info = /** @type {Info} */ (inlinedModulesToInfo.get(m));
- const allUsedNames = new Set(
- Array.from(info.through, v => v.identifier.name)
- );
- for (const variable of usedInNonInlined) {
- allUsedNames.add(variable.name);
- }
- for (const variable of info.variables) {
- const usedNamesInScopeInfo = new Map();
- const ignoredScopes = new Set();
- const name = variable.name;
- const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo(
- usedNamesInScopeInfo,
- info.module.identifier(),
- name
- );
- if (allUsedNames.has(name) || usedNames.has(name)) {
- const references = getAllReferences(variable);
- const allIdentifiers = new Set([
- ...references.map(r => r.identifier),
- ...variable.identifiers
- ]);
- for (const ref of references) {
- addScopeSymbols(
- ref.from,
- usedNames,
- alreadyCheckedScopes,
- ignoredScopes
- );
- }
- const newName = findNewName(
- variable.name,
- allUsedNames,
- usedNames,
- m.readableIdentifier(runtimeTemplate.requestShortener)
- );
- allUsedNames.add(newName);
- for (const identifier of allIdentifiers) {
- const r = /** @type {Range} */ (identifier.range);
- const path = getPathInAst(ast, identifier);
- if (path && path.length > 1) {
- const maybeProperty =
- path[1].type === "AssignmentPattern" && path[1].left === path[0]
- ? path[2]
- : path[1];
- if (
- maybeProperty.type === "Property" &&
- maybeProperty.shorthand
- ) {
- source.insert(r[1], `: ${newName}`);
- continue;
- }
- }
- source.replace(r[0], r[1] - 1, newName);
- }
- }
- allUsedNames.add(name);
- }
- renamedInlinedModules.set(m, source);
- }
- return renamedInlinedModules;
- }
- }
- module.exports = JavascriptModulesPlugin;
- module.exports.chunkHasJs = chunkHasJs;
|