| | |
| | | const ConcatenationScope = require("../ConcatenationScope"); |
| | | const { UsageState } = require("../ExportsInfo"); |
| | | const Module = require("../Module"); |
| | | const { JS_TYPES } = require("../ModuleSourceTypesConstants"); |
| | | const { |
| | | JAVASCRIPT_TYPE, |
| | | JAVASCRIPT_TYPES |
| | | } = require("../ModuleSourceTypeConstants"); |
| | | const { JAVASCRIPT_MODULE_TYPE_ESM } = require("../ModuleTypeConstants"); |
| | | const RuntimeGlobals = require("../RuntimeGlobals"); |
| | | const Template = require("../Template"); |
| | |
| | | const createHash = require("../util/createHash"); |
| | | const { makePathsRelative } = require("../util/identifier"); |
| | | const makeSerializable = require("../util/makeSerializable"); |
| | | const propertyAccess = require("../util/propertyAccess"); |
| | | const { propertyName } = require("../util/propertyName"); |
| | | const { propertyAccess, propertyName } = require("../util/property"); |
| | | const { |
| | | filterRuntime, |
| | | intersectRuntime, |
| | |
| | | /** @typedef {import("../Module").FileSystemDependencies} FileSystemDependencies */ |
| | | /** @typedef {import("../Module").BuildMeta} BuildMeta */ |
| | | /** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */ |
| | | /** @typedef {import("../Module").CodeGenerationResultData} CodeGenerationResultData */ |
| | | /** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */ |
| | | /** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */ |
| | | /** @typedef {import("../Module").LibIdent} LibIdent */ |
| | |
| | | /** @typedef {import("../javascript/JavascriptParser").Range} Range */ |
| | | /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */ |
| | | /** @typedef {import("../util/Hash")} Hash */ |
| | | /** @typedef {typeof import("../util/Hash")} HashConstructor */ |
| | | /** @typedef {import("../util/Hash").HashFunction} HashFunction */ |
| | | /** @typedef {import("../util/concatenate").UsedNames} UsedNames */ |
| | | /** @typedef {import("../util/concatenate").ScopeInfo} ScopeInfo */ |
| | | /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */ |
| | | /** @typedef {import("../util/identifier").AssociatedObjectForCache} AssociatedObjectForCache */ |
| | |
| | | * @property {ExportName} exportName |
| | | */ |
| | | |
| | | /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo } ModuleInfo */ |
| | | /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo | ReferenceToModuleInfo } ModuleInfoOrReference */ |
| | | /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo} ModuleInfo */ |
| | | /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo | ReferenceToModuleInfo} ModuleInfoOrReference */ |
| | | |
| | | /** @typedef {Map<string, string>} ExportMap */ |
| | | |
| | | /** |
| | | * @typedef {object} ConcatenatedModuleInfo |
| | |
| | | * @property {Scope | undefined} globalScope |
| | | * @property {Scope | undefined} moduleScope |
| | | * @property {Map<string, string>} internalNames |
| | | * @property {Map<string, string> | undefined} exportMap |
| | | * @property {Map<string, string> | undefined} rawExportMap |
| | | * @property {ExportMap | undefined} exportMap |
| | | * @property {ExportMap | undefined} rawExportMap |
| | | * @property {string=} namespaceExportSymbol |
| | | * @property {string | undefined} namespaceObjectName |
| | | * @property {ConcatenationScope | undefined} concatenationScope |
| | |
| | | /** |
| | | * @template T |
| | | * @param {string} property property |
| | | * @param {function(T[keyof T], T[keyof T]): 0 | 1 | -1} comparator comparator |
| | | * @param {(a: T[keyof T], b: T[keyof T]) => 0 | 1 | -1} comparator comparator |
| | | * @returns {Comparator<T>} comparator |
| | | */ |
| | | |
| | |
| | | } |
| | | return 0; |
| | | }; |
| | | |
| | | const bySourceOrder = createComparator("sourceOrder", compareNumbers); |
| | | const byRangeStart = createComparator("rangeStart", compareNumbers); |
| | | |
| | |
| | | ); |
| | | { |
| | | const { ids, comment } = binding; |
| | | /** @type {string} */ |
| | | let reference; |
| | | /** @type {boolean} */ |
| | | let isPropertyAccess; |
| | | if ("rawName" in binding) { |
| | | reference = `${binding.rawName}${comment || ""}${propertyAccess(ids)}`; |
| | |
| | | |
| | | /** |
| | | * @typedef {object} ConcatenateModuleHooks |
| | | * @property {SyncBailHook<[ConcatenatedModule], boolean>} onDemandExportsGeneration |
| | | * @property {SyncBailHook<[ConcatenatedModule, RuntimeSpec[], string, Record<string, string>], boolean>} onDemandExportsGeneration |
| | | * @property {SyncBailHook<[Partial<ConcatenatedModuleInfo>, ConcatenatedModuleInfo], boolean | void>} concatenatedModuleInfo |
| | | */ |
| | | |
| | |
| | | * @param {RuntimeSpec} runtime the runtime |
| | | * @param {Compilation} compilation the compilation |
| | | * @param {AssociatedObjectForCache=} associatedObjectForCache object for caching |
| | | * @param {string | HashConstructor=} hashFunction hash function to use |
| | | * @param {HashFunction=} hashFunction hash function to use |
| | | * @returns {ConcatenatedModule} the module |
| | | */ |
| | | static create( |
| | |
| | | let hooks = compilationHooksMap.get(compilation); |
| | | if (hooks === undefined) { |
| | | hooks = { |
| | | onDemandExportsGeneration: new SyncBailHook(["module"]), |
| | | onDemandExportsGeneration: new SyncBailHook([ |
| | | "module", |
| | | "runtimes", |
| | | "exportsFinalName", |
| | | "exportsSource" |
| | | ]), |
| | | concatenatedModuleInfo: new SyncBailHook([ |
| | | "updatedInfo", |
| | | "concatenatedModuleInfo" |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns the source types this module can generate. |
| | | * @returns {SourceTypes} types available (do not mutate) |
| | | */ |
| | | getSourceTypes() { |
| | | return JS_TYPES; |
| | | return JAVASCRIPT_TYPES; |
| | | } |
| | | |
| | | get modules() { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns the unique identifier used to reference this module. |
| | | * @returns {string} a unique identifier of the module |
| | | */ |
| | | identifier() { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns a human-readable identifier for this module. |
| | | * @param {RequestShortener} requestShortener the request shortener |
| | | * @returns {string} a user readable identifier of the module |
| | | */ |
| | |
| | | } |
| | | |
| | | /** |
| | | * Gets the library identifier. |
| | | * @param {LibIdentOptions} options options |
| | | * @returns {LibIdent | null} an identifier for library inclusion |
| | | */ |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns the path used when matching this module against rule conditions. |
| | | * @returns {NameForCondition | null} absolute path which should be used for condition matching (usually the resource path) |
| | | */ |
| | | nameForCondition() { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Gets side effects connection state. |
| | | * @param {ModuleGraph} moduleGraph the module graph |
| | | * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only |
| | | */ |
| | |
| | | } |
| | | |
| | | /** |
| | | * Builds the module using the provided compilation context. |
| | | * @param {WebpackOptions} options webpack options |
| | | * @param {Compilation} compilation the compilation |
| | | * @param {ResolverWithOptions} resolver the resolver |
| | |
| | | const { moduleArgument, exportsArgument } = |
| | | /** @type {BuildInfo} */ |
| | | (rootModule.buildInfo); |
| | | /** @type {BuildInfo} */ |
| | | this.buildInfo = { |
| | | strict: true, |
| | | cacheable: true, |
| | |
| | | for (const m of this._modules) { |
| | | // populate cacheable |
| | | if (!(/** @type {BuildInfo} */ (m.buildInfo).cacheable)) { |
| | | /** @type {BuildInfo} */ |
| | | (this.buildInfo).cacheable = false; |
| | | this.buildInfo.cacheable = false; |
| | | } |
| | | |
| | | // populate dependencies |
| | |
| | | const { assets, assetsInfo, topLevelDeclarations, needCreateRequire } = |
| | | /** @type {BuildInfo} */ (m.buildInfo); |
| | | |
| | | const buildInfo = /** @type {BuildInfo} */ (this.buildInfo); |
| | | const buildInfo = this.buildInfo; |
| | | |
| | | // populate topLevelDeclarations |
| | | if (topLevelDeclarations) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns the estimated size for the requested source type. |
| | | * @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) |
| | | */ |
| | |
| | | const references = connections |
| | | .filter((connection) => { |
| | | if (!(connection.dependency instanceof HarmonyImportDependency)) { |
| | | return false; |
| | | } |
| | | if ( |
| | | !Module.getSourceBasicTypes(connection.module).has(JAVASCRIPT_TYPE) |
| | | ) { |
| | | return false; |
| | | } |
| | | return ( |
| | |
| | | * @param {Module} rootModule the root module of the concatenation |
| | | * @param {Set<Module>} modules all modules in the concatenation (including the root module) |
| | | * @param {AssociatedObjectForCache=} associatedObjectForCache object for caching |
| | | * @param {string | HashConstructor=} hashFunction hash function to use |
| | | * @param {HashFunction=} hashFunction hash function to use |
| | | * @returns {string} the identifier |
| | | */ |
| | | static _createIdentifier( |
| | |
| | | /** @type {string} */ (rootModule.context), |
| | | associatedObjectForCache |
| | | ); |
| | | /** @type {string[]} */ |
| | | const identifiers = []; |
| | | for (const module of modules) { |
| | | identifiers.push(cachedMakePathsRelative(module.identifier())); |
| | |
| | | } |
| | | |
| | | /** |
| | | * Adds the provided file dependencies to the module. |
| | | * @param {FileSystemDependencies} fileDependencies set where file dependencies are added to |
| | | * @param {FileSystemDependencies} contextDependencies set where context dependencies are added to |
| | | * @param {FileSystemDependencies} missingDependencies set where missing dependencies are added to |
| | |
| | | } |
| | | |
| | | /** |
| | | * Generates code and runtime requirements for this module. |
| | | * @param {CodeGenerationContext} context context for code generation |
| | | * @returns {CodeGenerationResult} result |
| | | */ |
| | |
| | | moduleGraph, |
| | | chunkGraph, |
| | | runtime: generationRuntime, |
| | | runtimes, |
| | | codeGenerationResults |
| | | }) { |
| | | const { concatenatedModuleInfo } = ConcatenatedModule.getCompilationHooks( |
| | |
| | | moduleGraph, |
| | | chunkGraph, |
| | | runtime, |
| | | runtimes, |
| | | /** @type {CodeGenerationResults} */ |
| | | (codeGenerationResults), |
| | | allUsedNames |
| | |
| | | const usedNamesInScopeInfo = new Map(); |
| | | |
| | | // Set of already checked scopes |
| | | /** @type {Set<Scope>} */ |
| | | const ignoredScopes = new Set(); |
| | | |
| | | // get all global names |
| | |
| | | // The super class expression in class scopes behaves weird |
| | | // We get ranges of all super class expressions to make |
| | | // renaming to work correctly |
| | | /** @typedef {{ range: Range, variables: Variable[] }} ClassInfo */ |
| | | /** @type {WeakMap<Scope, ClassInfo[]>} */ |
| | | const superClassCache = new WeakMap(); |
| | | /** |
| | | * @param {Scope} scope scope |
| | | * @returns {{ range: Range, variables: Variable[] }[]} result |
| | | * @returns {ClassInfo[]} result |
| | | */ |
| | | const getSuperClassExpressions = (scope) => { |
| | | const cacheEntry = superClassCache.get(scope); |
| | | if (cacheEntry !== undefined) return cacheEntry; |
| | | /** @type {ClassInfo[]} */ |
| | | const superClassExpressions = []; |
| | | for (const childScope of scope.childScopes) { |
| | | if (childScope.type !== "class") continue; |
| | |
| | | * @param {string} name the name to find a new name for |
| | | * @param {ConcatenatedModuleInfo} info the info of the module |
| | | * @param {Reference[]} references the references to the name |
| | | * @returns {string|undefined} the new name or undefined if the name is not found |
| | | * @returns {string | undefined} the new name or undefined if the name is not found |
| | | */ |
| | | const _findNewName = (name, info, references) => { |
| | | const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo( |
| | |
| | | * @param {string} name the name to find a new name for |
| | | * @param {ConcatenatedModuleInfo} info the info of the module |
| | | * @param {Reference[]} references the references to the name |
| | | * @returns {string|undefined} the new name or undefined if the name is not found |
| | | * @returns {string | undefined} the new name or undefined if the name is not found |
| | | */ |
| | | const _findNewNameForSpecifier = (name, info, references) => { |
| | | const { usedNames: moduleUsedNames, alreadyCheckedScopes } = |
| | |
| | | info.module.identifier(), |
| | | name |
| | | ); |
| | | /** @type {UsedNames} */ |
| | | const referencesUsedNames = new Set(); |
| | | for (const ref of references) { |
| | | addScopeSymbols( |
| | |
| | | topLevelDeclarations.add(name); |
| | | } |
| | | } |
| | | /** @type {string} */ |
| | | let namespaceObjectName; |
| | | if (info.namespaceExportSymbol) { |
| | | namespaceObjectName = info.internalNames.get( |
| | | info.namespaceExportSymbol |
| | | ); |
| | | namespaceObjectName = |
| | | /** @type {string} */ |
| | | (info.internalNames.get(info.namespaceExportSymbol)); |
| | | } else { |
| | | namespaceObjectName = findNewName( |
| | | "namespaceObject", |
| | |
| | | ); |
| | | allUsedNames.add(namespaceObjectName); |
| | | } |
| | | info.namespaceObjectName = |
| | | /** @type {string} */ |
| | | (namespaceObjectName); |
| | | topLevelDeclarations.add( |
| | | /** @type {string} */ |
| | | (namespaceObjectName) |
| | | ); |
| | | info.namespaceObjectName = namespaceObjectName; |
| | | topLevelDeclarations.add(namespaceObjectName); |
| | | break; |
| | | } |
| | | case "external": { |
| | |
| | | if (info.type === "concatenated") { |
| | | const globalScope = /** @type {Scope} */ (info.globalScope); |
| | | // group references by name |
| | | /** @type {Map<string, Reference[]>} */ |
| | | const referencesByName = new Map(); |
| | | for (const reference of globalScope.through) { |
| | | const name = reference.identifier.name; |
| | | if (!referencesByName.has(name)) { |
| | | referencesByName.set(name, []); |
| | | } |
| | | referencesByName.get(name).push(reference); |
| | | /** @type {Reference[]} */ |
| | | (referencesByName.get(name)).push(reference); |
| | | } |
| | | for (const [name, references] of referencesByName) { |
| | | const match = ConcatenationScope.matchModuleReference(name); |
| | |
| | | |
| | | // define exports |
| | | if (exportsMap.size > 0) { |
| | | /** @type {string[]} */ |
| | | const definitions = []; |
| | | for (const [key, value] of exportsMap) { |
| | | definitions.push( |
| | |
| | | )}` |
| | | ); |
| | | } |
| | | |
| | | const { onDemandExportsGeneration } = |
| | | ConcatenatedModule.getCompilationHooks(this.compilation); |
| | | |
| | | runtimeRequirements.add(RuntimeGlobals.exports); |
| | | runtimeRequirements.add(RuntimeGlobals.definePropertyGetters); |
| | |
| | | ); |
| | | } |
| | | |
| | | if (onDemandExportsGeneration.call(this)) { |
| | | /** @type {BuildMeta} */ (this.buildMeta).factoryExportsBinding = |
| | | "\n// EXPORTS\n" + |
| | | `${RuntimeGlobals.definePropertyGetters}(${ |
| | | this.exportsArgument |
| | | }, {${definitions.join(",")}\n});\n`; |
| | | /** @type {BuildMeta} */ (this.buildMeta).exportsFinalName = |
| | | exportsFinalName; |
| | | } else { |
| | | result.add("\n// EXPORTS\n"); |
| | | result.add( |
| | | `${RuntimeGlobals.definePropertyGetters}(${ |
| | | this.exportsArgument |
| | | }, {${definitions.join(",")}\n});\n` |
| | | ); |
| | | const exportsSource = |
| | | "\n// EXPORTS\n" + |
| | | `${RuntimeGlobals.definePropertyGetters}(${this.exportsArgument}, {${definitions.join( |
| | | "," |
| | | )}\n});\n`; |
| | | |
| | | const { onDemandExportsGeneration } = |
| | | ConcatenatedModule.getCompilationHooks(this.compilation); |
| | | |
| | | if ( |
| | | !onDemandExportsGeneration.call( |
| | | this, |
| | | runtimes, |
| | | exportsSource, |
| | | exportsFinalName |
| | | ) |
| | | ) { |
| | | result.add(exportsSource); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // generate namespace objects |
| | | /** @type {Map<ConcatenatedModuleInfo, string>} */ |
| | | const namespaceObjectSources = new Map(); |
| | | for (const info of neededNamespaceObjects) { |
| | | if (info.namespaceExportSymbol) continue; |
| | | /** @type {string[]} */ |
| | | const nsObj = []; |
| | | const exportsInfo = moduleGraph.getExportsInfo(info.module); |
| | | for (const exportInfo of exportsInfo.orderedExports) { |
| | |
| | | |
| | | // evaluate modules in order |
| | | for (const rawInfo of modulesWithInfo) { |
| | | /** @type {undefined | string} */ |
| | | let name; |
| | | let isConditional = false; |
| | | const info = rawInfo.type === "reference" ? rawInfo.target : rawInfo; |
| | |
| | | } |
| | | } |
| | | |
| | | /** @type {CodeGenerationResultData} */ |
| | | const data = new Map(); |
| | | if (chunkInitFragments.length > 0) { |
| | | data.set("chunkInitFragments", chunkInitFragments); |
| | |
| | | |
| | | /** @type {CodeGenerationResult} */ |
| | | const resultEntry = { |
| | | sources: new Map([["javascript", new CachedSource(result)]]), |
| | | sources: new Map([[JAVASCRIPT_TYPE, new CachedSource(result)]]), |
| | | data, |
| | | runtimeRequirements |
| | | }; |
| | |
| | | * @param {ModuleGraph} moduleGraph moduleGraph |
| | | * @param {ChunkGraph} chunkGraph chunkGraph |
| | | * @param {RuntimeSpec} runtime runtime |
| | | * @param {RuntimeSpec[]} runtimes runtimes |
| | | * @param {CodeGenerationResults} codeGenerationResults codeGenerationResults |
| | | * @param {Set<string>} usedNames used names |
| | | * @param {UsedNames} usedNames used names |
| | | */ |
| | | _analyseModule( |
| | | modulesMap, |
| | |
| | | moduleGraph, |
| | | chunkGraph, |
| | | runtime, |
| | | runtimes, |
| | | codeGenerationResults, |
| | | usedNames |
| | | ) { |
| | |
| | | moduleGraph, |
| | | chunkGraph, |
| | | runtime, |
| | | runtimes, |
| | | concatenationScope, |
| | | codeGenerationResults, |
| | | sourceTypes: JS_TYPES |
| | | sourceTypes: JAVASCRIPT_TYPES |
| | | }); |
| | | const source = |
| | | /** @type {Source} */ |
| | | (codeGenResult.sources.get("javascript")); |
| | | (codeGenResult.sources.get(JAVASCRIPT_TYPE)); |
| | | const data = codeGenResult.data; |
| | | const chunkInitFragments = data && data.get("chunkInitFragments"); |
| | | const code = source.source().toString(); |
| | |
| | | } |
| | | |
| | | /** |
| | | * Updates the hash with the data contributed by this instance. |
| | | * @param {Hash} hash the hash used to track dependencies |
| | | * @param {UpdateHashContext} context context |
| | | * @returns {void} |