| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const { ConcatSource } = require("webpack-sources");
- const { UsageState } = require("../ExportsInfo");
- const ExternalModule = require("../ExternalModule");
- const { JAVASCRIPT_TYPE } = require("../ModuleSourceTypeConstants");
- const RuntimeGlobals = require("../RuntimeGlobals");
- const Template = require("../Template");
- const HarmonyExportExpressionDependency = require("../dependencies/HarmonyExportExpressionDependency");
- const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
- const HarmonyExportSpecifierDependency = require("../dependencies/HarmonyExportSpecifierDependency");
- const JavascriptModulesPlugin = require("../javascript/JavascriptModulesPlugin");
- const ConcatenatedModule = require("../optimize/ConcatenatedModule");
- const { InlinedUsedName } = require("../optimize/InlineExports");
- const {
- RESERVED_IDENTIFIER,
- SAFE_IDENTIFIER,
- propertyAccess
- } = require("../util/property");
- const { getEntryRuntime, getRuntimeKey } = require("../util/runtime");
- const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
- /** @import { Source } from "webpack-sources" */
- /**
- * @import {
- * LibraryOptions,
- * LibraryType,
- * LibraryExport
- * } from "../../declarations/WebpackOptions"
- */
- /** @import Chunk from "../Chunk" */
- /** @import Compilation from "../Compilation" */
- /** @import Compiler from "../Compiler" */
- /** @import ModuleGraph from "../ModuleGraph" */
- /** @import Module, { BuildMeta } from "../Module" */
- /**
- * @import {
- * StartupRenderContext,
- * ModuleRenderContext
- * } from "../javascript/JavascriptModulesPlugin"
- */
- /** @import { RuntimeSpec } from "../util/runtime" */
- /**
- * @import {
- * JavascriptModuleBuildMeta
- * } from "../javascript/JavascriptModule"
- */
- /**
- * Defines the shared type used by this module.
- * @template T
- * @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T>
- */
- /**
- * Defines the module library plugin options type used by this module.
- * @typedef {object} ModuleLibraryPluginOptions
- * @property {LibraryType} type
- */
- /**
- * Defines the module library plugin parsed type used by this module.
- * @typedef {object} ModuleLibraryPluginParsed
- * @property {string} name
- * @property {LibraryExport=} export
- */
- const PLUGIN_NAME = "ModuleLibraryPlugin";
- /**
- * The entry modules this plugin renders `export { … }` for, per compilation — the
- * only ones whose export definitions may be taken over.
- * @type {WeakMap<Compilation, WeakSet<Module>>}
- */
- const libraryEntryModules = new WeakMap();
- /**
- * Whether every export the module defines is a binding the library can export
- * natively, so the definitions written into the exports object are read by nobody.
- * A re-export or a renamed import is not: `renderStartup` reads those back off the
- * object, and `treatAsCommonJs` hands the object out as the default export.
- * @param {Module} module the entry module
- * @param {ModuleGraph} moduleGraph the module graph
- * @returns {boolean} true when the definitions may be taken over
- */
- const definesOnlyNativeExports = (module, moduleGraph) => {
- const buildMeta = /** @type {JavascriptModuleBuildMeta} */ (module.buildMeta);
- if (buildMeta && buildMeta.treatAsCommonJs) return false;
- // A top-level `await` wraps the body in `__webpack_require__.a`, and the
- // definitions read declarations inside that wrapper — re-emitting them after the
- // module would put them out of scope.
- if (moduleGraph.isAsync(module)) return false;
- const topLevelDeclarations =
- module.buildInfo && module.buildInfo.topLevelDeclarations;
- if (!topLevelDeclarations) return false;
- for (const dep of module.dependencies) {
- // A re-export or an `export default` has no declaration of its own to bind to,
- // so `renderStartup` reads its value back off the exports object.
- if (
- dep instanceof HarmonyExportImportedSpecifierDependency ||
- dep instanceof HarmonyExportExpressionDependency
- ) {
- return false;
- }
- if (!(dep instanceof HarmonyExportSpecifierDependency)) continue;
- if (!topLevelDeclarations.has(dep.id)) return false;
- }
- return true;
- };
- /**
- * An export name is either an identifier name (reserved words included, e.g.
- * `default`) or a string literal (arbitrary module namespace names).
- * @param {string} name export name
- * @returns {string} name as it can be written after `as`
- */
- const toExportName = (name) =>
- SAFE_IDENTIFIER.test(name) ? name : JSON.stringify(name);
- /**
- * Whether the export name can also be used as the declared binding name.
- * @param {string} name export name
- * @returns {boolean} true, when the name can be declared
- */
- const isDeclarableExportName = (name) =>
- SAFE_IDENTIFIER.test(name) && !RESERVED_IDENTIFIER.has(name);
- /**
- * Represents the module library plugin runtime component.
- * @typedef {ModuleLibraryPluginParsed} T
- * @extends {AbstractLibraryPlugin<ModuleLibraryPluginParsed>}
- */
- class ModuleLibraryPlugin extends AbstractLibraryPlugin {
- /**
- * Creates an instance of ModuleLibraryPlugin.
- * @param {ModuleLibraryPluginOptions} options the plugin options
- */
- constructor(options) {
- super({
- pluginName: "ModuleLibraryPlugin",
- type: options.type
- });
- }
- /**
- * Applies the plugin by registering its hooks on the compiler.
- * @param {Compiler} compiler the compiler instance
- * @returns {void}
- */
- apply(compiler) {
- super.apply(compiler);
- compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
- const { onDemandExportsGeneration } =
- ConcatenatedModule.getCompilationHooks(compilation);
- const javascriptHooks =
- JavascriptModulesPlugin.getCompilationHooks(compilation);
- onDemandExportsGeneration.tap(
- PLUGIN_NAME,
- (module, runtimes, source, finalName) => {
- /** @type {BuildMeta} */
- const buildMeta = module.buildMeta || (module.buildMeta = {});
- /** @type {BuildMeta["exportsSourceByRuntime"]} */
- const exportsSourceByRuntime =
- buildMeta.exportsSourceByRuntime ||
- (buildMeta.exportsSourceByRuntime = new Map());
- /** @type {BuildMeta["exportsFinalNameByRuntime"]} */
- const exportsFinalNameByRuntime =
- buildMeta.exportsFinalNameByRuntime ||
- (buildMeta.exportsFinalNameByRuntime = new Map());
- for (const runtime of runtimes) {
- const key = getRuntimeKey(runtime);
- exportsSourceByRuntime.set(key, source);
- exportsFinalNameByRuntime.set(key, finalName);
- }
- return true;
- }
- );
- // The same for a plain entry, whose definitions come from a dependency template.
- // Placed after the module body, which its value bindings read.
- javascriptHooks.onDemandExportsGeneration.tap(
- PLUGIN_NAME,
- (module, runtime, source, placeAtEnd) => {
- const entries = libraryEntryModules.get(compilation);
- if (!entries || !entries.has(module)) return;
- if (!definesOnlyNativeExports(module, compilation.moduleGraph)) {
- return;
- }
- /** @type {BuildMeta} */
- const buildMeta = module.buildMeta || (module.buildMeta = {});
- const key = getRuntimeKey(runtime);
- if (placeAtEnd) {
- const bindings =
- buildMeta.exportsBindingSourceByRuntime ||
- (buildMeta.exportsBindingSourceByRuntime = new Map());
- bindings.set(key, source);
- } else {
- const sources =
- buildMeta.exportsSourceByRuntime ||
- (buildMeta.exportsSourceByRuntime = new Map());
- // The `__esModule` marker and the definitions both land here, so
- // keep whichever arrived first rather than replacing it.
- const before = sources.get(key);
- sources.set(key, before ? `${before}${source}` : source);
- }
- return true;
- }
- );
- // `ModuleLibraryPlugin` stashes the on-demand exports source via
- // `onDemandExportsGeneration` and only re-emits it when the
- // module is wrapped in an IIFE/factory. When the entry is
- // inlined directly, the stashed source — and the
- // `definePropertyGetters` / `requireScope` runtime helpers it
- // pulled in — never make it into the output. Drop those helpers
- // from the chunk's set so the bundle stays clean.
- compilation.hooks.additionalChunkRuntimeRequirements.tap(
- PLUGIN_NAME,
- (chunk, set, { chunkGraph, codeGenerationResults }) => {
- if (!set.has(RuntimeGlobals.definePropertyGetters)) return;
- if (chunkGraph.getNumberOfEntryModules(chunk) !== 1) return;
- if (
- set.has(RuntimeGlobals.moduleFactories) ||
- set.has(RuntimeGlobals.moduleCache) ||
- set.has(RuntimeGlobals.interceptModuleExecution) ||
- set.has(RuntimeGlobals.module) ||
- set.has(RuntimeGlobals.thisAsExports)
- ) {
- return;
- }
- if (javascriptHooks.inlineInRuntimeBailout.isUsed()) return;
- const [module] = chunkGraph.getChunkEntryModulesIterable(chunk);
- const runtimeKey = getRuntimeKey(chunk.runtime);
- const buildMeta = module.buildMeta;
- const takenOver =
- (buildMeta &&
- buildMeta.exportsSourceByRuntime &&
- buildMeta.exportsSourceByRuntime.has(runtimeKey)) ||
- (buildMeta &&
- buildMeta.exportsBindingSourceByRuntime &&
- buildMeta.exportsBindingSourceByRuntime.has(runtimeKey));
- if (!takenOver) return;
- const codeGenResult = codeGenerationResults.get(
- module,
- chunk.runtime
- );
- const jsSource =
- codeGenResult && codeGenResult.sources.get("javascript");
- if (
- jsSource &&
- String(jsSource.source()).includes(`${RuntimeGlobals.require}.`)
- ) {
- return;
- }
- // Without `avoidEntryIife`, another rendered module wraps the entry in
- // an IIFE, which re-emits the stashed source — its helpers stay.
- if (!compilation.options.optimization.avoidEntryIife) {
- for (const m of chunkGraph.getChunkModulesIterableBySourceType(
- chunk,
- JAVASCRIPT_TYPE
- ) || []) {
- if (m !== module) return;
- }
- }
- // The helpers land in the runtime, not in this chunk, so what still
- // needs them is asked of every chunk sharing the entrypoint — the
- // runtime chunk, and whatever `splitChunks` moved out of the entry.
- /** @type {Set<Chunk>} */
- const siblings = new Set([chunk]);
- for (const [
- ,
- entrypoint
- ] of chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)) {
- if (!entrypoint) continue;
- for (const sibling of entrypoint.chunks) siblings.add(sibling);
- }
- let otherNeedsDefine = false;
- let otherNeedsNamespaceObject = false;
- let otherNeedsExports = false;
- let otherNeedsRequireScope = false;
- outer: for (const sibling of siblings) {
- for (const m of chunkGraph.getChunkModulesIterable(sibling)) {
- if (m === module) continue;
- const requirements = chunkGraph.getModuleRuntimeRequirements(
- m,
- sibling.runtime
- );
- if (!requirements) continue;
- if (requirements.has(RuntimeGlobals.definePropertyGetters)) {
- otherNeedsDefine = true;
- }
- if (requirements.has(RuntimeGlobals.makeNamespaceObject)) {
- otherNeedsNamespaceObject = true;
- }
- if (requirements.has(RuntimeGlobals.exports)) {
- otherNeedsExports = true;
- }
- if (requirements.has(RuntimeGlobals.requireScope)) {
- otherNeedsRequireScope = true;
- }
- if (otherNeedsDefine) break outer;
- }
- }
- if (otherNeedsDefine) return;
- set.delete(RuntimeGlobals.definePropertyGetters);
- if (!otherNeedsNamespaceObject) {
- set.delete(RuntimeGlobals.makeNamespaceObject);
- }
- if (!otherNeedsExports) set.delete(RuntimeGlobals.exports);
- if (!otherNeedsRequireScope) set.delete(RuntimeGlobals.requireScope);
- }
- );
- });
- }
- /**
- * Finish entry module.
- * @param {Module} module the exporting entry module
- * @param {string} entryName the name of the entrypoint
- * @param {LibraryContext<T>} libraryContext context
- * @returns {void}
- */
- finishEntryModule(
- module,
- entryName,
- { options, compilation, compilation: { moduleGraph } }
- ) {
- const runtime = getEntryRuntime(compilation, entryName);
- if (options.export) {
- const exportsInfo = moduleGraph.getExportInfo(
- module,
- Array.isArray(options.export) ? options.export[0] : options.export
- );
- exportsInfo.setUsed(UsageState.Used, runtime);
- exportsInfo.canMangleUse = false;
- exportsInfo.canInlineUse = false;
- } else {
- const exportsInfo = moduleGraph.getExportsInfo(module);
- if (
- // If the entry module is commonjs, its exports cannot be mangled
- (module.buildMeta &&
- /** @type {JavascriptModuleBuildMeta} */ (module.buildMeta)
- .treatAsCommonJs) ||
- // The entry module provides unknown exports
- exportsInfo._otherExportsInfo.provided === null
- ) {
- exportsInfo.setUsedInUnknownWay(runtime);
- } else {
- exportsInfo.setAllKnownExportsUsed(runtime);
- for (const exportInfo of exportsInfo.ownedExports) {
- exportInfo.canInlineUse = false;
- }
- }
- }
- moduleGraph.addExtraReason(module, "used as library export");
- let entries = libraryEntryModules.get(compilation);
- if (entries === undefined) {
- entries = new WeakSet();
- libraryEntryModules.set(compilation, entries);
- }
- entries.add(module);
- }
- /**
- * Returns preprocess as needed by overriding.
- * @param {LibraryOptions} library normalized library option
- * @returns {T} preprocess as needed by overriding
- */
- parseOptions(library) {
- const { name } = library;
- if (name) {
- throw new Error(
- `Library name must be unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
- );
- }
- const _name = /** @type {string} */ (name);
- return {
- name: _name,
- export: library.export
- };
- }
- /**
- * Analyze unknown provided exports.
- * @param {Source} source source
- * @param {Module} module module
- * @param {ModuleGraph} moduleGraph moduleGraph
- * @param {RuntimeSpec} runtime chunk runtime
- * @param {[string, string][]} exports exports
- * @param {Set<string>} alreadyRenderedExports already rendered exports
- * @returns {ConcatSource} source with null provided exports
- */
- _analyzeUnknownProvidedExports(
- source,
- module,
- moduleGraph,
- runtime,
- exports,
- alreadyRenderedExports
- ) {
- const result = new ConcatSource(source);
- /** @type {Set<string>} */
- const moduleRequests = new Set();
- /** @type {Map<string, string | InlinedUsedName>} */
- const unknownProvidedExports = new Map();
- /**
- * Resolves dynamic star reexport.
- * @param {Module} module the module
- * @param {boolean} isDynamicReexport if module is dynamic reexported
- */
- const resolveDynamicStarReexport = (module, isDynamicReexport) => {
- for (const connection of moduleGraph.getOutgoingConnections(module)) {
- const dep = connection.dependency;
- // Only handle star-reexport statement
- if (
- dep instanceof HarmonyExportImportedSpecifierDependency &&
- dep.name === null
- ) {
- const importedModule = connection.resolvedModule;
- const importedModuleExportsInfo =
- moduleGraph.getExportsInfo(importedModule);
- // The imported module provides unknown exports
- // So keep the reexports rendered in the bundle
- if (
- dep.getMode(moduleGraph, runtime).type === "dynamic-reexport" &&
- importedModuleExportsInfo._otherExportsInfo.provided === null
- ) {
- // Handle export * from 'external'
- if (importedModule instanceof ExternalModule) {
- moduleRequests.add(importedModule.userRequest);
- } else {
- resolveDynamicStarReexport(importedModule, true);
- }
- }
- // If importer modules existing `dynamic-reexport` dependency
- // We should keep export statement rendered in the bundle
- else if (isDynamicReexport) {
- for (const exportInfo of importedModuleExportsInfo.orderedExports) {
- if (!exportInfo.provided || exportInfo.name === "default") {
- continue;
- }
- const originalName = exportInfo.name;
- const usedName =
- /** @type {string | InlinedUsedName | false} */
- (exportInfo.getUsedName(originalName, runtime));
- if (!alreadyRenderedExports.has(originalName) && usedName) {
- unknownProvidedExports.set(originalName, usedName);
- }
- }
- }
- }
- }
- };
- resolveDynamicStarReexport(module, false);
- for (const request of moduleRequests) {
- result.add(`export * from "${request}";\n`);
- }
- for (const [origin, used] of unknownProvidedExports) {
- exports.push([
- origin,
- used instanceof InlinedUsedName
- ? used.render(
- Template.toNormalComment(
- `inlined export ${propertyAccess([origin])}`
- )
- )
- : `${RuntimeGlobals.exports}${propertyAccess([used])}`
- ]);
- }
- return result;
- }
- /**
- * Renders source with library export.
- * @param {Source} source source
- * @param {Module} module module
- * @param {StartupRenderContext} renderContext render context
- * @param {LibraryContext<T>} libraryContext context
- * @returns {Source} source with library export
- */
- renderStartup(source, module, renderContext, { options, compilation }) {
- const {
- moduleGraph,
- chunk,
- codeGenerationResults,
- inlined,
- inlinedInIIFE,
- runtimeTemplate
- } = renderContext;
- let result = new ConcatSource(source);
- const exportInfos = options.export
- ? [
- moduleGraph.getExportInfo(
- module,
- Array.isArray(options.export) ? options.export[0] : options.export
- )
- ]
- : moduleGraph.getExportsInfo(module).orderedExports;
- const exportsFinalNameByRuntime =
- (module.buildMeta &&
- module.buildMeta.exportsFinalNameByRuntime &&
- module.buildMeta.exportsFinalNameByRuntime.get(
- getRuntimeKey(chunk.runtime)
- )) ||
- {};
- const isInlinedEntryWithoutIIFE = inlined && !inlinedInIIFE;
- // Direct export bindings from on-demand concatenation
- const definitions = isInlinedEntryWithoutIIFE
- ? exportsFinalNameByRuntime
- : {};
- /** @type {string[]} */
- const shortHandedExports = [];
- /** @type {[string, string][]} */
- const exports = [];
- /** @type {Set<string>} */
- const alreadyRenderedExports = new Set();
- /** @type {Set<string>} */
- const usedLocalNames = new Set();
- /**
- * `toIdentifier` is lossy, so distinct export names (`"a b"` and `"a-b"`)
- * would otherwise be bound to the same generated name twice.
- * @param {string} exportName export name
- * @returns {string} unique local name for the export
- */
- const toLocalName = (exportName) => {
- const base = `${RuntimeGlobals.exports}${Template.toIdentifier(exportName)}`;
- let name = base;
- let i = 0;
- while (usedLocalNames.has(name)) name = `${base}_${i++}`;
- usedLocalNames.add(name);
- return name;
- };
- const isAsync = moduleGraph.isAsync(module);
- const treatAsCommonJs =
- module.buildMeta &&
- /** @type {JavascriptModuleBuildMeta} */ (module.buildMeta)
- .treatAsCommonJs;
- const skipRenderDefaultExport = Boolean(treatAsCommonJs);
- // A single (non-concatenated) inlined entry is rendered at the top
- // level, so its own declarations are top-level bindings we can export
- // directly — keeping ESM live bindings instead of snapshotting
- // `__webpack_exports__.x` into a `const`. Concatenated entries already
- // get direct bindings via `definitions` above.
- /** @type {Map<string, string> | undefined} */
- let directBindings;
- if (isInlinedEntryWithoutIIFE && !treatAsCommonJs) {
- const { data } = codeGenerationResults.get(module, chunk.runtime);
- const topLevelDeclarations =
- (data && data.get("topLevelDeclarations")) ||
- (module.buildInfo && module.buildInfo.topLevelDeclarations);
- if (topLevelDeclarations) {
- for (const dep of module.dependencies) {
- if (
- dep instanceof HarmonyExportSpecifierDependency &&
- topLevelDeclarations.has(dep.id)
- ) {
- (directBindings || (directBindings = new Map())).set(
- dep.name,
- dep.id
- );
- }
- }
- }
- }
- // Taken over by `onDemandExportsGeneration` above, and re-emitted by
- // `renderModuleContent` only where the module is wrapped — which is not here.
- const bindingsTakenOver = Boolean(
- module.buildMeta &&
- module.buildMeta.exportsBindingSourceByRuntime &&
- module.buildMeta.exportsBindingSourceByRuntime.has(
- getRuntimeKey(chunk.runtime)
- )
- );
- const moduleExportsInfo = moduleGraph.getExportsInfo(module);
- // Define ESM compatibility flag will rely on `__webpack_exports__`
- const needHarmonyCompatibilityFlag =
- moduleExportsInfo.otherExportsInfo.getUsed(chunk.runtime) !==
- UsageState.Unused ||
- moduleExportsInfo
- .getReadOnlyExportInfo("__esModule")
- .getUsed(chunk.runtime) !== UsageState.Unused;
- let needExportsDeclaration =
- !isInlinedEntryWithoutIIFE || isAsync || needHarmonyCompatibilityFlag;
- if (isAsync) {
- result.add(
- `${RuntimeGlobals.exports} = await ${RuntimeGlobals.exports};\n`
- );
- }
- // Try to find all known exports of the entry module
- outer: for (const exportInfo of exportInfos) {
- if (!exportInfo.provided) continue;
- const originalName = exportInfo.name;
- // Skip rendering the default export in some cases
- if (skipRenderDefaultExport && originalName === "default") continue;
- // Try to find all exports from the reexported modules
- const target = exportInfo.findTarget(moduleGraph, (_m) => true);
- // A namespace object target (`export * as ns from "./module"`) has no
- // export name, so there is nothing that could be missing
- if (target && target.export) {
- const targetExport = target.export[0];
- const reexportsInfo = moduleGraph.getExportsInfo(target.module);
- for (const reexportInfo of reexportsInfo.orderedExports) {
- if (
- reexportInfo.provided === false &&
- reexportInfo.name !== "default" &&
- reexportInfo.name === targetExport
- ) {
- continue outer;
- }
- }
- }
- // The exports of entry module are never inlined
- const usedName =
- /** @type {string} */
- (exportInfo.getUsedName(originalName, chunk.runtime));
- /** @type {string | undefined} */
- const definition = definitions[usedName];
- /** @type {string | undefined} */
- const directLocal =
- definition === undefined && directBindings
- ? directBindings.get(originalName)
- : undefined;
- /** @type {string | undefined} */
- let finalName;
- if (definition) {
- finalName = definition;
- } else if (directLocal !== undefined) {
- // Live binding to the inlined entry's own top-level declaration
- finalName = directLocal;
- // The declaration is only there for the definitions written into it; with
- // those taken over (and not re-emitted here) nothing reads the object.
- if (!bindingsTakenOver) needExportsDeclaration = true;
- } else {
- // Fallback to `__webpack_exports__` property access
- // when no direct export binding was found
- finalName = toLocalName(originalName);
- needExportsDeclaration = true;
- result.add(
- `${runtimeTemplate.renderConst()} ${finalName} = ${RuntimeGlobals.exports}${propertyAccess(
- [usedName]
- )};\n`
- );
- }
- if (
- // If the name includes `property access` and `call expressions`
- finalName &&
- (finalName.includes(".") ||
- finalName.includes("[") ||
- finalName.includes("("))
- ) {
- if (exportInfo.isReexport()) {
- const { data } = codeGenerationResults.get(module, chunk.runtime);
- const topLevelDeclarations =
- (data && data.get("topLevelDeclarations")) ||
- (module.buildInfo && module.buildInfo.topLevelDeclarations);
- if (topLevelDeclarations && topLevelDeclarations.has(originalName)) {
- const name = toLocalName(originalName);
- result.add(
- `${runtimeTemplate.renderConst()} ${name} = ${finalName};\n`
- );
- shortHandedExports.push(`${name} as ${toExportName(originalName)}`);
- } else {
- exports.push([originalName, finalName]);
- }
- } else {
- exports.push([originalName, finalName]);
- }
- } else {
- shortHandedExports.push(
- finalName === originalName
- ? finalName
- : `${finalName} as ${toExportName(originalName)}`
- );
- }
- alreadyRenderedExports.add(originalName);
- }
- if (shortHandedExports.length > 0) {
- result.add(`export { ${shortHandedExports.join(", ")} };\n`);
- }
- // Add default export `__webpack_exports__` statement to keep better compatibility
- if (treatAsCommonJs) {
- needExportsDeclaration = true;
- result.add(`export default ${RuntimeGlobals.exports};\n`);
- }
- result = this._analyzeUnknownProvidedExports(
- result,
- module,
- moduleGraph,
- chunk.runtime,
- exports,
- alreadyRenderedExports
- );
- for (const [exportName, final] of exports) {
- if (isDeclarableExportName(exportName)) {
- result.add(
- `export ${runtimeTemplate.renderConst()} ${exportName} = ${final};\n`
- );
- continue;
- }
- // Bind to a generated name, the export name can't be declared
- const name = toLocalName(exportName);
- result.add(
- `${runtimeTemplate.renderConst()} ${name} = ${final};\nexport { ${name} as ${toExportName(exportName)} };\n`
- );
- }
- if (!needExportsDeclaration) {
- renderContext.needExportsDeclaration = false;
- }
- return result;
- }
- /**
- * Renders module content.
- * @param {Source} source source
- * @param {Module} module module
- * @param {ModuleRenderContext} renderContext render context
- * @param {Omit<LibraryContext<T>, "options">} libraryContext context
- * @returns {Source} source with library export
- */
- renderModuleContent(
- source,
- module,
- { factory, inlinedInIIFE, chunk },
- libraryContext
- ) {
- const runtimeKey = getRuntimeKey(chunk.runtime);
- const buildMeta = module.buildMeta;
- const exportsSource =
- buildMeta &&
- buildMeta.exportsSourceByRuntime &&
- buildMeta.exportsSourceByRuntime.get(runtimeKey);
- const bindingSource =
- buildMeta &&
- buildMeta.exportsBindingSourceByRuntime &&
- buildMeta.exportsBindingSourceByRuntime.get(runtimeKey);
- // Re-add the exports source in a factory or IIFE-wrapped startup module; value
- // bindings read the declarations above them, so those go after the body.
- if ((inlinedInIIFE || factory) && (exportsSource || bindingSource)) {
- return new ConcatSource(
- ...(exportsSource ? [exportsSource] : []),
- source,
- ...(bindingSource ? ["\n", bindingSource] : [])
- );
- }
- return source;
- }
- }
- module.exports = ModuleLibraryPlugin;
|