| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const vm = require("vm");
- const { SyncBailHook, SyncHook, SyncWaterfallHook } = require("tapable");
- const {
- CachedSource,
- ConcatSource,
- OriginalSource,
- PrefixSource,
- RawSource,
- ReplaceSource
- } = require("webpack-sources");
- /**
- * @import Compilation, {
- * ChunkHashContext,
- * ExecuteModuleObject,
- * WebpackRequire
- * } from "../Compilation"
- */
- const HotUpdateChunk = require("../HotUpdateChunk");
- const InitFragment = require("../InitFragment");
- const { JAVASCRIPT_TYPE } = require("../ModuleSourceTypeConstants");
- 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 { tryRunOrWebpackError } = require("../errors/HookWebpackError");
- const { last, someInIterable } = require("../util/IterableHelpers");
- const StringXor = require("../util/StringXor");
- const { compareModulesByFullName } = require("../util/comparators");
- const {
- CHUNK_RUNTIME_DECLARATIONS,
- RESERVED_NAMES,
- addScopeSymbols,
- findNewName,
- getAllReferences,
- getPathInAst,
- getUsedNamesInScopeInfo
- } = require("../util/concatenate");
- const createHash = require("../util/createHash");
- const createHooksRegistry = require("../util/createHooksRegistry");
- const { digestNonNumericOnlyWithFull } = require("../util/nonNumericOnlyHash");
- const removeBOM = require("../util/removeBOM");
- const { intersectRuntime } = require("../util/runtime");
- const { getAllChunks } = require("./ChunkHelpers");
- const JavascriptGenerator = require("./JavascriptGenerator");
- const JavascriptModule = require("./JavascriptModule");
- const JavascriptParser = require("./JavascriptParser");
- const analyzeScope = require("./ScopeAnalyzer");
- /**
- * @import {
- * Program,
- * Node,
- * Identifier,
- * CatchClause,
- * ClassDeclaration,
- * ClassExpression,
- * FunctionDeclaration,
- * FunctionExpression,
- * ArrowFunctionExpression,
- * VariableDeclarator,
- * VariableDeclaration,
- * ImportDeclaration,
- * ImportSpecifier,
- * ImportDefaultSpecifier,
- * ImportNamespaceSpecifier,
- * AssignmentExpression,
- * ForInStatement,
- * ForOfStatement
- * } from "estree"
- */
- /** @import { Source } from "webpack-sources" */
- /**
- * @import {
- * OutputNormalizedWithDefaults as OutputOptions
- * } from "../config/defaults"
- */
- /** @import Chunk, { ChunkFilenameTemplate } from "../Chunk" */
- /** @import ChunkGraph, { EntryModuleWithChunkGroup } from "../ChunkGraph" */
- /** @import CodeGenerationResults from "../CodeGenerationResults" */
- /** @import Compiler from "../Compiler" */
- /** @import DependencyTemplates from "../DependencyTemplates" */
- /** @import Entrypoint from "../Entrypoint" */
- /** @import Module, { BuildInfo, CodeGenerationResultData } from "../Module" */
- /** @import { RuntimeSpec } from "../util/runtime" */
- /** @import ModuleGraph from "../ModuleGraph" */
- /** @import RuntimeTemplate from "../RuntimeTemplate" */
- /** @import WebpackError from "../errors/WebpackError" */
- /** @import { Range } from "../javascript/JavascriptParser" */
- /** @import Hash from "../util/Hash" */
- /** @import { ScopeSet, UsedNamesInScopeInfo } from "../util/concatenate" */
- /** @typedef {import("./ScopeAnalyzer").Scope} Scope */
- /** @typedef {import("./ScopeAnalyzer").Variable} Variable */
- /** @typedef {import("./ScopeAnalyzer").Reference} Reference */
- /** @type {WeakMap<ChunkGraph, WeakMap<Chunk, boolean>>} */
- const chunkHasJsCache = new WeakMap();
- /**
- * Returns true, when a JS file is needed for this chunk.
- * @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) {
- for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) {
- if (chunkGraph.getModuleSourceTypes(module).has(JAVASCRIPT_TYPE)) {
- return true;
- }
- }
- }
- return Boolean(
- chunkGraph.getChunkModulesIterableBySourceType(chunk, JAVASCRIPT_TYPE)
- );
- };
- /**
- * Returns true, when a JS file is needed for this chunk.
- * @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) => {
- let innerCache = chunkHasJsCache.get(chunkGraph);
- if (innerCache === undefined) {
- innerCache = new WeakMap();
- chunkHasJsCache.set(chunkGraph, innerCache);
- }
- const cachedResult = innerCache.get(chunk);
- if (cachedResult !== undefined) {
- return cachedResult;
- }
- const result = _chunkHasJs(chunk, chunkGraph);
- innerCache.set(chunk, result);
- return result;
- };
- /**
- * Chunk has runtime or js.
- * @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 (chunkHasJs(chunk, chunkGraph)) {
- return true;
- }
- if (
- chunkGraph.getChunkModulesIterableBySourceType(
- chunk,
- WEBPACK_MODULE_TYPE_RUNTIME
- )
- ) {
- for (const chunkGroup of chunk.groupsIterable) {
- for (const c of chunkGroup.chunks) {
- if (chunkHasJs(c, chunkGraph)) return true;
- }
- }
- return false;
- }
- return false;
- };
- /**
- * Print generated code for stack.
- * @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(
- /**
- * Handles the callback logic for this hook.
- * @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")}`;
- };
- /**
- * Defines the render context type used by this module.
- * @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
- */
- /**
- * Defines the main render context type used by this module.
- * @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
- */
- /**
- * Defines the chunk render context type used by this module.
- * @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
- * @property {Module=} inlinedEntryModule entry module inlined at the chunk top level instead of the registry
- * @property {Source=} inlinedEntrySource rendered body of the inlined entry module
- */
- /**
- * Defines the render bootstrap context type used by this module.
- * @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
- */
- /**
- * Defines the startup render context type used by this module.
- * @typedef {object} StartupRenderContext
- * @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
- * @property {boolean=} inlined inlined
- * @property {boolean=} inlinedInIIFE the inlined entry module is wrapped in an IIFE
- * @property {boolean=} needExportsDeclaration whether the top-level exports declaration needs to be generated
- */
- /**
- * Defines the module render context type used by this module.
- * @typedef {object} ModuleRenderContext
- * @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
- * @property {boolean} factory true: renders as factory method, false: pure module content
- * @property {boolean=} inlinedInIIFE the inlined entry module is wrapped in an IIFE, existing only when `factory` is set to false
- * @property {boolean=} renderInObject render module in object container
- */
- const createCompilationHooks = () => ({
- /**
- * @type {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>}
- */
- renderModuleContent: new SyncWaterfallHook([
- "source",
- "module",
- "moduleRenderContext"
- ]),
- /**
- * @type {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>}
- */
- renderModuleContainer: new SyncWaterfallHook([
- "source",
- "module",
- "moduleRenderContext"
- ]),
- /**
- * @type {SyncWaterfallHook<[Source, Module, ModuleRenderContext]>}
- */
- renderModulePackage: new SyncWaterfallHook([
- "source",
- "module",
- "moduleRenderContext"
- ]),
- /**
- * @type {SyncWaterfallHook<[Source, RenderContext]>}
- */
- render: new SyncWaterfallHook(["source", "renderContext"]),
- /**
- * @type {SyncWaterfallHook<[Source, RenderContext]>}
- * @since 5.41.0
- */
- renderContent: new SyncWaterfallHook(["source", "renderContext"]),
- /**
- * @type {SyncWaterfallHook<[Source, Module, StartupRenderContext]>}
- * @since 5.22.0
- */
- renderStartup: new SyncWaterfallHook([
- "source",
- "module",
- "startupRenderContext"
- ]),
- /**
- * @type {SyncWaterfallHook<[Source, RenderContext]>}
- */
- renderChunk: new SyncWaterfallHook(["source", "renderContext"]),
- /**
- * @type {SyncWaterfallHook<[Source, RenderContext]>}
- */
- renderMain: new SyncWaterfallHook(["source", "renderContext"]),
- /**
- * @type {SyncWaterfallHook<[string, RenderBootstrapContext]>}
- */
- renderRequire: new SyncWaterfallHook(["code", "renderContext"]),
- /**
- * @type {SyncBailHook<[Module, Partial<RenderBootstrapContext>], string | void>}
- * @since 5.22.0
- */
- inlineInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
- /**
- * Offers a module's rendered export-definition call to a consumer that can place
- * it better — a library whose entry exports the same bindings natively takes it
- * over and emits it only where the module is wrapped. Return true to take it.
- * @type {SyncBailHook<[Module, RuntimeSpec, string, boolean], boolean | void>}
- */
- onDemandExportsGeneration: new SyncBailHook([
- "module",
- "runtime",
- "source",
- "placeAtEnd"
- ]),
- /**
- * @type {SyncBailHook<[Module, RenderContext], string | void>}
- * @since 5.22.0
- */
- embedInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
- /**
- * @type {SyncBailHook<[RenderContext], string | void>}
- * @since 5.26.1
- */
- strictRuntimeBailout: new SyncBailHook(["renderContext"]),
- /**
- * @type {SyncHook<[Chunk, Hash, ChunkHashContext]>}
- */
- chunkHash: new SyncHook(["chunk", "hash", "context"]),
- /**
- * @type {SyncBailHook<[Chunk, RenderContext], boolean | void>}
- * @since 5.2.1
- */
- useSourceMap: new SyncBailHook(["chunk", "renderContext"])
- });
- /**
- * @typedef {ReturnType<typeof createCompilationHooks>} CompilationHooks
- */
- /**
- * Renames an inlined module's top-level declaration (and all its references) when
- * its name is already taken in the shared startup scope, recording the chosen name
- * in `allUsedNames`. Lets inlined modules be emitted without a per-entry/per-chunk
- * IIFE by resolving name collisions instead of isolating each module.
- * @param {InstanceType<typeof import("webpack-sources").ReplaceSource>} source the module source to edit
- * @param {Program} ast the parsed module AST
- * @param {Variable} variable the top-level variable to check/rename
- * @param {string} moduleIdentifier the module identifier (for scope caching)
- * @param {string} readableIdentifier the readable module identifier (for new names)
- * @param {Set<string>} allUsedNames names already used in the shared scope (mutated)
- * @returns {void}
- */
- const renameInlinedModuleVariable = (
- source,
- ast,
- variable,
- moduleIdentifier,
- readableIdentifier,
- allUsedNames
- ) => {
- /** @type {UsedNamesInScopeInfo} */
- const usedNamesInScopeInfo = new Map();
- /** @type {ScopeSet} */
- const ignoredScopes = new Set();
- const name = variable.name;
- const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo(
- usedNamesInScopeInfo,
- moduleIdentifier,
- 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(
- name,
- allUsedNames,
- usedNames,
- readableIdentifier
- );
- 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);
- };
- const PLUGIN_NAME = "JavascriptModulesPlugin";
- /** @typedef {{ header: string[], beforeStartup: string[], startup: string[], afterStartup: string[], allowInlineStartup: boolean }} Bootstrap */
- class JavascriptModulesPlugin {
- constructor(options = {}) {
- this.options = options;
- /** @type {WeakMap<Source, { source: Source, needModule: boolean, needExports: boolean, needRequire: boolean, needThisAsExports: boolean, needStrict: boolean | undefined, renderShorthand: boolean }>} */
- this._moduleFactoryCache = new WeakMap();
- }
- /**
- * Applies the plugin by registering its hooks on the compiler.
- * @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.createModuleClass
- .for(type)
- .tap(
- PLUGIN_NAME,
- (createData, _resolveData) => new JavascriptModule(createData)
- );
- normalModuleFactory.hooks.createParser
- .for(type)
- .tap(PLUGIN_NAME, (options) => {
- switch (type) {
- case JAVASCRIPT_MODULE_TYPE_AUTO: {
- return new JavascriptParser("auto", {
- parse: options.parse,
- typescript: options.typescript,
- importPhases: Boolean(
- options.deferImport || options.sourceImport
- ),
- strictModeViolations: options.strictModeViolations
- });
- }
- case JAVASCRIPT_MODULE_TYPE_DYNAMIC: {
- return new JavascriptParser("script", {
- parse: options.parse,
- typescript: options.typescript,
- importPhases: Boolean(
- options.deferImport || options.sourceImport
- ),
- strictModeViolations: options.strictModeViolations
- });
- }
- case JAVASCRIPT_MODULE_TYPE_ESM: {
- return new JavascriptParser("module", {
- parse: options.parse,
- typescript: options.typescript,
- importPhases: Boolean(
- options.deferImport || options.sourceImport
- ),
- strictModeViolations: options.strictModeViolations
- });
- }
- }
- });
- 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
- );
- /** @type {() => Source} */
- 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,
- moduleGraph,
- runtimeTemplate,
- outputOptions: {
- hashSalt,
- hashDigest,
- hashDigestLength,
- hashFunction
- }
- } = compilation;
- const codeGenerationResults =
- /** @type {CodeGenerationResults} */
- (compilation.codeGenerationResults);
- const hash = createHash(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_TYPE
- );
- 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);
- }
- [chunk.contentHash.javascript, chunk.contentHashFull.javascript] =
- digestNonNumericOnlyWithFull(hash, hashDigest, 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_TYPE);
- if (source === undefined) return;
- const { module } = options;
- const code = source.source();
- /** @type {(this: ExecuteModuleObject["exports"], exports: ExecuteModuleObject["exports"], moduleObject: ExecuteModuleObject, webpackRequire: WebpackRequire) => void} */
- 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,
- /** @type {WebpackRequire} */
- (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();
- /** @type {(this: null, webpackRequire: WebpackRequire) => void} */
- 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,
- /** @type {WebpackRequire} */
- (context.__webpack_require__)
- );
- } catch (err) {
- /** @type {Error} */
- (err).stack += printGeneratedCodeForStack(options.module, code);
- throw err;
- }
- });
- }
- );
- }
- /**
- * Gets chunk filename template.
- * @param {Chunk} chunk chunk
- * @param {OutputOptions} outputOptions output options
- * @returns {ChunkFilenameTemplate} used filename template
- */
- static getChunkFilenameTemplate(chunk, outputOptions) {
- if (chunk.filenameTemplate) {
- return chunk.filenameTemplate;
- } else if (chunk instanceof HotUpdateChunk) {
- return outputOptions.hotUpdateChunkFilename;
- }
- const entryOptions = chunk.getEntryOptions();
- // A worker entry (`new Worker` or `entry.worker`) uses workerChunkFilename;
- // chunks it loads internally keep `chunkFilename`
- if (entryOptions !== undefined && entryOptions.worker) {
- return outputOptions.workerChunkFilename;
- } else if (chunk.canBeInitial()) {
- return outputOptions.filename;
- }
- return outputOptions.chunkFilename;
- }
- /**
- * Renders the newly generated source from rendering.
- * @param {Module} module the rendered module
- * @param {ModuleRenderContext} renderContext options object
- * @param {CompilationHooks} hooks hooks
- * @returns {Source | null} the newly generated source from rendering
- */
- renderModule(module, renderContext, hooks) {
- const {
- chunk,
- chunkGraph,
- runtimeTemplate,
- codeGenerationResults,
- strictMode,
- factory,
- renderInObject
- } = renderContext;
- try {
- const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
- const moduleSource = codeGenResult.sources.get(JAVASCRIPT_TYPE);
- 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"
- );
- /** @type {Source} */
- 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
- );
- const renderShorthand =
- renderInObject === true && runtimeTemplate.supportsMethodShorthand();
- /** @type {Source} */
- let source;
- if (
- cacheEntry &&
- cacheEntry.needModule === needModule &&
- cacheEntry.needExports === needExports &&
- cacheEntry.needRequire === needRequire &&
- cacheEntry.needThisAsExports === needThisAsExports &&
- cacheEntry.needStrict === needStrict &&
- cacheEntry.renderShorthand === renderShorthand
- ) {
- source = cacheEntry.source;
- } else {
- const factorySource = new ConcatSource();
- /** @type {string[]} */
- 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 (renderShorthand) {
- // we can optimize function to methodShorthand if render module factory in object
- factorySource.add(`(${args.join(", ")}) {\n\n`);
- } else 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/***/ }${renderShorthand ? "" : ")"}`);
- source = new CachedSource(factorySource);
- this._moduleFactoryCache.set(moduleSourcePostContent, {
- source,
- needModule,
- needExports,
- needRequire,
- needThisAsExports,
- needStrict,
- renderShorthand
- });
- }
- 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;
- }
- }
- /**
- * Renders the rendered source.
- * @param {RenderContext} renderContext the render context
- * @param {CompilationHooks} hooks hooks
- * @returns {Source} the rendered source
- */
- renderChunk(renderContext, hooks) {
- const { chunk, chunkGraph, runtimeTemplate } = renderContext;
- const modules = chunkGraph.getOrderedChunkModulesIterableBySourceType(
- chunk,
- JAVASCRIPT_TYPE,
- compareModulesByFullName(runtimeTemplate.compilation.compiler)
- );
- const allModules = modules ? [...modules] : [];
- /** @type {undefined | string} */
- 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
- };
- // ESM entry chunk whose runtime lives in a separate chunk: inline the
- // single entry module at the top level (instead of the module registry)
- // so its own top-level declarations stay live ESM bindings for consumers.
- const inlinedEntryModule = this._getEsmEntryModuleToInline(
- renderContext,
- allModules
- );
- let registryModules = allModules;
- if (inlinedEntryModule) {
- const inlinedEntrySource = this.renderModule(
- inlinedEntryModule,
- { ...chunkRenderContext, factory: false },
- hooks
- );
- if (inlinedEntrySource) {
- registryModules = allModules.filter((m) => m !== inlinedEntryModule);
- chunkRenderContext.inlinedEntryModule = inlinedEntryModule;
- chunkRenderContext.inlinedEntrySource = inlinedEntrySource;
- }
- }
- const moduleSources =
- Template.renderChunkModules(
- chunkRenderContext,
- registryModules,
- (module, renderInObject) =>
- this.renderModule(
- module,
- { ...chunkRenderContext, factory: true, renderInObject },
- hooks
- )
- ) || 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, ";");
- }
- /**
- * Returns the chunk's single entry module when it can be inlined at the top
- * level of an ESM output chunk (instead of the module registry), which keeps
- * its exports as live ESM bindings. Only a self-contained ESM entry whose
- * top-level declarations can be lifted into the chunk scope qualifies;
- * otherwise `undefined` is returned and the registry path is used.
- * @param {RenderContext} renderContext render context
- * @param {Module[]} allModules all javascript modules of the chunk
- * @returns {Module | undefined} the entry module to inline, if any
- */
- _getEsmEntryModuleToInline(renderContext, allModules) {
- const {
- chunk,
- chunkGraph,
- moduleGraph,
- runtimeTemplate,
- codeGenerationResults
- } = renderContext;
- // Only a single ESM entry whose runtime lives in a separate chunk.
- if (
- !runtimeTemplate.isModule() ||
- chunk.hasRuntime() ||
- chunkGraph.getNumberOfEntryModules(chunk) !== 1
- ) {
- return undefined;
- }
- const [entryEntry] =
- chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk);
- const [entryModule, entrypoint] = /** @type {[Module, Entrypoint]} */ (
- entryEntry
- );
- // Module-local safety: the body is lifted verbatim, so it must use the
- // standard exports binding (not `module`/`this`) and expose top-level
- // declarations whose names can't collide with runtime/startup identifiers.
- const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
- entryModule,
- chunk.runtime
- );
- if (
- entryModule.exportsArgument !== RuntimeGlobals.exports ||
- runtimeRequirements.has(RuntimeGlobals.module) ||
- runtimeRequirements.has(RuntimeGlobals.thisAsExports)
- ) {
- return undefined;
- }
- const topLevelDeclarations =
- codeGenerationResults.getData(
- entryModule,
- chunk.runtime,
- "topLevelDeclarations"
- ) ||
- (entryModule.buildInfo && entryModule.buildInfo.topLevelDeclarations);
- if (!topLevelDeclarations || topLevelDeclarations.size === 0) {
- return undefined;
- }
- for (const name of topLevelDeclarations) {
- if (RESERVED_NAMES.has(name) || name.startsWith("__webpack_")) {
- return undefined;
- }
- }
- // Self-contained: the entry must not be imported by another module (which
- // needs it in the registry), and must not require other chunks or
- // `dependOn` parents to execute first.
- if (
- entrypoint.getParents().length > 0 ||
- getAllChunks(entrypoint, chunk, entrypoint.getRuntimeChunk()).size > 0
- ) {
- return undefined;
- }
- const referenced = someInIterable(
- moduleGraph.getIncomingConnectionsByOriginModule(entryModule),
- ([originModule, connections]) =>
- originModule &&
- originModule !== entryModule &&
- connections.some((c) => c.isTargetActive(chunk.runtime)) &&
- someInIterable(
- chunkGraph.getModuleRuntimes(originModule),
- (runtime) => intersectRuntime(runtime, chunk.runtime) !== undefined
- )
- );
- return referenced ? undefined : entryModule;
- }
- /**
- * Renders the newly generated source from rendering.
- * @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_TYPE,
- compareModulesByFullName(runtimeTemplate.compilation.compiler)
- ) || [])
- ];
- 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();
- /** @type {string} */
- 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)
- ) {
- // a non-arrow bootstrap IIFE is called without a receiver, so in strict
- // mode the `this` that `output.globalObject` reads would be undefined
- const globalObjectNeedsThis =
- iife &&
- !runtimeTemplate.supportsArrowFunction() &&
- runtimeTemplate.globalObjectUsesThis();
- const strictBailout =
- hooks.strictRuntimeBailout.call(renderContext) ||
- (globalObjectNeedsThis
- ? "'output.globalObject' reads 'this'"
- : undefined);
- 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, renderInObject) =>
- this.renderModule(
- module,
- { ...chunkRenderContext, factory: true, renderInObject },
- hooks
- ),
- 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();
- const avoidEntryIife = compilation.options.optimization.avoidEntryIife;
- /** @type {Map<Module, Source> | false} */
- let renamedInlinedModule = false;
- let inlinedInIIFE = false;
- if (avoidEntryIife) {
- renamedInlinedModule = this._getRenamedInlineModule(
- compilation,
- allModules,
- renderContext,
- inlinedModules,
- chunkRenderContext,
- hooks,
- allStrict,
- Boolean(chunkModules)
- );
- }
- for (const m of inlinedModules) {
- const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
- m,
- chunk.runtime
- );
- const exports = runtimeRequirements.has(RuntimeGlobals.exports);
- const webpackExports =
- exports && m.exportsArgument === RuntimeGlobals.exports;
- const innerStrict =
- !allStrict && /** @type {BuildInfo} */ (m.buildInfo).strict;
- const iife = innerStrict
- ? "it needs to be in strict mode."
- : inlinedModules.size > 1 && !renamedInlinedModule
- ? "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);
- if (iife) {
- inlinedInIIFE = true;
- }
- const renderedModule = renamedInlinedModule
- ? renamedInlinedModule.get(m)
- : this.renderModule(
- m,
- {
- ...chunkRenderContext,
- factory: false,
- inlinedInIIFE
- },
- hooks
- );
- if (renderedModule) {
- /** @type {string} */
- 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(
- `${runtimeTemplate.renderLet()} ${m.exportsArgument} = {};\n`
- );
- } else if (m.exportsArgument !== RuntimeGlobals.exports) {
- startupSource.add(
- `${runtimeTemplate.renderLet()} ${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`
- );
- }
- /** @type {StartupRenderContext} */
- const startupRenderContext = {
- ...renderContext,
- inlined: true,
- inlinedInIIFE,
- needExportsDeclaration: runtimeRequirements.has(RuntimeGlobals.exports)
- };
- let renderedStartup = hooks.renderStartup.call(
- startupSource,
- lastInlinedModule,
- startupRenderContext
- );
- const lastInlinedModuleRequirements =
- chunkGraph.getModuleRuntimeRequirements(
- lastInlinedModule,
- chunk.runtime
- );
- if (
- // `onChunksLoaded` reads and reassigns `__webpack_exports__`
- runtimeRequirements.has(RuntimeGlobals.onChunksLoaded) ||
- // Top-level `__webpack_exports__` will be returned
- runtimeRequirements.has(RuntimeGlobals.returnExportsFromRuntime) ||
- // Custom exports argument aliases from `__webpack_exports__`
- (lastInlinedModuleRequirements.has(RuntimeGlobals.exports) &&
- lastInlinedModule.exportsArgument !== RuntimeGlobals.exports)
- ) {
- startupRenderContext.needExportsDeclaration = true;
- }
- if (startupRenderContext.needExportsDeclaration) {
- renderedStartup = new ConcatSource(
- `${runtimeTemplate.renderLet()} ${RuntimeGlobals.exports} = {};\n`,
- renderedStartup
- );
- }
- source.add(renderedStartup);
- 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,
- needExportsDeclaration: true
- }
- ),
- 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;
- }
- /**
- * Updates hash with bootstrap.
- * @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]));
- }
- }
- }
- /**
- * Renders the generated source of the bootstrap code.
- * @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;
- }
- const bootstrapCst = runtimeTemplate.renderConst();
- if (useRequire || moduleCache) {
- buf.push("// The module cache");
- buf.push(`${bootstrapCst} __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(`${bootstrapCst} __webpack_module_deferred_exports__ = {};`);
- // Per the TC39 import-defer spec, every defer-import call site for
- // the same module must yield the same Deferred Module Namespace
- // Exotic Object (and a distinct one from any eager namespace).
- // Cache the deferred namespace proxy here so calls from different
- // files share identity.
- buf.push("// The deferred namespace cache");
- buf.push(
- `${bootstrapCst} __webpack_module_deferred_namespace_cache__ = {};`
- );
- 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(`${bootstrapCst} ${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");
- /** @type {EntryModuleWithChunkGroup[]} */
- const jsEntries = [];
- for (const [
- entryModule,
- entrypoint
- ] of chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)) {
- if (
- chunkGraph.getModuleSourceTypes(entryModule).has(JAVASCRIPT_TYPE)
- ) {
- jsEntries.push([entryModule, entrypoint]);
- continue;
- }
- }
- let i = jsEntries.length;
- for (const [entryModule, entrypoint] of jsEntries) {
- 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;
- }
- /** @type {undefined | CodeGenerationResultData} */
- 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) {
- // the bail-out above already established that one of the two
- // sources carries them
- const topLevelDeclarations =
- (data && data.get("topLevelDeclarations")) ||
- /** @type {BuildInfo} */ (entryModule.buildInfo)
- .topLevelDeclarations;
- for (const name of CHUNK_RUNTIME_DECLARATIONS) {
- if (/** @type {Set<string>} */ (topLevelDeclarations).has(name)) {
- buf2.push(
- `// This entry module declares '${name}' on top-level, which the runtime also declares, so it can't be inlined`
- );
- result.allowInlineStartup = false;
- break;
- }
- }
- }
- 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 (
- result.allowInlineStartup &&
- entryRuntimeRequirements.has(RuntimeGlobals.thisAsExports)
- ) {
- buf2.push(
- "// This entry module used `this` as exports so it can't be inlined"
- );
- result.allowInlineStartup = false;
- }
- // `__webpack_exports__` may be reassigned later — by the
- // `onChunksLoaded` wrapper below, by an inlined entry
- // module that uses top-level `await` (the emitted
- // bridge reassigns `__webpack_exports__` to the awaited
- // value), or by other downstream codegen. Always declare
- // with `let` (or `var` if `let` is unsupported) so
- // reassignment is allowed.
- const exportsDecl = runtimeTemplate.renderLet();
- if (chunks.length > 0) {
- buf2.push(
- `${i === 0 ? `${exportsDecl} ${RuntimeGlobals.exports} = ` : ""}${
- RuntimeGlobals.onChunksLoaded
- }(undefined, ${JSON.stringify(
- chunks.map((c) => c.id)
- )}, ${runtimeTemplate.returningFunction(
- `${RuntimeGlobals.require}(${moduleIdExpr})`
- )})`
- );
- } else if (useRequire) {
- buf2.push(
- `${i === 0 ? `${exportsDecl} ${RuntimeGlobals.exports} = ` : ""}${
- RuntimeGlobals.require
- }(${moduleIdExpr});`
- );
- } else {
- if (i === 0) {
- buf2.push(`${exportsDecl} ${RuntimeGlobals.exports} = {};`);
- }
- const needThisAsExports = entryRuntimeRequirements.has(
- RuntimeGlobals.thisAsExports
- );
- /** @type {string[]} */
- const args = [];
- if (
- requireScopeUsed ||
- entryRuntimeRequirements.has(RuntimeGlobals.exports)
- ) {
- const exportsArg = i === 0 ? RuntimeGlobals.exports : "{}";
- args.push("0", exportsArg);
- if (requireScopeUsed) {
- args.push(RuntimeGlobals.require);
- }
- }
- buf2.push(
- Template.asString(
- (() => {
- if (needThisAsExports) {
- const comma = args.length ? "," : "";
- return `__webpack_modules__[${moduleIdExpr}].call(${
- RuntimeGlobals.exports
- }${comma}${args.join(",")});`;
- }
- return `__webpack_modules__[${moduleIdExpr}](${args.join(
- ","
- )});`;
- })()
- )
- );
- }
- }
- 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;
- }
- /**
- * Renders the generated source of the require function.
- * @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 } = renderContext;
- const { outputOptions } = runtimeTemplate;
- const cst = runtimeTemplate.renderConst();
- const lt = runtimeTemplate.renderLet();
- const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
- /**
- * Renders missing module error.
- * @param {string} condition guard expression
- * @returns {string[]} source
- */
- const renderMissingModuleError = (condition) =>
- outputOptions.strictModuleResolution
- ? [
- `if (${condition}) {`,
- Template.indent([
- "delete __webpack_module_cache__[moduleId];",
- `${cst} e = new Error("Cannot find module '" + moduleId + "'");`,
- "e.code = 'MODULE_NOT_FOUND';",
- "throw e;"
- ]),
- "}"
- ]
- : [];
- const moduleExecution = runtimeRequirements.has(
- RuntimeGlobals.interceptModuleExecution
- )
- ? Template.asString([
- `${cst} execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: ${RuntimeGlobals.require} };`,
- `${RuntimeGlobals.interceptModuleExecution}.forEach(function(handler) { handler(execOptions); });`,
- ...renderMissingModuleError("!execOptions.factory"),
- "module = execOptions.module;",
- "execOptions.factory.call(module.exports, module, module.exports, execOptions.require);"
- ])
- : runtimeRequirements.has(RuntimeGlobals.thisAsExports)
- ? Template.asString([
- ...renderMissingModuleError("!(moduleId in __webpack_modules__)"),
- `__webpack_modules__[moduleId].call(module.exports, module, module.exports, ${RuntimeGlobals.require});`
- ])
- : Template.asString([
- ...renderMissingModuleError("!(moduleId in __webpack_modules__)"),
- `__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
- );
- // Both deferred-namespace runtimes re-invoke `__webpack_require__` on
- // access, so a module's evaluation error must be retained and re-thrown
- // (a Cyclic Module Record's [[EvaluationError]]); the optimized variant
- // does not use `__webpack_module_deferred_exports__`, so it is tracked
- // separately from `needModuleDefer`.
- const needModuleDeferAny =
- needModuleDefer ||
- runtimeRequirements.has(
- RuntimeGlobals.makeOptimizedDeferredNamespaceObject
- );
- const needModuleErrorCaching =
- outputOptions.strictModuleErrorHandling || needModuleDeferAny;
- // `module` is reassigned by the interceptModuleExecution path; use `let`.
- const moduleDecl = runtimeRequirements.has(
- RuntimeGlobals.interceptModuleExecution
- )
- ? lt
- : cst;
- const content = Template.asString([
- "// Check if module is in cache",
- `${cst} cachedModule = __webpack_module_cache__[moduleId];`,
- "if (cachedModule !== undefined) {",
- needModuleErrorCaching
- ? 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)",
- `${moduleDecl} 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 && !needModuleErrorCaching
- ? Template.asString([
- "// Execute the module function",
- `${lt} 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];"
- ]),
- "}"
- ])
- : needModuleErrorCaching
- ? Template.asString([
- "// Execute the module function",
- // Mark the module as evaluating so a deferred namespace that
- // forces evaluation of an already-evaluating module can throw
- // instead of exposing its partial exports.
- ...(needModuleDeferAny ? ["module.evaluating = true;"] : []),
- "try {",
- Template.indent([
- moduleExecution,
- ...(needModuleDefer
- ? ["delete __webpack_module_deferred_exports__[moduleId];"]
- : []),
- ...(needModuleDeferAny ? ["module.evaluating = false;"] : [])
- ]),
- "} catch(e) {",
- Template.indent([
- ...(needModuleDeferAny ? ["module.evaluating = false;"] : []),
- "module.error = e;",
- "throw e;"
- ]),
- "}"
- ])
- : Template.asString([
- "// Execute the module function",
- moduleExecution,
- ...(needModuleDefer
- ? ["delete __webpack_module_deferred_exports__[moduleId];"]
- : [])
- ]),
- 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"
- );
- }
- /**
- * Get renamed inline module.
- * @param {Compilation} compilation compilation
- * @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(
- compilation,
- 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;
- // This step is before the IIFE reason calculation; it only runs for the
- // cases whose IIFE reason it can remove: multiple inlined entry modules, or a
- // single inlined entry alongside other chunk modules. The remaining reason
- // ('it uses a non-standard name for the exports') is not handled here.
- if (innerStrict || (!isMultipleEntries && !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>} */
- const inlinedModuleSources = new Map();
- for (const m of allModules) {
- const isInlinedModule = inlinedModules && inlinedModules.has(m);
- const moduleSource = this.renderModule(
- m,
- {
- ...chunkRenderContext,
- factory: !isInlinedModule,
- inlinedInIIFE: false
- },
- hooks
- );
- if (!moduleSource) continue;
- if (isInlinedModule) {
- // Parsing the inlined entry (often the whole concatenated app) is
- // expensive; defer it until we know renaming is actually needed.
- inlinedModuleSources.set(m, moduleSource);
- continue;
- }
- const code = /** @type {string} */ (moduleSource.source());
- const { experiments } = compilation.options;
- const { ast } = JavascriptParser._parse(
- code,
- {
- sourceType: "auto",
- ranges: true,
- // generated code contains phase imports when the experiments are on
- importPhases: Boolean(
- experiments.deferImport || experiments.sourceImport
- )
- },
- JavascriptParser._getModuleParseFunction(compilation, m)
- );
- const analysis = analyzeScope(ast);
- for (const ref of analysis.unresolvedReferences) {
- nonInlinedModuleThroughIdentifiers.add(ref.identifier.name);
- }
- }
- // Fast path: codegen reports each inlined entry's rendered top-level
- // declarations and free names (post-concatenation), so when no declaration
- // collides with a free name of any other module, another entry's
- // declarations, or a reserved name, no renaming is needed and the entries
- // don't have to be parsed at all.
- fastPath: {
- const { codeGenerationResults, chunk } = renderContext;
- /** @type {Set<string>} */
- const usedNames = new Set(nonInlinedModuleThroughIdentifiers);
- for (const name of RESERVED_NAMES) usedNames.add(name);
- /** @type {Set<string>[]} */
- const declarationsList = [];
- for (const m of inlinedModuleSources.keys()) {
- if (!codeGenerationResults.has(m, chunk.runtime)) break fastPath;
- const result = codeGenerationResults.get(m, chunk.runtime);
- const data = result.data;
- if (!data) break fastPath;
- const declarations = data.get("topLevelDeclarations");
- if (!declarations) break fastPath;
- declarationsList.push(declarations);
- if (!isMultipleEntries) continue;
- // Entries share the startup scope: an entry's free names and runtime
- // globals must not be shadowed by another entry's declarations.
- const freeNames = data.get("freeNames");
- if (!freeNames) break fastPath;
- for (const name of freeNames) usedNames.add(name);
- if (result.runtimeRequirements) {
- for (const req of result.runtimeRequirements) {
- const dot = req.indexOf(".");
- usedNames.add(dot === -1 ? req : req.slice(0, dot));
- }
- }
- }
- for (const declarations of declarationsList) {
- for (const name of declarations) {
- if (usedNames.has(name)) break fastPath;
- }
- // earlier entries' declarations join the used set so later entries
- // are checked against them
- for (const name of declarations) usedNames.add(name);
- }
- for (const [m, moduleSource] of inlinedModuleSources) {
- renamedInlinedModules.set(m, moduleSource);
- }
- return renamedInlinedModules;
- }
- for (const [m, moduleSource] of inlinedModuleSources) {
- const code = /** @type {string} */ (moduleSource.source());
- const { experiments } = compilation.options;
- const { ast } = JavascriptParser._parse(
- code,
- {
- sourceType: "auto",
- ranges: true,
- // generated code contains phase imports when the experiments are on
- importPhases: Boolean(
- experiments.deferImport || experiments.sourceImport
- )
- },
- JavascriptParser._getModuleParseFunction(compilation, m)
- );
- const analysis = analyzeScope(ast);
- const moduleScope = analysis.moduleScope;
- inlinedModulesToInfo.set(m, {
- source: moduleSource,
- ast,
- module: m,
- variables: new Set(moduleScope.variables),
- through: new Set(analysis.unresolvedReferences),
- usedInNonInlined: new Set(),
- moduleScope
- });
- }
- for (const [, { variables, usedInNonInlined }] of inlinedModulesToInfo) {
- for (const variable of variables) {
- if (
- nonInlinedModuleThroughIdentifiers.has(variable.name) ||
- RESERVED_NAMES.has(variable.name)
- ) {
- usedInNonInlined.add(variable);
- }
- }
- }
- // Multiple inlined entry modules share the chunk's startup scope. Rename any
- // top-level declaration that would collide with another inlined module's
- // declaration, with any inlined or non-inlined module's free (global)
- // reference, or with a reserved name, so the modules can be emitted without a
- // per-entry IIFE.
- if (isMultipleEntries) {
- /** @type {Set<string>} */
- const allUsedNames = new Set(nonInlinedModuleThroughIdentifiers);
- for (const name of RESERVED_NAMES) allUsedNames.add(name);
- for (const { through } of inlinedModulesToInfo.values()) {
- for (const ref of through) allUsedNames.add(ref.identifier.name);
- }
- for (const [m, moduleInfo] of inlinedModulesToInfo) {
- const { ast, source: _source } = moduleInfo;
- const source = new ReplaceSource(_source);
- for (const variable of moduleInfo.variables) {
- renameInlinedModuleVariable(
- source,
- ast,
- variable,
- moduleInfo.module.identifier(),
- m.readableIdentifier(runtimeTemplate.requestShortener),
- allUsedNames
- );
- }
- renamedInlinedModules.set(m, source);
- }
- return renamedInlinedModules;
- }
- 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) {
- renameInlinedModuleVariable(
- source,
- ast,
- variable,
- info.module.identifier(),
- m.readableIdentifier(runtimeTemplate.requestShortener),
- allUsedNames
- );
- }
- renamedInlinedModules.set(m, source);
- }
- return renamedInlinedModules;
- }
- }
- JavascriptModulesPlugin.getCompilationHooks = createHooksRegistry(
- createCompilationHooks
- );
- JavascriptModulesPlugin.chunkHasJs = chunkHasJs;
- module.exports = JavascriptModulesPlugin;
|