summaryrefslogtreecommitdiff
path: root/node_modules/webpack/lib/json/JsonGenerator.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/webpack/lib/json/JsonGenerator.js')
-rw-r--r--node_modules/webpack/lib/json/JsonGenerator.js205
1 files changed, 205 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/json/JsonGenerator.js b/node_modules/webpack/lib/json/JsonGenerator.js
new file mode 100644
index 00000000..d7074fc0
--- /dev/null
+++ b/node_modules/webpack/lib/json/JsonGenerator.js
@@ -0,0 +1,205 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const { RawSource } = require("webpack-sources");
+const ConcatenationScope = require("../ConcatenationScope");
+const { UsageState } = require("../ExportsInfo");
+const Generator = require("../Generator");
+const RuntimeGlobals = require("../RuntimeGlobals");
+
+/** @typedef {import("webpack-sources").Source} Source */
+/** @typedef {import("../ExportsInfo")} ExportsInfo */
+/** @typedef {import("../Generator").GenerateContext} GenerateContext */
+/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
+/** @typedef {import("../NormalModule")} NormalModule */
+/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
+/** @typedef {import("./JsonData")} JsonData */
+/** @typedef {import("./JsonModulesPlugin").RawJsonData} RawJsonData */
+
+/**
+ * @param {RawJsonData} data Raw JSON data
+ * @returns {undefined|string} stringified data
+ */
+const stringifySafe = data => {
+ const stringified = JSON.stringify(data);
+ if (!stringified) {
+ return undefined; // Invalid JSON
+ }
+
+ return stringified.replace(/\u2028|\u2029/g, str =>
+ str === "\u2029" ? "\\u2029" : "\\u2028"
+ ); // invalid in JavaScript but valid JSON
+};
+
+/**
+ * @param {RawJsonData} data Raw JSON data (always an object or array)
+ * @param {ExportsInfo} exportsInfo exports info
+ * @param {RuntimeSpec} runtime the runtime
+ * @returns {RawJsonData} reduced data
+ */
+const createObjectForExportsInfo = (data, exportsInfo, runtime) => {
+ if (exportsInfo.otherExportsInfo.getUsed(runtime) !== UsageState.Unused)
+ return data;
+ const isArray = Array.isArray(data);
+ /** @type {RawJsonData} */
+ const reducedData = isArray ? [] : {};
+ for (const key of Object.keys(data)) {
+ const exportInfo = exportsInfo.getReadOnlyExportInfo(key);
+ const used = exportInfo.getUsed(runtime);
+ if (used === UsageState.Unused) continue;
+
+ /** @type {RawJsonData} */
+ let value;
+ if (used === UsageState.OnlyPropertiesUsed && exportInfo.exportsInfo) {
+ value = createObjectForExportsInfo(
+ data[key],
+ exportInfo.exportsInfo,
+ runtime
+ );
+ } else {
+ value = data[key];
+ }
+
+ const name = /** @type {string} */ (exportInfo.getUsedName(key, runtime));
+ /** @type {Record<string, RawJsonData>} */ (reducedData)[name] = value;
+ }
+ if (isArray) {
+ let arrayLengthWhenUsed =
+ exportsInfo.getReadOnlyExportInfo("length").getUsed(runtime) !==
+ UsageState.Unused
+ ? data.length
+ : undefined;
+
+ let sizeObjectMinusArray = 0;
+ for (let i = 0; i < reducedData.length; i++) {
+ if (reducedData[i] === undefined) {
+ sizeObjectMinusArray -= 2;
+ } else {
+ sizeObjectMinusArray += `${i}`.length + 3;
+ }
+ }
+ if (arrayLengthWhenUsed !== undefined) {
+ sizeObjectMinusArray +=
+ `${arrayLengthWhenUsed}`.length +
+ 8 -
+ (arrayLengthWhenUsed - reducedData.length) * 2;
+ }
+ if (sizeObjectMinusArray < 0)
+ return Object.assign(
+ arrayLengthWhenUsed === undefined
+ ? {}
+ : { length: arrayLengthWhenUsed },
+ reducedData
+ );
+ /** @type {number} */
+ const generatedLength =
+ arrayLengthWhenUsed !== undefined
+ ? Math.max(arrayLengthWhenUsed, reducedData.length)
+ : reducedData.length;
+ for (let i = 0; i < generatedLength; i++) {
+ if (reducedData[i] === undefined) {
+ reducedData[i] = 0;
+ }
+ }
+ }
+ return reducedData;
+};
+
+const TYPES = new Set(["javascript"]);
+
+class JsonGenerator extends Generator {
+ /**
+ * @param {NormalModule} module fresh module
+ * @returns {Set<string>} available types (do not mutate)
+ */
+ getTypes(module) {
+ return TYPES;
+ }
+
+ /**
+ * @param {NormalModule} module the module
+ * @param {string=} type source type
+ * @returns {number} estimate size of the module
+ */
+ getSize(module, type) {
+ /** @type {RawJsonData | undefined} */
+ const data =
+ module.buildInfo &&
+ module.buildInfo.jsonData &&
+ module.buildInfo.jsonData.get();
+ if (!data) return 0;
+ return /** @type {string} */ (stringifySafe(data)).length + 10;
+ }
+
+ /**
+ * @param {NormalModule} module module for which the bailout reason should be determined
+ * @param {ConcatenationBailoutReasonContext} context context
+ * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
+ */
+ getConcatenationBailoutReason(module, context) {
+ return undefined;
+ }
+
+ /**
+ * @param {NormalModule} module module for which the code should be generated
+ * @param {GenerateContext} generateContext context for generate
+ * @returns {Source} generated code
+ */
+ generate(
+ module,
+ {
+ moduleGraph,
+ runtimeTemplate,
+ runtimeRequirements,
+ runtime,
+ concatenationScope
+ }
+ ) {
+ /** @type {RawJsonData | undefined} */
+ const data =
+ module.buildInfo &&
+ module.buildInfo.jsonData &&
+ module.buildInfo.jsonData.get();
+ if (data === undefined) {
+ return new RawSource(
+ runtimeTemplate.missingModuleStatement({
+ request: module.rawRequest
+ })
+ );
+ }
+ const exportsInfo = moduleGraph.getExportsInfo(module);
+ /** @type {RawJsonData} */
+ let finalJson =
+ typeof data === "object" &&
+ data &&
+ exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused
+ ? createObjectForExportsInfo(data, exportsInfo, runtime)
+ : data;
+ // Use JSON because JSON.parse() is much faster than JavaScript evaluation
+ const jsonStr = /** @type {string} */ (stringifySafe(finalJson));
+ const jsonExpr =
+ jsonStr.length > 20 && typeof finalJson === "object"
+ ? `JSON.parse('${jsonStr.replace(/[\\']/g, "\\$&")}')`
+ : jsonStr;
+ /** @type {string} */
+ let content;
+ if (concatenationScope) {
+ content = `${runtimeTemplate.supportsConst() ? "const" : "var"} ${
+ ConcatenationScope.NAMESPACE_OBJECT_EXPORT
+ } = ${jsonExpr};`;
+ concatenationScope.registerNamespaceExport(
+ ConcatenationScope.NAMESPACE_OBJECT_EXPORT
+ );
+ } else {
+ runtimeRequirements.add(RuntimeGlobals.module);
+ content = `${module.moduleArgument}.exports = ${jsonExpr};`;
+ }
+ return new RawSource(content);
+ }
+}
+
+module.exports = JsonGenerator;