UNPKG

4.21 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Sergey Melyukov @smelukov
4*/
5
6"use strict";
7
8const { ReplaceSource, RawSource, ConcatSource } = require("webpack-sources");
9const { UsageState } = require("../ExportsInfo");
10const Generator = require("../Generator");
11const RuntimeGlobals = require("../RuntimeGlobals");
12const 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
22const TYPES = new Set(["javascript"]);
23
24class 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
139module.exports = CssExportsGenerator;