1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | "use strict";
|
7 |
|
8 | const { RawSource } = require("webpack-sources");
|
9 | const ConcatenationScope = require("../ConcatenationScope");
|
10 | const { UsageState } = require("../ExportsInfo");
|
11 | const Generator = require("../Generator");
|
12 | const RuntimeGlobals = require("../RuntimeGlobals");
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | const stringifySafe = data => {
|
22 | const stringified = JSON.stringify(data);
|
23 | if (!stringified) {
|
24 | return undefined;
|
25 | }
|
26 |
|
27 | return stringified.replace(/\u2028|\u2029/g, str =>
|
28 | str === "\u2029" ? "\\u2029" : "\\u2028"
|
29 | );
|
30 | };
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | const createObjectForExportsInfo = (data, exportsInfo, runtime) => {
|
39 | if (exportsInfo.otherExportsInfo.getUsed(runtime) !== UsageState.Unused)
|
40 | return data;
|
41 | const isArray = Array.isArray(data);
|
42 | const reducedData = isArray ? [] : {};
|
43 | for (const key of Object.keys(data)) {
|
44 | const exportInfo = exportsInfo.getReadOnlyExportInfo(key);
|
45 | const used = exportInfo.getUsed(runtime);
|
46 | if (used === UsageState.Unused) continue;
|
47 |
|
48 | let value;
|
49 | if (used === UsageState.OnlyPropertiesUsed && exportInfo.exportsInfo) {
|
50 | value = createObjectForExportsInfo(
|
51 | data[key],
|
52 | exportInfo.exportsInfo,
|
53 | runtime
|
54 | );
|
55 | } else {
|
56 | value = data[key];
|
57 | }
|
58 | const name = exportInfo.getUsedName(key, runtime);
|
59 | reducedData[name] = value;
|
60 | }
|
61 | if (isArray) {
|
62 | let arrayLengthWhenUsed =
|
63 | exportsInfo.getReadOnlyExportInfo("length").getUsed(runtime) !==
|
64 | UsageState.Unused
|
65 | ? data.length
|
66 | : undefined;
|
67 |
|
68 | let sizeObjectMinusArray = 0;
|
69 | for (let i = 0; i < reducedData.length; i++) {
|
70 | if (reducedData[i] === undefined) {
|
71 | sizeObjectMinusArray -= 2;
|
72 | } else {
|
73 | sizeObjectMinusArray += `${i}`.length + 3;
|
74 | }
|
75 | }
|
76 | if (arrayLengthWhenUsed !== undefined) {
|
77 | sizeObjectMinusArray +=
|
78 | `${arrayLengthWhenUsed}`.length +
|
79 | 8 -
|
80 | (arrayLengthWhenUsed - reducedData.length) * 2;
|
81 | }
|
82 | if (sizeObjectMinusArray < 0)
|
83 | return Object.assign(
|
84 | arrayLengthWhenUsed === undefined
|
85 | ? {}
|
86 | : { length: arrayLengthWhenUsed },
|
87 | reducedData
|
88 | );
|
89 | const generatedLength =
|
90 | arrayLengthWhenUsed !== undefined
|
91 | ? Math.max(arrayLengthWhenUsed, reducedData.length)
|
92 | : reducedData.length;
|
93 | for (let i = 0; i < generatedLength; i++) {
|
94 | if (reducedData[i] === undefined) {
|
95 | reducedData[i] = 0;
|
96 | }
|
97 | }
|
98 | }
|
99 | return reducedData;
|
100 | };
|
101 |
|
102 | const TYPES = new Set(["javascript"]);
|
103 |
|
104 | class JsonGenerator extends Generator {
|
105 | |
106 |
|
107 |
|
108 |
|
109 | getTypes(module) {
|
110 | return TYPES;
|
111 | }
|
112 |
|
113 | |
114 |
|
115 |
|
116 |
|
117 |
|
118 | getSize(module, type) {
|
119 | let data = module.buildInfo.jsonData;
|
120 | if (!data) return 0;
|
121 | return stringifySafe(data).length + 10;
|
122 | }
|
123 |
|
124 | |
125 |
|
126 |
|
127 |
|
128 |
|
129 | getConcatenationBailoutReason(module, context) {
|
130 | return undefined;
|
131 | }
|
132 |
|
133 | |
134 |
|
135 |
|
136 |
|
137 |
|
138 | generate(
|
139 | module,
|
140 | {
|
141 | moduleGraph,
|
142 | runtimeTemplate,
|
143 | runtimeRequirements,
|
144 | runtime,
|
145 | concatenationScope
|
146 | }
|
147 | ) {
|
148 | const data = module.buildInfo.jsonData;
|
149 | if (data === undefined) {
|
150 | return new RawSource(
|
151 | runtimeTemplate.missingModuleStatement({
|
152 | request: module.rawRequest
|
153 | })
|
154 | );
|
155 | }
|
156 | const exportsInfo = moduleGraph.getExportsInfo(module);
|
157 | let finalJson =
|
158 | typeof data === "object" &&
|
159 | data &&
|
160 | exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused
|
161 | ? createObjectForExportsInfo(data, exportsInfo, runtime)
|
162 | : data;
|
163 |
|
164 | const jsonStr = stringifySafe(finalJson);
|
165 | const jsonExpr =
|
166 | jsonStr.length > 20 && typeof finalJson === "object"
|
167 | ? `JSON.parse('${jsonStr.replace(/[\\']/g, "\\$&")}')`
|
168 | : jsonStr;
|
169 | let content;
|
170 | if (concatenationScope) {
|
171 | content = `${runtimeTemplate.supportsConst() ? "const" : "var"} ${
|
172 | ConcatenationScope.NAMESPACE_OBJECT_EXPORT
|
173 | } = ${jsonExpr};`;
|
174 | concatenationScope.registerNamespaceExport(
|
175 | ConcatenationScope.NAMESPACE_OBJECT_EXPORT
|
176 | );
|
177 | } else {
|
178 | runtimeRequirements.add(RuntimeGlobals.module);
|
179 | content = `${module.moduleArgument}.exports = ${jsonExpr};`;
|
180 | }
|
181 | return new RawSource(content);
|
182 | }
|
183 | }
|
184 |
|
185 | module.exports = JsonGenerator;
|