source: trip-planner-front/node_modules/webpack/lib/asset/AssetGenerator.js@ 6a3a178

Last change on this file since 6a3a178 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 9.8 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Sergey Melyukov @smelukov
4*/
5
6"use strict";
7
8const mimeTypes = require("mime-types");
9const path = require("path");
10const { RawSource } = require("webpack-sources");
11const Generator = require("../Generator");
12const RuntimeGlobals = require("../RuntimeGlobals");
13const createHash = require("../util/createHash");
14const { makePathsRelative } = require("../util/identifier");
15
16/** @typedef {import("webpack-sources").Source} Source */
17/** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorOptions} AssetGeneratorOptions */
18/** @typedef {import("../../declarations/WebpackOptions").RawPublicPath} RawPublicPath */
19/** @typedef {import("../Compilation")} Compilation */
20/** @typedef {import("../Compiler")} Compiler */
21/** @typedef {import("../Generator").GenerateContext} GenerateContext */
22/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */
23/** @typedef {import("../Module")} Module */
24/** @typedef {import("../NormalModule")} NormalModule */
25/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
26/** @typedef {import("../util/Hash")} Hash */
27
28const mergeMaybeArrays = (a, b) => {
29 const set = new Set();
30 if (Array.isArray(a)) for (const item of a) set.add(item);
31 else set.add(a);
32 if (Array.isArray(b)) for (const item of b) set.add(item);
33 else set.add(b);
34 return Array.from(set);
35};
36
37const mergeAssetInfo = (a, b) => {
38 const result = { ...a, ...b };
39 for (const key of Object.keys(a)) {
40 if (key in b) {
41 if (a[key] === b[key]) continue;
42 switch (key) {
43 case "fullhash":
44 case "chunkhash":
45 case "modulehash":
46 case "contenthash":
47 result[key] = mergeMaybeArrays(a[key], b[key]);
48 break;
49 case "immutable":
50 case "development":
51 case "hotModuleReplacement":
52 case "javascriptModule ":
53 result[key] = a[key] || b[key];
54 break;
55 case "related":
56 result[key] = mergeRelatedInfo(a[key], b[key]);
57 break;
58 default:
59 throw new Error(`Can't handle conflicting asset info for ${key}`);
60 }
61 }
62 }
63 return result;
64};
65
66const mergeRelatedInfo = (a, b) => {
67 const result = { ...a, ...b };
68 for (const key of Object.keys(a)) {
69 if (key in b) {
70 if (a[key] === b[key]) continue;
71 result[key] = mergeMaybeArrays(a[key], b[key]);
72 }
73 }
74 return result;
75};
76
77const JS_TYPES = new Set(["javascript"]);
78const JS_AND_ASSET_TYPES = new Set(["javascript", "asset"]);
79
80class AssetGenerator extends Generator {
81 /**
82 * @param {AssetGeneratorOptions["dataUrl"]=} dataUrlOptions the options for the data url
83 * @param {string=} filename override for output.assetModuleFilename
84 * @param {RawPublicPath=} publicPath override for output.assetModulePublicPath
85 * @param {boolean=} emit generate output asset
86 */
87 constructor(dataUrlOptions, filename, publicPath, emit) {
88 super();
89 this.dataUrlOptions = dataUrlOptions;
90 this.filename = filename;
91 this.publicPath = publicPath;
92 this.emit = emit;
93 }
94
95 /**
96 * @param {NormalModule} module module for which the code should be generated
97 * @param {GenerateContext} generateContext context for generate
98 * @returns {Source} generated code
99 */
100 generate(
101 module,
102 { runtime, chunkGraph, runtimeTemplate, runtimeRequirements, type, getData }
103 ) {
104 switch (type) {
105 case "asset":
106 return module.originalSource();
107 default: {
108 runtimeRequirements.add(RuntimeGlobals.module);
109
110 const originalSource = module.originalSource();
111 if (module.buildInfo.dataUrl) {
112 let encodedSource;
113 if (typeof this.dataUrlOptions === "function") {
114 encodedSource = this.dataUrlOptions.call(
115 null,
116 originalSource.source(),
117 {
118 filename: module.matchResource || module.resource,
119 module
120 }
121 );
122 } else {
123 /** @type {string | false | undefined} */
124 let encoding = this.dataUrlOptions.encoding;
125 if (encoding === undefined) {
126 if (
127 module.resourceResolveData &&
128 module.resourceResolveData.encoding !== undefined
129 ) {
130 encoding = module.resourceResolveData.encoding;
131 }
132 }
133 if (encoding === undefined) {
134 encoding = "base64";
135 }
136 let ext;
137 let mimeType = this.dataUrlOptions.mimetype;
138 if (mimeType === undefined) {
139 ext = path.extname(module.nameForCondition());
140 if (
141 module.resourceResolveData &&
142 module.resourceResolveData.mimetype !== undefined
143 ) {
144 mimeType =
145 module.resourceResolveData.mimetype +
146 module.resourceResolveData.parameters;
147 } else if (ext) {
148 mimeType = mimeTypes.lookup(ext);
149 }
150 }
151 if (typeof mimeType !== "string") {
152 throw new Error(
153 "DataUrl can't be generated automatically, " +
154 `because there is no mimetype for "${ext}" in mimetype database. ` +
155 'Either pass a mimetype via "generator.mimetype" or ' +
156 'use type: "asset/resource" to create a resource file instead of a DataUrl'
157 );
158 }
159
160 let encodedContent;
161 if (
162 module.resourceResolveData &&
163 module.resourceResolveData.encoding === encoding
164 ) {
165 encodedContent = module.resourceResolveData.encodedContent;
166 } else {
167 switch (encoding) {
168 case "base64": {
169 encodedContent = originalSource.buffer().toString("base64");
170 break;
171 }
172 case false: {
173 const content = originalSource.source();
174
175 if (typeof content !== "string") {
176 encodedContent = content.toString("utf-8");
177 }
178
179 encodedContent = encodeURIComponent(encodedContent).replace(
180 /[!'()*]/g,
181 character => "%" + character.codePointAt(0).toString(16)
182 );
183 break;
184 }
185 default:
186 throw new Error(`Unsupported encoding '${encoding}'`);
187 }
188 }
189
190 encodedSource = `data:${mimeType}${
191 encoding ? `;${encoding}` : ""
192 },${encodedContent}`;
193 }
194 return new RawSource(
195 `${RuntimeGlobals.module}.exports = ${JSON.stringify(
196 encodedSource
197 )};`
198 );
199 } else {
200 const assetModuleFilename =
201 this.filename || runtimeTemplate.outputOptions.assetModuleFilename;
202 const hash = createHash(runtimeTemplate.outputOptions.hashFunction);
203 if (runtimeTemplate.outputOptions.hashSalt) {
204 hash.update(runtimeTemplate.outputOptions.hashSalt);
205 }
206 hash.update(originalSource.buffer());
207 const fullHash = /** @type {string} */ (
208 hash.digest(runtimeTemplate.outputOptions.hashDigest)
209 );
210 const contentHash = fullHash.slice(
211 0,
212 runtimeTemplate.outputOptions.hashDigestLength
213 );
214 module.buildInfo.fullContentHash = fullHash;
215 const sourceFilename = makePathsRelative(
216 runtimeTemplate.compilation.compiler.context,
217 module.matchResource || module.resource,
218 runtimeTemplate.compilation.compiler.root
219 ).replace(/^\.\//, "");
220 let { path: filename, info: assetInfo } =
221 runtimeTemplate.compilation.getAssetPathWithInfo(
222 assetModuleFilename,
223 {
224 module,
225 runtime,
226 filename: sourceFilename,
227 chunkGraph,
228 contentHash
229 }
230 );
231 let publicPath;
232 if (this.publicPath !== undefined) {
233 const { path, info } =
234 runtimeTemplate.compilation.getAssetPathWithInfo(
235 this.publicPath,
236 {
237 module,
238 runtime,
239 filename: sourceFilename,
240 chunkGraph,
241 contentHash
242 }
243 );
244 publicPath = JSON.stringify(path);
245 assetInfo = mergeAssetInfo(assetInfo, info);
246 } else {
247 publicPath = RuntimeGlobals.publicPath;
248 runtimeRequirements.add(RuntimeGlobals.publicPath); // add __webpack_require__.p
249 }
250 assetInfo = {
251 sourceFilename,
252 ...assetInfo
253 };
254 module.buildInfo.filename = filename;
255 module.buildInfo.assetInfo = assetInfo;
256 if (getData) {
257 // Due to code generation caching module.buildInfo.XXX can't used to store such information
258 // It need to be stored in the code generation results instead, where it's cached too
259 // TODO webpack 6 For back-compat reasons we also store in on module.buildInfo
260 const data = getData();
261 data.set("fullContentHash", fullHash);
262 data.set("filename", filename);
263 data.set("assetInfo", assetInfo);
264 }
265
266 return new RawSource(
267 `${
268 RuntimeGlobals.module
269 }.exports = ${publicPath} + ${JSON.stringify(filename)};`
270 );
271 }
272 }
273 }
274 }
275
276 /**
277 * @param {NormalModule} module fresh module
278 * @returns {Set<string>} available types (do not mutate)
279 */
280 getTypes(module) {
281 if ((module.buildInfo && module.buildInfo.dataUrl) || this.emit === false) {
282 return JS_TYPES;
283 } else {
284 return JS_AND_ASSET_TYPES;
285 }
286 }
287
288 /**
289 * @param {NormalModule} module the module
290 * @param {string=} type source type
291 * @returns {number} estimate size of the module
292 */
293 getSize(module, type) {
294 switch (type) {
295 case "asset": {
296 const originalSource = module.originalSource();
297
298 if (!originalSource) {
299 return 0;
300 }
301
302 return originalSource.size();
303 }
304 default:
305 if (module.buildInfo && module.buildInfo.dataUrl) {
306 const originalSource = module.originalSource();
307
308 if (!originalSource) {
309 return 0;
310 }
311
312 // roughly for data url
313 // Example: m.exports="data:image/png;base64,ag82/f+2=="
314 // 4/3 = base64 encoding
315 // 34 = ~ data url header + footer + rounding
316 return originalSource.size() * 1.34 + 36;
317 } else {
318 // it's only estimated so this number is probably fine
319 // Example: m.exports=r.p+"0123456789012345678901.ext"
320 return 42;
321 }
322 }
323 }
324
325 /**
326 * @param {Hash} hash hash that will be modified
327 * @param {UpdateHashContext} updateHashContext context for updating hash
328 */
329 updateHash(hash, { module }) {
330 hash.update(module.buildInfo.dataUrl ? "data-url" : "resource");
331 }
332}
333
334module.exports = AssetGenerator;
Note: See TracBrowser for help on using the repository browser.