source: frontend/node_modules/webpack/lib/json/JsonGenerator.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const { RawSource } = require("webpack-sources");
9const ConcatenationScope = require("../ConcatenationScope");
10const { UsageState } = require("../ExportsInfo");
11const Generator = require("../Generator");
12const { JAVASCRIPT_TYPES } = require("../ModuleSourceTypeConstants");
13const RuntimeGlobals = require("../RuntimeGlobals");
14
15/** @typedef {import("webpack-sources").Source} Source */
16/** @typedef {import("../../declarations/WebpackOptions").JsonGeneratorOptions} JsonGeneratorOptions */
17/** @typedef {import("../ExportsInfo")} ExportsInfo */
18/** @typedef {import("../Generator").GenerateContext} GenerateContext */
19/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */
20/** @typedef {import("../util/Hash")} Hash */
21/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
22/** @typedef {import("../Module").SourceType} SourceType */
23/** @typedef {import("../Module").SourceTypes} SourceTypes */
24/** @typedef {import("../NormalModule")} NormalModule */
25/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
26/** @typedef {import("../util/fs").JsonArray} JsonArray */
27/** @typedef {import("../util/fs").JsonObject} JsonObject */
28/** @typedef {import("../util/fs").JsonValue} JsonValue */
29
30/**
31 * Returns stringified data.
32 * @param {JsonValue} data Raw JSON data
33 * @returns {undefined | string} stringified data
34 */
35const stringifySafe = (data) => {
36 const stringified = JSON.stringify(data);
37 if (!stringified) {
38 return; // Invalid JSON
39 }
40
41 return stringified.replace(/\u2028|\u2029/g, (str) =>
42 str === "\u2029" ? "\\u2029" : "\\u2028"
43 ); // invalid in JavaScript but valid JSON
44};
45
46/**
47 * Creates an object for exports info.
48 * @param {JsonObject | JsonArray} data Raw JSON data (always an object or array)
49 * @param {ExportsInfo} exportsInfo exports info
50 * @param {RuntimeSpec} runtime the runtime
51 * @returns {JsonObject | JsonArray} reduced data
52 */
53const createObjectForExportsInfo = (data, exportsInfo, runtime) => {
54 if (exportsInfo.otherExportsInfo.getUsed(runtime) !== UsageState.Unused) {
55 return data;
56 }
57 const isArray = Array.isArray(data);
58 /** @type {JsonObject | JsonArray} */
59 const reducedData = isArray ? [] : {};
60 for (const key of Object.keys(data)) {
61 const exportInfo = exportsInfo.getReadOnlyExportInfo(key);
62 const used = exportInfo.getUsed(runtime);
63 if (used === UsageState.Unused) continue;
64
65 // The real type is `JsonObject | JsonArray`, but typescript doesn't work `Object.keys(['string', 'other-string', 'etc'])` properly
66 const newData = /** @type {JsonObject} */ (data)[key];
67 const value =
68 used === UsageState.OnlyPropertiesUsed &&
69 exportInfo.exportsInfo &&
70 typeof newData === "object" &&
71 newData
72 ? createObjectForExportsInfo(newData, exportInfo.exportsInfo, runtime)
73 : newData;
74
75 const name = /** @type {string} */ (exportInfo.getUsedName(key, runtime));
76 /** @type {JsonObject} */
77 (reducedData)[name] = value;
78 }
79 if (isArray) {
80 const arrayLengthWhenUsed =
81 exportsInfo.getReadOnlyExportInfo("length").getUsed(runtime) !==
82 UsageState.Unused
83 ? data.length
84 : undefined;
85
86 let sizeObjectMinusArray = 0;
87 const reducedDataLength =
88 /** @type {JsonArray} */
89 (reducedData).length;
90 for (let i = 0; i < reducedDataLength; i++) {
91 if (/** @type {JsonArray} */ (reducedData)[i] === undefined) {
92 sizeObjectMinusArray -= 2;
93 } else {
94 sizeObjectMinusArray += `${i}`.length + 3;
95 }
96 }
97 if (arrayLengthWhenUsed !== undefined) {
98 sizeObjectMinusArray +=
99 `${arrayLengthWhenUsed}`.length +
100 8 -
101 (arrayLengthWhenUsed - reducedDataLength) * 2;
102 }
103 if (sizeObjectMinusArray < 0) {
104 return Object.assign(
105 arrayLengthWhenUsed === undefined
106 ? {}
107 : { length: arrayLengthWhenUsed },
108 reducedData
109 );
110 }
111 /** @type {number} */
112 const generatedLength =
113 arrayLengthWhenUsed !== undefined
114 ? Math.max(arrayLengthWhenUsed, reducedDataLength)
115 : reducedDataLength;
116 for (let i = 0; i < generatedLength; i++) {
117 if (/** @type {JsonArray} */ (reducedData)[i] === undefined) {
118 /** @type {JsonArray} */
119 (reducedData)[i] = 0;
120 }
121 }
122 }
123 return reducedData;
124};
125
126class JsonGenerator extends Generator {
127 /**
128 * Creates an instance of JsonGenerator.
129 * @param {JsonGeneratorOptions} options options
130 */
131 constructor(options) {
132 super();
133 /** @type {JsonGeneratorOptions} */
134 this.options = options;
135 }
136
137 /**
138 * Returns the source types available for this module.
139 * @param {NormalModule} module fresh module
140 * @returns {SourceTypes} available types (do not mutate)
141 */
142 getTypes(module) {
143 return JAVASCRIPT_TYPES;
144 }
145
146 /**
147 * Returns the estimated size for the requested source type.
148 * @param {NormalModule} module the module
149 * @param {SourceType=} type source type
150 * @returns {number} estimate size of the module
151 */
152 getSize(module, type) {
153 /** @type {JsonValue | undefined} */
154 const data =
155 module.buildInfo &&
156 module.buildInfo.jsonData &&
157 module.buildInfo.jsonData.get();
158 if (!data) return 0;
159 return /** @type {string} */ (stringifySafe(data)).length + 10;
160 }
161
162 /**
163 * Returns the reason this module cannot be concatenated, when one exists.
164 * @param {NormalModule} module module for which the bailout reason should be determined
165 * @param {ConcatenationBailoutReasonContext} context context
166 * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
167 */
168 getConcatenationBailoutReason(module, context) {
169 return undefined;
170 }
171
172 /**
173 * Generates generated code for this runtime module.
174 * @param {NormalModule} module module for which the code should be generated
175 * @param {GenerateContext} generateContext context for generate
176 * @returns {Source | null} generated code
177 */
178 generate(
179 module,
180 {
181 moduleGraph,
182 runtimeTemplate,
183 runtimeRequirements,
184 runtime,
185 concatenationScope
186 }
187 ) {
188 /** @type {JsonValue | undefined} */
189 const data =
190 module.buildInfo &&
191 module.buildInfo.jsonData &&
192 module.buildInfo.jsonData.get();
193 if (data === undefined) {
194 return new RawSource(
195 runtimeTemplate.missingModuleStatement({
196 request: module.rawRequest
197 })
198 );
199 }
200 const exportsInfo = moduleGraph.getExportsInfo(module);
201 /** @type {JsonValue} */
202 const finalJson =
203 typeof data === "object" &&
204 data &&
205 exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused
206 ? createObjectForExportsInfo(data, exportsInfo, runtime)
207 : data;
208 // Use JSON because JSON.parse() is much faster than JavaScript evaluation
209 const jsonStr = /** @type {string} */ (stringifySafe(finalJson));
210 const jsonExpr =
211 this.options.JSONParse &&
212 jsonStr.length > 20 &&
213 typeof finalJson === "object"
214 ? `/*#__PURE__*/JSON.parse('${jsonStr.replace(/[\\']/g, "\\$&")}')`
215 : jsonStr.replace(/"__proto__":/g, '["__proto__"]:');
216 /** @type {string} */
217 let content;
218 if (concatenationScope) {
219 content = `${runtimeTemplate.renderConst()} ${
220 ConcatenationScope.NAMESPACE_OBJECT_EXPORT
221 } = ${jsonExpr};`;
222 concatenationScope.registerNamespaceExport(
223 ConcatenationScope.NAMESPACE_OBJECT_EXPORT
224 );
225 } else {
226 runtimeRequirements.add(RuntimeGlobals.module);
227 content = `${module.moduleArgument}.exports = ${jsonExpr};`;
228 }
229 return new RawSource(content);
230 }
231
232 /**
233 * Generates fallback output for the provided error condition.
234 * @param {Error} error the error
235 * @param {NormalModule} module module for which the code should be generated
236 * @param {GenerateContext} generateContext context for generate
237 * @returns {Source | null} generated code
238 */
239 generateError(error, module, generateContext) {
240 return new RawSource(`throw new Error(${JSON.stringify(error.message)});`);
241 }
242
243 /**
244 * Updates the hash with the data contributed by this instance.
245 * @param {Hash} hash hash that will be modified
246 * @param {UpdateHashContext} updateHashContext context for updating hash
247 */
248 updateHash(hash, updateHashContext) {
249 if (this.options.JSONParse) {
250 hash.update("json-parse");
251 }
252 }
253}
254
255module.exports = JsonGenerator;
Note: See TracBrowser for help on using the repository browser.