CssExportsGenerator.js (4214B)
1 /* 2 MIT License http://www.opensource.org/licenses/mit-license.php 3 Author Sergey Melyukov @smelukov 4 */ 5 6 "use strict"; 7 8 const { ReplaceSource, RawSource, ConcatSource } = require("webpack-sources"); 9 const { UsageState } = require("../ExportsInfo"); 10 const Generator = require("../Generator"); 11 const RuntimeGlobals = require("../RuntimeGlobals"); 12 const Template = require("../Template"); 13 14 /** @typedef {import("webpack-sources").Source} Source */ 15 /** @typedef {import("../Dependency")} Dependency */ 16 /** @typedef {import("../Generator").GenerateContext} GenerateContext */ 17 /** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */ 18 /** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */ 19 /** @typedef {import("../NormalModule")} NormalModule */ 20 /** @typedef {import("../util/Hash")} Hash */ 21 22 const TYPES = new Set(["javascript"]); 23 24 class CssExportsGenerator extends Generator { 25 constructor() { 26 super(); 27 } 28 29 // TODO add getConcatenationBailoutReason to allow concatenation 30 // but how to make it have a module id 31 32 /** 33 * @param {NormalModule} module module for which the code should be generated 34 * @param {GenerateContext} generateContext context for generate 35 * @returns {Source} generated code 36 */ 37 generate(module, generateContext) { 38 const source = new ReplaceSource(new RawSource("")); 39 const initFragments = []; 40 const cssExports = new Map(); 41 42 generateContext.runtimeRequirements.add(RuntimeGlobals.module); 43 44 const runtimeRequirements = new Set(); 45 46 const templateContext = { 47 runtimeTemplate: generateContext.runtimeTemplate, 48 dependencyTemplates: generateContext.dependencyTemplates, 49 moduleGraph: generateContext.moduleGraph, 50 chunkGraph: generateContext.chunkGraph, 51 module, 52 runtime: generateContext.runtime, 53 runtimeRequirements: runtimeRequirements, 54 concatenationScope: generateContext.concatenationScope, 55 codeGenerationResults: generateContext.codeGenerationResults, 56 initFragments, 57 cssExports 58 }; 59 60 const handleDependency = dependency => { 61 const constructor = /** @type {new (...args: any[]) => Dependency} */ ( 62 dependency.constructor 63 ); 64 const template = generateContext.dependencyTemplates.get(constructor); 65 if (!template) { 66 throw new Error( 67 "No template for dependency: " + dependency.constructor.name 68 ); 69 } 70 71 template.apply(dependency, source, templateContext); 72 }; 73 module.dependencies.forEach(handleDependency); 74 75 if (generateContext.concatenationScope) { 76 const source = new ConcatSource(); 77 const usedIdentifiers = new Set(); 78 for (const [k, v] of cssExports) { 79 let identifier = Template.toIdentifier(k); 80 let i = 0; 81 while (usedIdentifiers.has(identifier)) { 82 identifier = Template.toIdentifier(k + i); 83 } 84 usedIdentifiers.add(identifier); 85 generateContext.concatenationScope.registerExport(k, identifier); 86 source.add( 87 `${ 88 generateContext.runtimeTemplate.supportsConst ? "const" : "var" 89 } ${identifier} = ${JSON.stringify(v)};\n` 90 ); 91 } 92 return source; 93 } else { 94 const otherUsed = 95 generateContext.moduleGraph 96 .getExportsInfo(module) 97 .otherExportsInfo.getUsed(generateContext.runtime) !== 98 UsageState.Unused; 99 if (otherUsed) { 100 generateContext.runtimeRequirements.add( 101 RuntimeGlobals.makeNamespaceObject 102 ); 103 } 104 return new RawSource( 105 `${otherUsed ? `${RuntimeGlobals.makeNamespaceObject}(` : ""}${ 106 module.moduleArgument 107 }.exports = {\n${Array.from( 108 cssExports, 109 ([k, v]) => `\t${JSON.stringify(k)}: ${JSON.stringify(v)}` 110 ).join(",\n")}\n}${otherUsed ? ")" : ""};` 111 ); 112 } 113 } 114 115 /** 116 * @param {NormalModule} module fresh module 117 * @returns {Set<string>} available types (do not mutate) 118 */ 119 getTypes(module) { 120 return TYPES; 121 } 122 123 /** 124 * @param {NormalModule} module the module 125 * @param {string=} type source type 126 * @returns {number} estimate size of the module 127 */ 128 getSize(module, type) { 129 return 42; 130 } 131 132 /** 133 * @param {Hash} hash hash that will be modified 134 * @param {UpdateHashContext} updateHashContext context for updating hash 135 */ 136 updateHash(hash, { module }) {} 137 } 138 139 module.exports = CssExportsGenerator;