1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const eslintScope = require("eslint-scope");
- const Referencer = require("eslint-scope/lib/referencer");
- const {
- CachedSource,
- ConcatSource,
- ReplaceSource
- } = require("webpack-sources");
- const ConcatenationScope = require("../ConcatenationScope");
- const { UsageState } = require("../ExportsInfo");
- const Module = require("../Module");
- const RuntimeGlobals = require("../RuntimeGlobals");
- const Template = require("../Template");
- const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
- const JavascriptParser = require("../javascript/JavascriptParser");
- const { equals } = require("../util/ArrayHelpers");
- const LazySet = require("../util/LazySet");
- const { concatComparators } = require("../util/comparators");
- const createHash = require("../util/createHash");
- const { makePathsRelative } = require("../util/identifier");
- const makeSerializable = require("../util/makeSerializable");
- const propertyAccess = require("../util/propertyAccess");
- const {
- filterRuntime,
- intersectRuntime,
- mergeRuntimeCondition,
- mergeRuntimeConditionNonFalse,
- runtimeConditionToString,
- subtractRuntimeCondition
- } = require("../util/runtime");
- /** @typedef {import("eslint-scope").Scope} Scope */
- /** @typedef {import("webpack-sources").Source} Source */
- /** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
- /** @typedef {import("../ChunkGraph")} ChunkGraph */
- /** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
- /** @typedef {import("../Compilation")} Compilation */
- /** @typedef {import("../Dependency")} Dependency */
- /** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
- /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
- /** @typedef {import("../DependencyTemplates")} DependencyTemplates */
- /** @typedef {import("../ExportsInfo").ExportInfo} ExportInfo */
- /** @template T @typedef {import("../InitFragment")<T>} InitFragment */
- /** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
- /** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
- /** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
- /** @typedef {import("../ModuleGraph")} ModuleGraph */
- /** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
- /** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
- /** @typedef {import("../RequestShortener")} RequestShortener */
- /** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
- /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
- /** @typedef {import("../WebpackError")} WebpackError */
- /** @typedef {import("../javascript/JavascriptModulesPlugin").ChunkRenderContext} ChunkRenderContext */
- /** @typedef {import("../util/Hash")} Hash */
- /** @typedef {typeof import("../util/Hash")} HashConstructor */
- /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
- /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
- // fix eslint-scope to support class properties correctly
- // cspell:word Referencer
- const ReferencerClass = Referencer;
- if (!ReferencerClass.prototype.PropertyDefinition) {
- ReferencerClass.prototype.PropertyDefinition =
- ReferencerClass.prototype.Property;
- }
- /**
- * @typedef {Object} ReexportInfo
- * @property {Module} module
- * @property {string[]} export
- */
- /** @typedef {RawBinding | SymbolBinding} Binding */
- /**
- * @typedef {Object} RawBinding
- * @property {ModuleInfo} info
- * @property {string} rawName
- * @property {string=} comment
- * @property {string[]} ids
- * @property {string[]} exportName
- */
- /**
- * @typedef {Object} SymbolBinding
- * @property {ConcatenatedModuleInfo} info
- * @property {string} name
- * @property {string=} comment
- * @property {string[]} ids
- * @property {string[]} exportName
- */
- /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo } ModuleInfo */
- /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo | ReferenceToModuleInfo } ModuleInfoOrReference */
- /**
- * @typedef {Object} ConcatenatedModuleInfo
- * @property {"concatenated"} type
- * @property {Module} module
- * @property {number} index
- * @property {Object} ast
- * @property {Source} internalSource
- * @property {ReplaceSource} source
- * @property {InitFragment<ChunkRenderContext>[]=} chunkInitFragments
- * @property {Iterable<string>} runtimeRequirements
- * @property {Scope} globalScope
- * @property {Scope} moduleScope
- * @property {Map<string, string>} internalNames
- * @property {Map<string, string>} exportMap
- * @property {Map<string, string>} rawExportMap
- * @property {string=} namespaceExportSymbol
- * @property {string} namespaceObjectName
- * @property {boolean} interopNamespaceObjectUsed
- * @property {string} interopNamespaceObjectName
- * @property {boolean} interopNamespaceObject2Used
- * @property {string} interopNamespaceObject2Name
- * @property {boolean} interopDefaultAccessUsed
- * @property {string} interopDefaultAccessName
- */
- /**
- * @typedef {Object} ExternalModuleInfo
- * @property {"external"} type
- * @property {Module} module
- * @property {RuntimeSpec | boolean} runtimeCondition
- * @property {number} index
- * @property {string} name
- * @property {boolean} interopNamespaceObjectUsed
- * @property {string} interopNamespaceObjectName
- * @property {boolean} interopNamespaceObject2Used
- * @property {string} interopNamespaceObject2Name
- * @property {boolean} interopDefaultAccessUsed
- * @property {string} interopDefaultAccessName
- */
- /**
- * @typedef {Object} ReferenceToModuleInfo
- * @property {"reference"} type
- * @property {RuntimeSpec | boolean} runtimeCondition
- * @property {ConcatenatedModuleInfo | ExternalModuleInfo} target
- */
- const RESERVED_NAMES = new Set(
- [
- // internal names (should always be renamed)
- ConcatenationScope.DEFAULT_EXPORT,
- ConcatenationScope.NAMESPACE_OBJECT_EXPORT,
- // keywords
- "abstract,arguments,async,await,boolean,break,byte,case,catch,char,class,const,continue",
- "debugger,default,delete,do,double,else,enum,eval,export,extends,false,final,finally,float",
- "for,function,goto,if,implements,import,in,instanceof,int,interface,let,long,native,new,null",
- "package,private,protected,public,return,short,static,super,switch,synchronized,this,throw",
- "throws,transient,true,try,typeof,var,void,volatile,while,with,yield",
- // commonjs/amd
- "module,__dirname,__filename,exports,require,define",
- // js globals
- "Array,Date,eval,function,hasOwnProperty,Infinity,isFinite,isNaN,isPrototypeOf,length,Math",
- "NaN,name,Number,Object,prototype,String,toString,undefined,valueOf",
- // browser globals
- "alert,all,anchor,anchors,area,assign,blur,button,checkbox,clearInterval,clearTimeout",
- "clientInformation,close,closed,confirm,constructor,crypto,decodeURI,decodeURIComponent",
- "defaultStatus,document,element,elements,embed,embeds,encodeURI,encodeURIComponent,escape",
- "event,fileUpload,focus,form,forms,frame,innerHeight,innerWidth,layer,layers,link,location",
- "mimeTypes,navigate,navigator,frames,frameRate,hidden,history,image,images,offscreenBuffering",
- "open,opener,option,outerHeight,outerWidth,packages,pageXOffset,pageYOffset,parent,parseFloat",
- "parseInt,password,pkcs11,plugin,prompt,propertyIsEnum,radio,reset,screenX,screenY,scroll",
- "secure,select,self,setInterval,setTimeout,status,submit,taint,text,textarea,top,unescape",
- "untaint,window",
- // window events
- "onblur,onclick,onerror,onfocus,onkeydown,onkeypress,onkeyup,onmouseover,onload,onmouseup,onmousedown,onsubmit"
- ]
- .join(",")
- .split(",")
- );
- const createComparator = (property, comparator) => (a, b) =>
- comparator(a[property], b[property]);
- const compareNumbers = (a, b) => {
- if (isNaN(a)) {
- if (!isNaN(b)) {
- return 1;
- }
- } else {
- if (isNaN(b)) {
- return -1;
- }
- if (a !== b) {
- return a < b ? -1 : 1;
- }
- }
- return 0;
- };
- const bySourceOrder = createComparator("sourceOrder", compareNumbers);
- const byRangeStart = createComparator("rangeStart", compareNumbers);
- const joinIterableWithComma = iterable => {
- // This is more performant than Array.from().join(", ")
- // as it doesn't create an array
- let str = "";
- let first = true;
- for (const item of iterable) {
- if (first) {
- first = false;
- } else {
- str += ", ";
- }
- str += item;
- }
- return str;
- };
- /**
- * @typedef {Object} ConcatenationEntry
- * @property {"concatenated" | "external"} type
- * @property {Module} module
- * @property {RuntimeSpec | boolean} runtimeCondition
- */
- /**
- * @param {ModuleGraph} moduleGraph the module graph
- * @param {ModuleInfo} info module info
- * @param {string[]} exportName exportName
- * @param {Map<Module, ModuleInfo>} moduleToInfoMap moduleToInfoMap
- * @param {RuntimeSpec} runtime for which runtime
- * @param {RequestShortener} requestShortener the request shortener
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @param {Set<ConcatenatedModuleInfo>} neededNamespaceObjects modules for which a namespace object should be generated
- * @param {boolean} asCall asCall
- * @param {boolean} strictHarmonyModule strictHarmonyModule
- * @param {boolean | undefined} asiSafe asiSafe
- * @param {Set<ExportInfo>} alreadyVisited alreadyVisited
- * @returns {Binding} the final variable
- */
- const getFinalBinding = (
- moduleGraph,
- info,
- exportName,
- moduleToInfoMap,
- runtime,
- requestShortener,
- runtimeTemplate,
- neededNamespaceObjects,
- asCall,
- strictHarmonyModule,
- asiSafe,
- alreadyVisited = new Set()
- ) => {
- const exportsType = info.module.getExportsType(
- moduleGraph,
- strictHarmonyModule
- );
- if (exportName.length === 0) {
- switch (exportsType) {
- case "default-only":
- info.interopNamespaceObject2Used = true;
- return {
- info,
- rawName: info.interopNamespaceObject2Name,
- ids: exportName,
- exportName
- };
- case "default-with-named":
- info.interopNamespaceObjectUsed = true;
- return {
- info,
- rawName: info.interopNamespaceObjectName,
- ids: exportName,
- exportName
- };
- case "namespace":
- case "dynamic":
- break;
- default:
- throw new Error(`Unexpected exportsType ${exportsType}`);
- }
- } else {
- switch (exportsType) {
- case "namespace":
- break;
- case "default-with-named":
- switch (exportName[0]) {
- case "default":
- exportName = exportName.slice(1);
- break;
- case "__esModule":
- return {
- info,
- rawName: "/* __esModule */true",
- ids: exportName.slice(1),
- exportName
- };
- }
- break;
- case "default-only": {
- const exportId = exportName[0];
- if (exportId === "__esModule") {
- return {
- info,
- rawName: "/* __esModule */true",
- ids: exportName.slice(1),
- exportName
- };
- }
- exportName = exportName.slice(1);
- if (exportId !== "default") {
- return {
- info,
- rawName:
- "/* non-default import from default-exporting module */undefined",
- ids: exportName,
- exportName
- };
- }
- break;
- }
- case "dynamic":
- switch (exportName[0]) {
- case "default": {
- exportName = exportName.slice(1);
- info.interopDefaultAccessUsed = true;
- const defaultExport = asCall
- ? `${info.interopDefaultAccessName}()`
- : asiSafe
- ? `(${info.interopDefaultAccessName}())`
- : asiSafe === false
- ? `;(${info.interopDefaultAccessName}())`
- : `${info.interopDefaultAccessName}.a`;
- return {
- info,
- rawName: defaultExport,
- ids: exportName,
- exportName
- };
- }
- case "__esModule":
- return {
- info,
- rawName: "/* __esModule */true",
- ids: exportName.slice(1),
- exportName
- };
- }
- break;
- default:
- throw new Error(`Unexpected exportsType ${exportsType}`);
- }
- }
- if (exportName.length === 0) {
- switch (info.type) {
- case "concatenated":
- neededNamespaceObjects.add(info);
- return {
- info,
- rawName: info.namespaceObjectName,
- ids: exportName,
- exportName
- };
- case "external":
- return { info, rawName: info.name, ids: exportName, exportName };
- }
- }
- const exportsInfo = moduleGraph.getExportsInfo(info.module);
- const exportInfo = exportsInfo.getExportInfo(exportName[0]);
- if (alreadyVisited.has(exportInfo)) {
- return {
- info,
- rawName: "/* circular reexport */ Object(function x() { x() }())",
- ids: [],
- exportName
- };
- }
- alreadyVisited.add(exportInfo);
- switch (info.type) {
- case "concatenated": {
- const exportId = exportName[0];
- if (exportInfo.provided === false) {
- // It's not provided, but it could be on the prototype
- neededNamespaceObjects.add(info);
- return {
- info,
- rawName: info.namespaceObjectName,
- ids: exportName,
- exportName
- };
- }
- const directExport = info.exportMap && info.exportMap.get(exportId);
- if (directExport) {
- const usedName = /** @type {string[]} */ (
- exportsInfo.getUsedName(exportName, runtime)
- );
- if (!usedName) {
- return {
- info,
- rawName: "/* unused export */ undefined",
- ids: exportName.slice(1),
- exportName
- };
- }
- return {
- info,
- name: directExport,
- ids: usedName.slice(1),
- exportName
- };
- }
- const rawExport = info.rawExportMap && info.rawExportMap.get(exportId);
- if (rawExport) {
- return {
- info,
- rawName: rawExport,
- ids: exportName.slice(1),
- exportName
- };
- }
- const reexport = exportInfo.findTarget(moduleGraph, module =>
- moduleToInfoMap.has(module)
- );
- if (reexport === false) {
- throw new Error(
- `Target module of reexport from '${info.module.readableIdentifier(
- requestShortener
- )}' is not part of the concatenation (export '${exportId}')\nModules in the concatenation:\n${Array.from(
- moduleToInfoMap,
- ([m, info]) =>
- ` * ${info.type} ${m.readableIdentifier(requestShortener)}`
- ).join("\n")}`
- );
- }
- if (reexport) {
- const refInfo = moduleToInfoMap.get(reexport.module);
- return getFinalBinding(
- moduleGraph,
- refInfo,
- reexport.export
- ? [...reexport.export, ...exportName.slice(1)]
- : exportName.slice(1),
- moduleToInfoMap,
- runtime,
- requestShortener,
- runtimeTemplate,
- neededNamespaceObjects,
- asCall,
- info.module.buildMeta.strictHarmonyModule,
- asiSafe,
- alreadyVisited
- );
- }
- if (info.namespaceExportSymbol) {
- const usedName = /** @type {string[]} */ (
- exportsInfo.getUsedName(exportName, runtime)
- );
- return {
- info,
- rawName: info.namespaceObjectName,
- ids: usedName,
- exportName
- };
- }
- throw new Error(
- `Cannot get final name for export '${exportName.join(
- "."
- )}' of ${info.module.readableIdentifier(requestShortener)}`
- );
- }
- case "external": {
- const used = /** @type {string[]} */ (
- exportsInfo.getUsedName(exportName, runtime)
- );
- if (!used) {
- return {
- info,
- rawName: "/* unused export */ undefined",
- ids: exportName.slice(1),
- exportName
- };
- }
- const comment = equals(used, exportName)
- ? ""
- : Template.toNormalComment(`${exportName.join(".")}`);
- return { info, rawName: info.name + comment, ids: used, exportName };
- }
- }
- };
- /**
- * @param {ModuleGraph} moduleGraph the module graph
- * @param {ModuleInfo} info module info
- * @param {string[]} exportName exportName
- * @param {Map<Module, ModuleInfo>} moduleToInfoMap moduleToInfoMap
- * @param {RuntimeSpec} runtime for which runtime
- * @param {RequestShortener} requestShortener the request shortener
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @param {Set<ConcatenatedModuleInfo>} neededNamespaceObjects modules for which a namespace object should be generated
- * @param {boolean} asCall asCall
- * @param {boolean} callContext callContext
- * @param {boolean} strictHarmonyModule strictHarmonyModule
- * @param {boolean | undefined} asiSafe asiSafe
- * @returns {string} the final name
- */
- const getFinalName = (
- moduleGraph,
- info,
- exportName,
- moduleToInfoMap,
- runtime,
- requestShortener,
- runtimeTemplate,
- neededNamespaceObjects,
- asCall,
- callContext,
- strictHarmonyModule,
- asiSafe
- ) => {
- const binding = getFinalBinding(
- moduleGraph,
- info,
- exportName,
- moduleToInfoMap,
- runtime,
- requestShortener,
- runtimeTemplate,
- neededNamespaceObjects,
- asCall,
- strictHarmonyModule,
- asiSafe
- );
- {
- const { ids, comment } = binding;
- let reference;
- let isPropertyAccess;
- if ("rawName" in binding) {
- reference = `${binding.rawName}${comment || ""}${propertyAccess(ids)}`;
- isPropertyAccess = ids.length > 0;
- } else {
- const { info, name: exportId } = binding;
- const name = info.internalNames.get(exportId);
- if (!name) {
- throw new Error(
- `The export "${exportId}" in "${info.module.readableIdentifier(
- requestShortener
- )}" has no internal name (existing names: ${
- Array.from(
- info.internalNames,
- ([name, symbol]) => `${name}: ${symbol}`
- ).join(", ") || "none"
- })`
- );
- }
- reference = `${name}${comment || ""}${propertyAccess(ids)}`;
- isPropertyAccess = ids.length > 1;
- }
- if (isPropertyAccess && asCall && callContext === false) {
- return asiSafe
- ? `(0,${reference})`
- : asiSafe === false
- ? `;(0,${reference})`
- : `/*#__PURE__*/Object(${reference})`;
- }
- return reference;
- }
- };
- const addScopeSymbols = (s, nameSet, scopeSet1, scopeSet2) => {
- let scope = s;
- while (scope) {
- if (scopeSet1.has(scope)) break;
- if (scopeSet2.has(scope)) break;
- scopeSet1.add(scope);
- for (const variable of scope.variables) {
- nameSet.add(variable.name);
- }
- scope = scope.upper;
- }
- };
- const getAllReferences = variable => {
- let set = variable.references;
- // Look for inner scope variables too (like in class Foo { t() { Foo } })
- const identifiers = new Set(variable.identifiers);
- for (const scope of variable.scope.childScopes) {
- for (const innerVar of scope.variables) {
- if (innerVar.identifiers.some(id => identifiers.has(id))) {
- set = set.concat(innerVar.references);
- break;
- }
- }
- }
- return set;
- };
- const getPathInAst = (ast, node) => {
- if (ast === node) {
- return [];
- }
- const nr = node.range;
- const enterNode = n => {
- if (!n) return undefined;
- const r = n.range;
- if (r) {
- if (r[0] <= nr[0] && r[1] >= nr[1]) {
- const path = getPathInAst(n, node);
- if (path) {
- path.push(n);
- return path;
- }
- }
- }
- return undefined;
- };
- if (Array.isArray(ast)) {
- for (let i = 0; i < ast.length; i++) {
- const enterResult = enterNode(ast[i]);
- if (enterResult !== undefined) return enterResult;
- }
- } else if (ast && typeof ast === "object") {
- const keys = Object.keys(ast);
- for (let i = 0; i < keys.length; i++) {
- const value = ast[keys[i]];
- if (Array.isArray(value)) {
- const pathResult = getPathInAst(value, node);
- if (pathResult !== undefined) return pathResult;
- } else if (value && typeof value === "object") {
- const enterResult = enterNode(value);
- if (enterResult !== undefined) return enterResult;
- }
- }
- }
- };
- const TYPES = new Set(["javascript"]);
- class ConcatenatedModule extends Module {
- /**
- * @param {Module} rootModule the root module of the concatenation
- * @param {Set<Module>} modules all modules in the concatenation (including the root module)
- * @param {RuntimeSpec} runtime the runtime
- * @param {Object=} associatedObjectForCache object for caching
- * @param {string | HashConstructor=} hashFunction hash function to use
- * @returns {ConcatenatedModule} the module
- */
- static create(
- rootModule,
- modules,
- runtime,
- associatedObjectForCache,
- hashFunction = "md4"
- ) {
- const identifier = ConcatenatedModule._createIdentifier(
- rootModule,
- modules,
- associatedObjectForCache,
- hashFunction
- );
- return new ConcatenatedModule({
- identifier,
- rootModule,
- modules,
- runtime
- });
- }
- /**
- * @param {Object} options options
- * @param {string} options.identifier the identifier of the module
- * @param {Module=} options.rootModule the root module of the concatenation
- * @param {RuntimeSpec} options.runtime the selected runtime
- * @param {Set<Module>=} options.modules all concatenated modules
- */
- constructor({ identifier, rootModule, modules, runtime }) {
- super("javascript/esm", null, rootModule && rootModule.layer);
- // Info from Factory
- /** @type {string} */
- this._identifier = identifier;
- /** @type {Module} */
- this.rootModule = rootModule;
- /** @type {Set<Module>} */
- this._modules = modules;
- this._runtime = runtime;
- this.factoryMeta = rootModule && rootModule.factoryMeta;
- }
- /**
- * Assuming this module is in the cache. Update the (cached) module with
- * the fresh module from the factory. Usually updates internal references
- * and properties.
- * @param {Module} module fresh module
- * @returns {void}
- */
- updateCacheModule(module) {
- throw new Error("Must not be called");
- }
- /**
- * @returns {Set<string>} types available (do not mutate)
- */
- getSourceTypes() {
- return TYPES;
- }
- get modules() {
- return Array.from(this._modules);
- }
- /**
- * @returns {string} a unique identifier of the module
- */
- identifier() {
- return this._identifier;
- }
- /**
- * @param {RequestShortener} requestShortener the request shortener
- * @returns {string} a user readable identifier of the module
- */
- readableIdentifier(requestShortener) {
- return (
- this.rootModule.readableIdentifier(requestShortener) +
- ` + ${this._modules.size - 1} modules`
- );
- }
- /**
- * @param {LibIdentOptions} options options
- * @returns {string | null} an identifier for library inclusion
- */
- libIdent(options) {
- return this.rootModule.libIdent(options);
- }
- /**
- * @returns {string | null} absolute path which should be used for condition matching (usually the resource path)
- */
- nameForCondition() {
- return this.rootModule.nameForCondition();
- }
- /**
- * @param {ModuleGraph} moduleGraph the module graph
- * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
- */
- getSideEffectsConnectionState(moduleGraph) {
- return this.rootModule.getSideEffectsConnectionState(moduleGraph);
- }
- /**
- * @param {WebpackOptions} options webpack options
- * @param {Compilation} compilation the compilation
- * @param {ResolverWithOptions} resolver the resolver
- * @param {InputFileSystem} fs the file system
- * @param {function(WebpackError=): void} callback callback function
- * @returns {void}
- */
- build(options, compilation, resolver, fs, callback) {
- const { rootModule } = this;
- this.buildInfo = {
- strict: true,
- cacheable: true,
- moduleArgument: rootModule.buildInfo.moduleArgument,
- exportsArgument: rootModule.buildInfo.exportsArgument,
- fileDependencies: new LazySet(),
- contextDependencies: new LazySet(),
- missingDependencies: new LazySet(),
- topLevelDeclarations: new Set(),
- assets: undefined
- };
- this.buildMeta = rootModule.buildMeta;
- this.clearDependenciesAndBlocks();
- this.clearWarningsAndErrors();
- for (const m of this._modules) {
- // populate cacheable
- if (!m.buildInfo.cacheable) {
- this.buildInfo.cacheable = false;
- }
- // populate dependencies
- for (const d of m.dependencies.filter(
- dep =>
- !(dep instanceof HarmonyImportDependency) ||
- !this._modules.has(compilation.moduleGraph.getModule(dep))
- )) {
- this.dependencies.push(d);
- }
- // populate blocks
- for (const d of m.blocks) {
- this.blocks.push(d);
- }
- // populate warnings
- const warnings = m.getWarnings();
- if (warnings !== undefined) {
- for (const warning of warnings) {
- this.addWarning(warning);
- }
- }
- // populate errors
- const errors = m.getErrors();
- if (errors !== undefined) {
- for (const error of errors) {
- this.addError(error);
- }
- }
- // populate topLevelDeclarations
- if (m.buildInfo.topLevelDeclarations) {
- const topLevelDeclarations = this.buildInfo.topLevelDeclarations;
- if (topLevelDeclarations !== undefined) {
- for (const decl of m.buildInfo.topLevelDeclarations) {
- topLevelDeclarations.add(decl);
- }
- }
- } else {
- this.buildInfo.topLevelDeclarations = undefined;
- }
- // populate assets
- if (m.buildInfo.assets) {
- if (this.buildInfo.assets === undefined) {
- this.buildInfo.assets = Object.create(null);
- }
- Object.assign(this.buildInfo.assets, m.buildInfo.assets);
- }
- if (m.buildInfo.assetsInfo) {
- if (this.buildInfo.assetsInfo === undefined) {
- this.buildInfo.assetsInfo = new Map();
- }
- for (const [key, value] of m.buildInfo.assetsInfo) {
- this.buildInfo.assetsInfo.set(key, value);
- }
- }
- }
- callback();
- }
- /**
- * @param {string=} type the source type for which the size should be estimated
- * @returns {number} the estimated size of the module (must be non-zero)
- */
- size(type) {
- // Guess size from embedded modules
- let size = 0;
- for (const module of this._modules) {
- size += module.size(type);
- }
- return size;
- }
- /**
- * @private
- * @param {Module} rootModule the root of the concatenation
- * @param {Set<Module>} modulesSet a set of modules which should be concatenated
- * @param {RuntimeSpec} runtime for this runtime
- * @param {ModuleGraph} moduleGraph the module graph
- * @returns {ConcatenationEntry[]} concatenation list
- */
- _createConcatenationList(rootModule, modulesSet, runtime, moduleGraph) {
- /** @type {ConcatenationEntry[]} */
- const list = [];
- /** @type {Map<Module, RuntimeSpec | true>} */
- const existingEntries = new Map();
- /**
- * @param {Module} module a module
- * @returns {Iterable<{ connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true }>} imported modules in order
- */
- const getConcatenatedImports = module => {
- let connections = Array.from(moduleGraph.getOutgoingConnections(module));
- if (module === rootModule) {
- for (const c of moduleGraph.getOutgoingConnections(this))
- connections.push(c);
- }
- /**
- * @type {Array<{ connection: ModuleGraphConnection, sourceOrder: number, rangeStart: number }>}
- */
- const references = connections
- .filter(connection => {
- if (!(connection.dependency instanceof HarmonyImportDependency))
- return false;
- return (
- connection &&
- connection.resolvedOriginModule === module &&
- connection.module &&
- connection.isTargetActive(runtime)
- );
- })
- .map(connection => {
- const dep = /** @type {HarmonyImportDependency} */ (
- connection.dependency
- );
- return {
- connection,
- sourceOrder: dep.sourceOrder,
- rangeStart: dep.range && dep.range[0]
- };
- });
- /**
- * bySourceOrder
- * @example
- * import a from "a"; // sourceOrder=1
- * import b from "b"; // sourceOrder=2
- *
- * byRangeStart
- * @example
- * import {a, b} from "a"; // sourceOrder=1
- * a.a(); // first range
- * b.b(); // second range
- *
- * If there is no reexport, we have the same source.
- * If there is reexport, but module has side effects, this will lead to reexport module only.
- * If there is side-effects-free reexport, we can get simple deterministic result with range start comparison.
- */
- references.sort(concatComparators(bySourceOrder, byRangeStart));
- /** @type {Map<Module, { connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true }>} */
- const referencesMap = new Map();
- for (const { connection } of references) {
- const runtimeCondition = filterRuntime(runtime, r =>
- connection.isTargetActive(r)
- );
- if (runtimeCondition === false) continue;
- const module = connection.module;
- const entry = referencesMap.get(module);
- if (entry === undefined) {
- referencesMap.set(module, { connection, runtimeCondition });
- continue;
- }
- entry.runtimeCondition = mergeRuntimeConditionNonFalse(
- entry.runtimeCondition,
- runtimeCondition,
- runtime
- );
- }
- return referencesMap.values();
- };
- /**
- * @param {ModuleGraphConnection} connection graph connection
- * @param {RuntimeSpec | true} runtimeCondition runtime condition
- * @returns {void}
- */
- const enterModule = (connection, runtimeCondition) => {
- const module = connection.module;
- if (!module) return;
- const existingEntry = existingEntries.get(module);
- if (existingEntry === true) {
- return;
- }
- if (modulesSet.has(module)) {
- existingEntries.set(module, true);
- if (runtimeCondition !== true) {
- throw new Error(
- `Cannot runtime-conditional concatenate a module (${module.identifier()} in ${this.rootModule.identifier()}, ${runtimeConditionToString(
- runtimeCondition
- )}). This should not happen.`
- );
- }
- const imports = getConcatenatedImports(module);
- for (const { connection, runtimeCondition } of imports)
- enterModule(connection, runtimeCondition);
- list.push({
- type: "concatenated",
- module: connection.module,
- runtimeCondition
- });
- } else {
- if (existingEntry !== undefined) {
- const reducedRuntimeCondition = subtractRuntimeCondition(
- runtimeCondition,
- existingEntry,
- runtime
- );
- if (reducedRuntimeCondition === false) return;
- runtimeCondition = reducedRuntimeCondition;
- existingEntries.set(
- connection.module,
- mergeRuntimeConditionNonFalse(
- existingEntry,
- runtimeCondition,
- runtime
- )
- );
- } else {
- existingEntries.set(connection.module, runtimeCondition);
- }
- if (list.length > 0) {
- const lastItem = list[list.length - 1];
- if (
- lastItem.type === "external" &&
- lastItem.module === connection.module
- ) {
- lastItem.runtimeCondition = mergeRuntimeCondition(
- lastItem.runtimeCondition,
- runtimeCondition,
- runtime
- );
- return;
- }
- }
- list.push({
- type: "external",
- get module() {
- // We need to use a getter here, because the module in the dependency
- // could be replaced by some other process (i. e. also replaced with a
- // concatenated module)
- return connection.module;
- },
- runtimeCondition
- });
- }
- };
- existingEntries.set(rootModule, true);
- const imports = getConcatenatedImports(rootModule);
- for (const { connection, runtimeCondition } of imports)
- enterModule(connection, runtimeCondition);
- list.push({
- type: "concatenated",
- module: rootModule,
- runtimeCondition: true
- });
- return list;
- }
- /**
- * @param {Module} rootModule the root module of the concatenation
- * @param {Set<Module>} modules all modules in the concatenation (including the root module)
- * @param {Object=} associatedObjectForCache object for caching
- * @param {string | HashConstructor=} hashFunction hash function to use
- * @returns {string} the identifier
- */
- static _createIdentifier(
- rootModule,
- modules,
- associatedObjectForCache,
- hashFunction = "md4"
- ) {
- const cachedMakePathsRelative = makePathsRelative.bindContextCache(
- rootModule.context,
- associatedObjectForCache
- );
- let identifiers = [];
- for (const module of modules) {
- identifiers.push(cachedMakePathsRelative(module.identifier()));
- }
- identifiers.sort();
- const hash = createHash(hashFunction);
- hash.update(identifiers.join(" "));
- return rootModule.identifier() + "|" + hash.digest("hex");
- }
- /**
- * @param {LazySet<string>} fileDependencies set where file dependencies are added to
- * @param {LazySet<string>} contextDependencies set where context dependencies are added to
- * @param {LazySet<string>} missingDependencies set where missing dependencies are added to
- * @param {LazySet<string>} buildDependencies set where build dependencies are added to
- */
- addCacheDependencies(
- fileDependencies,
- contextDependencies,
- missingDependencies,
- buildDependencies
- ) {
- for (const module of this._modules) {
- module.addCacheDependencies(
- fileDependencies,
- contextDependencies,
- missingDependencies,
- buildDependencies
- );
- }
- }
- /**
- * @param {CodeGenerationContext} context context for code generation
- * @returns {CodeGenerationResult} result
- */
- codeGeneration({
- dependencyTemplates,
- runtimeTemplate,
- moduleGraph,
- chunkGraph,
- runtime: generationRuntime,
- codeGenerationResults
- }) {
- /** @type {Set<string>} */
- const runtimeRequirements = new Set();
- const runtime = intersectRuntime(generationRuntime, this._runtime);
- const requestShortener = runtimeTemplate.requestShortener;
- // Meta info for each module
- const [modulesWithInfo, moduleToInfoMap] = this._getModulesWithInfo(
- moduleGraph,
- runtime
- );
- // Set with modules that need a generated namespace object
- /** @type {Set<ConcatenatedModuleInfo>} */
- const neededNamespaceObjects = new Set();
- // Generate source code and analyse scopes
- // Prepare a ReplaceSource for the final source
- for (const info of moduleToInfoMap.values()) {
- this._analyseModule(
- moduleToInfoMap,
- info,
- dependencyTemplates,
- runtimeTemplate,
- moduleGraph,
- chunkGraph,
- runtime,
- codeGenerationResults
- );
- }
- // List of all used names to avoid conflicts
- const allUsedNames = new Set(RESERVED_NAMES);
- // Updated Top level declarations are created by renaming
- const topLevelDeclarations = new Set();
- // List of additional names in scope for module references
- /** @type {Map<string, { usedNames: Set<string>, alreadyCheckedScopes: Set<TODO> }>} */
- const usedNamesInScopeInfo = new Map();
- /**
- * @param {string} module module identifier
- * @param {string} id export id
- * @returns {{ usedNames: Set<string>, alreadyCheckedScopes: Set<TODO> }} info
- */
- const getUsedNamesInScopeInfo = (module, id) => {
- const key = `${module}-${id}`;
- let info = usedNamesInScopeInfo.get(key);
- if (info === undefined) {
- info = {
- usedNames: new Set(),
- alreadyCheckedScopes: new Set()
- };
- usedNamesInScopeInfo.set(key, info);
- }
- return info;
- };
- // Set of already checked scopes
- const ignoredScopes = new Set();
- // get all global names
- for (const info of modulesWithInfo) {
- if (info.type === "concatenated") {
- // ignore symbols from moduleScope
- if (info.moduleScope) {
- ignoredScopes.add(info.moduleScope);
- }
- // The super class expression in class scopes behaves weird
- // We get ranges of all super class expressions to make
- // renaming to work correctly
- const superClassCache = new WeakMap();
- const getSuperClassExpressions = scope => {
- const cacheEntry = superClassCache.get(scope);
- if (cacheEntry !== undefined) return cacheEntry;
- const superClassExpressions = [];
- for (const childScope of scope.childScopes) {
- if (childScope.type !== "class") continue;
- const block = childScope.block;
- if (
- (block.type === "ClassDeclaration" ||
- block.type === "ClassExpression") &&
- block.superClass
- ) {
- superClassExpressions.push({
- range: block.superClass.range,
- variables: childScope.variables
- });
- }
- }
- superClassCache.set(scope, superClassExpressions);
- return superClassExpressions;
- };
- // add global symbols
- if (info.globalScope) {
- for (const reference of info.globalScope.through) {
- const name = reference.identifier.name;
- if (ConcatenationScope.isModuleReference(name)) {
- const match = ConcatenationScope.matchModuleReference(name);
- if (!match) continue;
- const referencedInfo = modulesWithInfo[match.index];
- if (referencedInfo.type === "reference")
- throw new Error("Module reference can't point to a reference");
- const binding = getFinalBinding(
- moduleGraph,
- referencedInfo,
- match.ids,
- moduleToInfoMap,
- runtime,
- requestShortener,
- runtimeTemplate,
- neededNamespaceObjects,
- false,
- info.module.buildMeta.strictHarmonyModule,
- true
- );
- if (!binding.ids) continue;
- const { usedNames, alreadyCheckedScopes } =
- getUsedNamesInScopeInfo(
- binding.info.module.identifier(),
- "name" in binding ? binding.name : ""
- );
- for (const expr of getSuperClassExpressions(reference.from)) {
- if (
- expr.range[0] <= reference.identifier.range[0] &&
- expr.range[1] >= reference.identifier.range[1]
- ) {
- for (const variable of expr.variables) {
- usedNames.add(variable.name);
- }
- }
- }
- addScopeSymbols(
- reference.from,
- usedNames,
- alreadyCheckedScopes,
- ignoredScopes
- );
- } else {
- allUsedNames.add(name);
- }
- }
- }
- }
- }
- // generate names for symbols
- for (const info of moduleToInfoMap.values()) {
- const { usedNames: namespaceObjectUsedNames } = getUsedNamesInScopeInfo(
- info.module.identifier(),
- ""
- );
- switch (info.type) {
- case "concatenated": {
- for (const variable of info.moduleScope.variables) {
- const name = variable.name;
- const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo(
- info.module.identifier(),
- name
- );
- if (allUsedNames.has(name) || usedNames.has(name)) {
- const references = getAllReferences(variable);
- for (const ref of references) {
- addScopeSymbols(
- ref.from,
- usedNames,
- alreadyCheckedScopes,
- ignoredScopes
- );
- }
- const newName = this.findNewName(
- name,
- allUsedNames,
- usedNames,
- info.module.readableIdentifier(requestShortener)
- );
- allUsedNames.add(newName);
- info.internalNames.set(name, newName);
- topLevelDeclarations.add(newName);
- const source = info.source;
- const allIdentifiers = new Set(
- references.map(r => r.identifier).concat(variable.identifiers)
- );
- for (const identifier of allIdentifiers) {
- const r = identifier.range;
- const path = getPathInAst(info.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);
- }
- } else {
- allUsedNames.add(name);
- info.internalNames.set(name, name);
- topLevelDeclarations.add(name);
- }
- }
- let namespaceObjectName;
- if (info.namespaceExportSymbol) {
- namespaceObjectName = info.internalNames.get(
- info.namespaceExportSymbol
- );
- } else {
- namespaceObjectName = this.findNewName(
- "namespaceObject",
- allUsedNames,
- namespaceObjectUsedNames,
- info.module.readableIdentifier(requestShortener)
- );
- allUsedNames.add(namespaceObjectName);
- }
- info.namespaceObjectName = namespaceObjectName;
- topLevelDeclarations.add(namespaceObjectName);
- break;
- }
- case "external": {
- const externalName = this.findNewName(
- "",
- allUsedNames,
- namespaceObjectUsedNames,
- info.module.readableIdentifier(requestShortener)
- );
- allUsedNames.add(externalName);
- info.name = externalName;
- topLevelDeclarations.add(externalName);
- break;
- }
- }
- if (info.module.buildMeta.exportsType !== "namespace") {
- const externalNameInterop = this.findNewName(
- "namespaceObject",
- allUsedNames,
- namespaceObjectUsedNames,
- info.module.readableIdentifier(requestShortener)
- );
- allUsedNames.add(externalNameInterop);
- info.interopNamespaceObjectName = externalNameInterop;
- topLevelDeclarations.add(externalNameInterop);
- }
- if (
- info.module.buildMeta.exportsType === "default" &&
- info.module.buildMeta.defaultObject !== "redirect"
- ) {
- const externalNameInterop = this.findNewName(
- "namespaceObject2",
- allUsedNames,
- namespaceObjectUsedNames,
- info.module.readableIdentifier(requestShortener)
- );
- allUsedNames.add(externalNameInterop);
- info.interopNamespaceObject2Name = externalNameInterop;
- topLevelDeclarations.add(externalNameInterop);
- }
- if (
- info.module.buildMeta.exportsType === "dynamic" ||
- !info.module.buildMeta.exportsType
- ) {
- const externalNameInterop = this.findNewName(
- "default",
- allUsedNames,
- namespaceObjectUsedNames,
- info.module.readableIdentifier(requestShortener)
- );
- allUsedNames.add(externalNameInterop);
- info.interopDefaultAccessName = externalNameInterop;
- topLevelDeclarations.add(externalNameInterop);
- }
- }
- // Find and replace references to modules
- for (const info of moduleToInfoMap.values()) {
- if (info.type === "concatenated") {
- for (const reference of info.globalScope.through) {
- const name = reference.identifier.name;
- const match = ConcatenationScope.matchModuleReference(name);
- if (match) {
- const referencedInfo = modulesWithInfo[match.index];
- if (referencedInfo.type === "reference")
- throw new Error("Module reference can't point to a reference");
- const finalName = getFinalName(
- moduleGraph,
- referencedInfo,
- match.ids,
- moduleToInfoMap,
- runtime,
- requestShortener,
- runtimeTemplate,
- neededNamespaceObjects,
- match.call,
- !match.directImport,
- info.module.buildMeta.strictHarmonyModule,
- match.asiSafe
- );
- const r = reference.identifier.range;
- const source = info.source;
- // range is extended by 2 chars to cover the appended "._"
- source.replace(r[0], r[1] + 1, finalName);
- }
- }
- }
- }
- // Map with all root exposed used exports
- /** @type {Map<string, function(RequestShortener): string>} */
- const exportsMap = new Map();
- // Set with all root exposed unused exports
- /** @type {Set<string>} */
- const unusedExports = new Set();
- const rootInfo = /** @type {ConcatenatedModuleInfo} */ (
- moduleToInfoMap.get(this.rootModule)
- );
- const strictHarmonyModule = rootInfo.module.buildMeta.strictHarmonyModule;
- const exportsInfo = moduleGraph.getExportsInfo(rootInfo.module);
- for (const exportInfo of exportsInfo.orderedExports) {
- const name = exportInfo.name;
- if (exportInfo.provided === false) continue;
- const used = exportInfo.getUsedName(undefined, runtime);
- if (!used) {
- unusedExports.add(name);
- continue;
- }
- exportsMap.set(used, requestShortener => {
- try {
- const finalName = getFinalName(
- moduleGraph,
- rootInfo,
- [name],
- moduleToInfoMap,
- runtime,
- requestShortener,
- runtimeTemplate,
- neededNamespaceObjects,
- false,
- false,
- strictHarmonyModule,
- true
- );
- return `/* ${
- exportInfo.isReexport() ? "reexport" : "binding"
- } */ ${finalName}`;
- } catch (e) {
- e.message += `\nwhile generating the root export '${name}' (used name: '${used}')`;
- throw e;
- }
- });
- }
- const result = new ConcatSource();
- // add harmony compatibility flag (must be first because of possible circular dependencies)
- if (
- moduleGraph.getExportsInfo(this).otherExportsInfo.getUsed(runtime) !==
- UsageState.Unused
- ) {
- result.add(`// ESM COMPAT FLAG\n`);
- result.add(
- runtimeTemplate.defineEsModuleFlagStatement({
- exportsArgument: this.exportsArgument,
- runtimeRequirements
- })
- );
- }
- // define exports
- if (exportsMap.size > 0) {
- runtimeRequirements.add(RuntimeGlobals.exports);
- runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
- const definitions = [];
- for (const [key, value] of exportsMap) {
- definitions.push(
- `\n ${JSON.stringify(key)}: ${runtimeTemplate.returningFunction(
- value(requestShortener)
- )}`
- );
- }
- result.add(`\n// EXPORTS\n`);
- result.add(
- `${RuntimeGlobals.definePropertyGetters}(${
- this.exportsArgument
- }, {${definitions.join(",")}\n});\n`
- );
- }
- // list unused exports
- if (unusedExports.size > 0) {
- result.add(
- `\n// UNUSED EXPORTS: ${joinIterableWithComma(unusedExports)}\n`
- );
- }
- // generate namespace objects
- const namespaceObjectSources = new Map();
- for (const info of neededNamespaceObjects) {
- if (info.namespaceExportSymbol) continue;
- const nsObj = [];
- const exportsInfo = moduleGraph.getExportsInfo(info.module);
- for (const exportInfo of exportsInfo.orderedExports) {
- if (exportInfo.provided === false) continue;
- const usedName = exportInfo.getUsedName(undefined, runtime);
- if (usedName) {
- const finalName = getFinalName(
- moduleGraph,
- info,
- [exportInfo.name],
- moduleToInfoMap,
- runtime,
- requestShortener,
- runtimeTemplate,
- neededNamespaceObjects,
- false,
- undefined,
- info.module.buildMeta.strictHarmonyModule,
- true
- );
- nsObj.push(
- `\n ${JSON.stringify(
- usedName
- )}: ${runtimeTemplate.returningFunction(finalName)}`
- );
- }
- }
- const name = info.namespaceObjectName;
- const defineGetters =
- nsObj.length > 0
- ? `${RuntimeGlobals.definePropertyGetters}(${name}, {${nsObj.join(
- ","
- )}\n});\n`
- : "";
- if (nsObj.length > 0)
- runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
- namespaceObjectSources.set(
- info,
- `
- // NAMESPACE OBJECT: ${info.module.readableIdentifier(requestShortener)}
- var ${name} = {};
- ${RuntimeGlobals.makeNamespaceObject}(${name});
- ${defineGetters}`
- );
- runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject);
- }
- // define required namespace objects (must be before evaluation modules)
- for (const info of modulesWithInfo) {
- if (info.type === "concatenated") {
- const source = namespaceObjectSources.get(info);
- if (!source) continue;
- result.add(source);
- }
- }
- const chunkInitFragments = [];
- // evaluate modules in order
- for (const rawInfo of modulesWithInfo) {
- let name;
- let isConditional = false;
- const info = rawInfo.type === "reference" ? rawInfo.target : rawInfo;
- switch (info.type) {
- case "concatenated": {
- result.add(
- `\n;// CONCATENATED MODULE: ${info.module.readableIdentifier(
- requestShortener
- )}\n`
- );
- result.add(info.source);
- if (info.chunkInitFragments) {
- for (const f of info.chunkInitFragments) chunkInitFragments.push(f);
- }
- if (info.runtimeRequirements) {
- for (const r of info.runtimeRequirements) {
- runtimeRequirements.add(r);
- }
- }
- name = info.namespaceObjectName;
- break;
- }
- case "external": {
- result.add(
- `\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
- requestShortener
- )}\n`
- );
- runtimeRequirements.add(RuntimeGlobals.require);
- const { runtimeCondition } =
- /** @type {ExternalModuleInfo | ReferenceToModuleInfo} */ (rawInfo);
- const condition = runtimeTemplate.runtimeConditionExpression({
- chunkGraph,
- runtimeCondition,
- runtime,
- runtimeRequirements
- });
- if (condition !== "true") {
- isConditional = true;
- result.add(`if (${condition}) {\n`);
- }
- result.add(
- `var ${info.name} = __webpack_require__(${JSON.stringify(
- chunkGraph.getModuleId(info.module)
- )});`
- );
- name = info.name;
- break;
- }
- default:
- // @ts-expect-error never is expected here
- throw new Error(`Unsupported concatenation entry type ${info.type}`);
- }
- if (info.interopNamespaceObjectUsed) {
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- result.add(
- `\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name}, 2);`
- );
- }
- if (info.interopNamespaceObject2Used) {
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- result.add(
- `\nvar ${info.interopNamespaceObject2Name} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name});`
- );
- }
- if (info.interopDefaultAccessUsed) {
- runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
- result.add(
- `\nvar ${info.interopDefaultAccessName} = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${name});`
- );
- }
- if (isConditional) {
- result.add("\n}");
- }
- }
- const data = new Map();
- if (chunkInitFragments.length > 0)
- data.set("chunkInitFragments", chunkInitFragments);
- data.set("topLevelDeclarations", topLevelDeclarations);
- /** @type {CodeGenerationResult} */
- const resultEntry = {
- sources: new Map([["javascript", new CachedSource(result)]]),
- data,
- runtimeRequirements
- };
- return resultEntry;
- }
- /**
- * @param {Map<Module, ModuleInfo>} modulesMap modulesMap
- * @param {ModuleInfo} info info
- * @param {DependencyTemplates} dependencyTemplates dependencyTemplates
- * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate
- * @param {ModuleGraph} moduleGraph moduleGraph
- * @param {ChunkGraph} chunkGraph chunkGraph
- * @param {RuntimeSpec} runtime runtime
- * @param {CodeGenerationResults} codeGenerationResults codeGenerationResults
- */
- _analyseModule(
- modulesMap,
- info,
- dependencyTemplates,
- runtimeTemplate,
- moduleGraph,
- chunkGraph,
- runtime,
- codeGenerationResults
- ) {
- if (info.type === "concatenated") {
- const m = info.module;
- try {
- // Create a concatenation scope to track and capture information
- const concatenationScope = new ConcatenationScope(modulesMap, info);
- // TODO cache codeGeneration results
- const codeGenResult = m.codeGeneration({
- dependencyTemplates,
- runtimeTemplate,
- moduleGraph,
- chunkGraph,
- runtime,
- concatenationScope,
- codeGenerationResults,
- sourceTypes: TYPES
- });
- const source = codeGenResult.sources.get("javascript");
- const data = codeGenResult.data;
- const chunkInitFragments = data && data.get("chunkInitFragments");
- const code = source.source().toString();
- let ast;
- try {
- ast = JavascriptParser._parse(code, {
- sourceType: "module"
- });
- } catch (err) {
- if (
- err.loc &&
- typeof err.loc === "object" &&
- typeof err.loc.line === "number"
- ) {
- const lineNumber = err.loc.line;
- const lines = code.split("\n");
- err.message +=
- "\n| " +
- lines
- .slice(Math.max(0, lineNumber - 3), lineNumber + 2)
- .join("\n| ");
- }
- throw err;
- }
- const scopeManager = eslintScope.analyze(ast, {
- ecmaVersion: 6,
- sourceType: "module",
- optimistic: true,
- ignoreEval: true,
- impliedStrict: true
- });
- const globalScope = scopeManager.acquire(ast);
- const moduleScope = globalScope.childScopes[0];
- const resultSource = new ReplaceSource(source);
- info.runtimeRequirements = codeGenResult.runtimeRequirements;
- info.ast = ast;
- info.internalSource = source;
- info.source = resultSource;
- info.chunkInitFragments = chunkInitFragments;
- info.globalScope = globalScope;
- info.moduleScope = moduleScope;
- } catch (err) {
- err.message += `\nwhile analyzing module ${m.identifier()} for concatenation`;
- throw err;
- }
- }
- }
- /**
- * @param {ModuleGraph} moduleGraph the module graph
- * @param {RuntimeSpec} runtime the runtime
- * @returns {[ModuleInfoOrReference[], Map<Module, ModuleInfo>]} module info items
- */
- _getModulesWithInfo(moduleGraph, runtime) {
- const orderedConcatenationList = this._createConcatenationList(
- this.rootModule,
- this._modules,
- runtime,
- moduleGraph
- );
- /** @type {Map<Module, ModuleInfo>} */
- const map = new Map();
- const list = orderedConcatenationList.map((info, index) => {
- let item = map.get(info.module);
- if (item === undefined) {
- switch (info.type) {
- case "concatenated":
- item = {
- type: "concatenated",
- module: info.module,
- index,
- ast: undefined,
- internalSource: undefined,
- runtimeRequirements: undefined,
- source: undefined,
- globalScope: undefined,
- moduleScope: undefined,
- internalNames: new Map(),
- exportMap: undefined,
- rawExportMap: undefined,
- namespaceExportSymbol: undefined,
- namespaceObjectName: undefined,
- interopNamespaceObjectUsed: false,
- interopNamespaceObjectName: undefined,
- interopNamespaceObject2Used: false,
- interopNamespaceObject2Name: undefined,
- interopDefaultAccessUsed: false,
- interopDefaultAccessName: undefined
- };
- break;
- case "external":
- item = {
- type: "external",
- module: info.module,
- runtimeCondition: info.runtimeCondition,
- index,
- name: undefined,
- interopNamespaceObjectUsed: false,
- interopNamespaceObjectName: undefined,
- interopNamespaceObject2Used: false,
- interopNamespaceObject2Name: undefined,
- interopDefaultAccessUsed: false,
- interopDefaultAccessName: undefined
- };
- break;
- default:
- throw new Error(
- `Unsupported concatenation entry type ${info.type}`
- );
- }
- map.set(item.module, item);
- return item;
- } else {
- /** @type {ReferenceToModuleInfo} */
- const ref = {
- type: "reference",
- runtimeCondition: info.runtimeCondition,
- target: item
- };
- return ref;
- }
- });
- return [list, map];
- }
- findNewName(oldName, usedNamed1, usedNamed2, extraInfo) {
- let name = oldName;
- if (name === ConcatenationScope.DEFAULT_EXPORT) {
- name = "";
- }
- if (name === ConcatenationScope.NAMESPACE_OBJECT_EXPORT) {
- name = "namespaceObject";
- }
- // Remove uncool stuff
- extraInfo = extraInfo.replace(
- /\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g,
- ""
- );
- const splittedInfo = extraInfo.split("/");
- while (splittedInfo.length) {
- name = splittedInfo.pop() + (name ? "_" + name : "");
- const nameIdent = Template.toIdentifier(name);
- if (
- !usedNamed1.has(nameIdent) &&
- (!usedNamed2 || !usedNamed2.has(nameIdent))
- )
- return nameIdent;
- }
- let i = 0;
- let nameWithNumber = Template.toIdentifier(`${name}_${i}`);
- while (
- usedNamed1.has(nameWithNumber) ||
- (usedNamed2 && usedNamed2.has(nameWithNumber))
- ) {
- i++;
- nameWithNumber = Template.toIdentifier(`${name}_${i}`);
- }
- return nameWithNumber;
- }
- /**
- * @param {Hash} hash the hash used to track dependencies
- * @param {UpdateHashContext} context context
- * @returns {void}
- */
- updateHash(hash, context) {
- const { chunkGraph, runtime } = context;
- for (const info of this._createConcatenationList(
- this.rootModule,
- this._modules,
- intersectRuntime(runtime, this._runtime),
- chunkGraph.moduleGraph
- )) {
- switch (info.type) {
- case "concatenated":
- info.module.updateHash(hash, context);
- break;
- case "external":
- hash.update(`${chunkGraph.getModuleId(info.module)}`);
- // TODO runtimeCondition
- break;
- }
- }
- super.updateHash(hash, context);
- }
- static deserialize(context) {
- const obj = new ConcatenatedModule({
- identifier: undefined,
- rootModule: undefined,
- modules: undefined,
- runtime: undefined
- });
- obj.deserialize(context);
- return obj;
- }
- }
- makeSerializable(ConcatenatedModule, "webpack/lib/optimize/ConcatenatedModule");
- module.exports = ConcatenatedModule;
|