mirror of https://github.com/webpack/webpack.git
feat: implement `module.generator.json.JSONParse`
For large `.json` modules, webpack will generate `JSON.parse` by default for better performance. But there are some circumstances that `JSON.parse` is not a good choice (e.g.: when doing AOT compilation). Thus, a new generator option `module.generator.json.JSONParse` is added to disable generating `JSON.parse` for `.json` module. The default value is kept as `true` and can be opt-out by custom rules. fix: #19319
This commit is contained in:
parent
cb25853b58
commit
8ab85e29bb
|
@ -3346,6 +3346,15 @@ export interface JavascriptParserOptions {
|
||||||
wrappedContextRegExp?: RegExp;
|
wrappedContextRegExp?: RegExp;
|
||||||
[k: string]: any;
|
[k: string]: any;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Generator options for json modules.
|
||||||
|
*/
|
||||||
|
export interface JsonGeneratorOptions {
|
||||||
|
/**
|
||||||
|
* Use `JSON.parse` when the JSON string is longer than 20 characters.
|
||||||
|
*/
|
||||||
|
JSONParse?: boolean;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Options for the default backend.
|
* Options for the default backend.
|
||||||
*/
|
*/
|
||||||
|
@ -3882,6 +3891,10 @@ export interface GeneratorOptionsByModuleTypeKnown {
|
||||||
* No generator options are supported for this module type.
|
* No generator options are supported for this module type.
|
||||||
*/
|
*/
|
||||||
"javascript/esm"?: EmptyGeneratorOptions;
|
"javascript/esm"?: EmptyGeneratorOptions;
|
||||||
|
/**
|
||||||
|
* Generator options for json modules.
|
||||||
|
*/
|
||||||
|
json?: JsonGeneratorOptions;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Specify options for each generator.
|
* Specify options for each generator.
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* This file was automatically generated.
|
||||||
|
* DO NOT MODIFY BY HAND.
|
||||||
|
* Run `yarn special-lint-fix` to update
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface JsonModulesPluginGeneratorOptions {
|
||||||
|
/**
|
||||||
|
* Use `JSON.parse` when the JSON string is longer than 20 characters.
|
||||||
|
*/
|
||||||
|
JSONParse?: boolean;
|
||||||
|
}
|
|
@ -47,6 +47,7 @@ const {
|
||||||
/** @typedef {import("../../declarations/WebpackOptions").GeneratorOptionsByModuleTypeKnown} GeneratorOptionsByModuleTypeKnown */
|
/** @typedef {import("../../declarations/WebpackOptions").GeneratorOptionsByModuleTypeKnown} GeneratorOptionsByModuleTypeKnown */
|
||||||
/** @typedef {import("../../declarations/WebpackOptions").InfrastructureLogging} InfrastructureLogging */
|
/** @typedef {import("../../declarations/WebpackOptions").InfrastructureLogging} InfrastructureLogging */
|
||||||
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
|
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
|
||||||
|
/** @typedef {import("../../declarations/WebpackOptions").JsonGeneratorOptions} JsonGeneratorOptions */
|
||||||
/** @typedef {import("../../declarations/WebpackOptions").Library} Library */
|
/** @typedef {import("../../declarations/WebpackOptions").Library} Library */
|
||||||
/** @typedef {import("../../declarations/WebpackOptions").LibraryName} LibraryName */
|
/** @typedef {import("../../declarations/WebpackOptions").LibraryName} LibraryName */
|
||||||
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
|
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
|
||||||
|
@ -581,6 +582,14 @@ const applyJavascriptParserOptionsDefaults = (
|
||||||
if (futureDefaults) D(parserOptions, "exportsPresence", "error");
|
if (futureDefaults) D(parserOptions, "exportsPresence", "error");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {JsonGeneratorOptions} generatorOptions generator options
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
const applyJsonGeneratorOptionsDefaults = generatorOptions => {
|
||||||
|
D(generatorOptions, "JSONParse", true);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {CssGeneratorOptions} generatorOptions generator options
|
* @param {CssGeneratorOptions} generatorOptions generator options
|
||||||
* @param {object} options options
|
* @param {object} options options
|
||||||
|
@ -682,6 +691,12 @@ const applyModuleDefaults = (
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
F(module.generator, "json", () => ({}));
|
||||||
|
applyJsonGeneratorOptionsDefaults(
|
||||||
|
/** @type {NonNullable<GeneratorOptionsByModuleTypeKnown["json"]>} */
|
||||||
|
(module.generator.json)
|
||||||
|
);
|
||||||
|
|
||||||
if (css) {
|
if (css) {
|
||||||
F(module.parser, CSS_MODULE_TYPE, () => ({}));
|
F(module.parser, CSS_MODULE_TYPE, () => ({}));
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ const { JS_TYPES } = require("../ModuleSourceTypesConstants");
|
||||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||||
|
|
||||||
/** @typedef {import("webpack-sources").Source} Source */
|
/** @typedef {import("webpack-sources").Source} Source */
|
||||||
|
/** @typedef {import("../../declarations/WebpackOptions").JsonGeneratorOptions} JsonGeneratorOptions */
|
||||||
/** @typedef {import("../ExportsInfo")} ExportsInfo */
|
/** @typedef {import("../ExportsInfo")} ExportsInfo */
|
||||||
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
|
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
|
||||||
/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
|
/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
|
||||||
|
@ -106,6 +107,14 @@ const createObjectForExportsInfo = (data, exportsInfo, runtime) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonGenerator extends Generator {
|
class JsonGenerator extends Generator {
|
||||||
|
/**
|
||||||
|
* @param {JsonGeneratorOptions} options options
|
||||||
|
*/
|
||||||
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {NormalModule} module fresh module
|
* @param {NormalModule} module fresh module
|
||||||
* @returns {SourceTypes} available types (do not mutate)
|
* @returns {SourceTypes} available types (do not mutate)
|
||||||
|
@ -176,7 +185,9 @@ class JsonGenerator extends Generator {
|
||||||
// Use JSON because JSON.parse() is much faster than JavaScript evaluation
|
// Use JSON because JSON.parse() is much faster than JavaScript evaluation
|
||||||
const jsonStr = /** @type {string} */ (stringifySafe(finalJson));
|
const jsonStr = /** @type {string} */ (stringifySafe(finalJson));
|
||||||
const jsonExpr =
|
const jsonExpr =
|
||||||
jsonStr.length > 20 && typeof finalJson === "object"
|
this.options.JSONParse &&
|
||||||
|
jsonStr.length > 20 &&
|
||||||
|
typeof finalJson === "object"
|
||||||
? `/*#__PURE__*/JSON.parse('${jsonStr.replace(/[\\']/g, "\\$&")}')`
|
? `/*#__PURE__*/JSON.parse('${jsonStr.replace(/[\\']/g, "\\$&")}')`
|
||||||
: jsonStr.replace(/"__proto__":/g, '["__proto__"]:');
|
: jsonStr.replace(/"__proto__":/g, '["__proto__"]:');
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
|
|
|
@ -22,6 +22,15 @@ const validate = createSchemaValidation(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const validateGenerator = createSchemaValidation(
|
||||||
|
require("../../schemas/plugins/JsonModulesPluginGenerator.check.js"),
|
||||||
|
() => require("../../schemas/plugins/JsonModulesPluginGenerator.json"),
|
||||||
|
{
|
||||||
|
name: "Json Modules Plugin",
|
||||||
|
baseDataPath: "generator"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const PLUGIN_NAME = "JsonModulesPlugin";
|
const PLUGIN_NAME = "JsonModulesPlugin";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,7 +55,10 @@ class JsonModulesPlugin {
|
||||||
});
|
});
|
||||||
normalModuleFactory.hooks.createGenerator
|
normalModuleFactory.hooks.createGenerator
|
||||||
.for(JSON_MODULE_TYPE)
|
.for(JSON_MODULE_TYPE)
|
||||||
.tap(PLUGIN_NAME, () => new JsonGenerator());
|
.tap(PLUGIN_NAME, generatorOptions => {
|
||||||
|
validateGenerator(generatorOptions);
|
||||||
|
return new JsonGenerator(generatorOptions);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,5 +187,6 @@
|
||||||
"node node_modules/prettier/bin/prettier.cjs --cache --write --ignore-unknown",
|
"node node_modules/prettier/bin/prettier.cjs --cache --write --ignore-unknown",
|
||||||
"cspell --cache --no-must-find-files"
|
"cspell --cache --no-must-find-files"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1571,6 +1571,9 @@
|
||||||
},
|
},
|
||||||
"javascript/esm": {
|
"javascript/esm": {
|
||||||
"$ref": "#/definitions/EmptyGeneratorOptions"
|
"$ref": "#/definitions/EmptyGeneratorOptions"
|
||||||
|
},
|
||||||
|
"json": {
|
||||||
|
"$ref": "#/definitions/JsonGeneratorOptions"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2009,6 +2012,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"JsonGeneratorOptions": {
|
||||||
|
"description": "Generator options for json modules.",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"JSONParse": {
|
||||||
|
"description": "Use `JSON.parse` when the JSON string is longer than 20 characters.",
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Layer": {
|
"Layer": {
|
||||||
"description": "Specifies the layer in which modules of this entrypoint are placed.",
|
"description": "Specifies the layer in which modules of this entrypoint are placed.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
/*
|
||||||
|
* This file was automatically generated.
|
||||||
|
* DO NOT MODIFY BY HAND.
|
||||||
|
* Run `yarn special-lint-fix` to update
|
||||||
|
*/
|
||||||
|
declare const check: (options: import("../../declarations/plugins/JsonModulesPluginGenerator").JsonModulesPluginGeneratorOptions) => boolean;
|
||||||
|
export = check;
|
|
@ -0,0 +1,6 @@
|
||||||
|
/*
|
||||||
|
* This file was automatically generated.
|
||||||
|
* DO NOT MODIFY BY HAND.
|
||||||
|
* Run `yarn special-lint-fix` to update
|
||||||
|
*/
|
||||||
|
"use strict";function r(e,{instancePath:t="",parentData:a,parentDataProperty:o,rootData:s=e}={}){if(!e||"object"!=typeof e||Array.isArray(e))return r.errors=[{params:{type:"object"}}],!1;{const t=0;for(const t in e)if("JSONParse"!==t)return r.errors=[{params:{additionalProperty:t}}],!1;if(0===t&&void 0!==e.JSONParse&&"boolean"!=typeof e.JSONParse)return r.errors=[{params:{type:"boolean"}}],!1}return r.errors=null,!0}module.exports=r,module.exports.default=r;
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"title": "JsonModulesPluginGeneratorOptions",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"JSONParse": {
|
||||||
|
"description": "Use `JSON.parse` when the JSON string is longer than 20 characters.",
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -225,7 +225,11 @@ describe("snapshots", () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"generator": Object {},
|
"generator": Object {
|
||||||
|
"json": Object {
|
||||||
|
"JSONParse": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
"noParse": undefined,
|
"noParse": undefined,
|
||||||
"parser": Object {
|
"parser": Object {
|
||||||
"asset": Object {
|
"asset": Object {
|
||||||
|
@ -2290,7 +2294,7 @@ describe("snapshots", () => {
|
||||||
+ },
|
+ },
|
||||||
+ "resolve": Object {
|
+ "resolve": Object {
|
||||||
+ "fullySpecified": true,
|
+ "fullySpecified": true,
|
||||||
+ },
|
@@ ... @@
|
||||||
+ },
|
+ },
|
||||||
+ ],
|
+ ],
|
||||||
+ "test": /\\.wasm$/i,
|
+ "test": /\\.wasm$/i,
|
||||||
|
@ -2299,7 +2303,7 @@ describe("snapshots", () => {
|
||||||
+ Object {
|
+ Object {
|
||||||
+ "mimetype": "application/wasm",
|
+ "mimetype": "application/wasm",
|
||||||
+ "rules": Array [
|
+ "rules": Array [
|
||||||
+ Object {
|
@@ ... @@
|
||||||
+ "descriptionData": Object {
|
+ "descriptionData": Object {
|
||||||
+ "type": "module",
|
+ "type": "module",
|
||||||
+ },
|
+ },
|
||||||
|
@ -2331,12 +2335,11 @@ describe("snapshots", () => {
|
||||||
+ "resolve": Object {
|
+ "resolve": Object {
|
||||||
+ "fullySpecified": true,
|
+ "fullySpecified": true,
|
||||||
+ "preferRelative": true,
|
+ "preferRelative": true,
|
||||||
@@ ... @@
|
+ },
|
||||||
+ "type": "css",
|
+ "type": "css",
|
||||||
+ },
|
+ },
|
||||||
|
+ Object {
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
- "generator": Object {},
|
|
||||||
+ "generator": Object {
|
|
||||||
+ "css": Object {
|
+ "css": Object {
|
||||||
+ "esModule": true,
|
+ "esModule": true,
|
||||||
+ "exportsOnly": false,
|
+ "exportsOnly": false,
|
||||||
|
@ -2353,14 +2356,12 @@ describe("snapshots", () => {
|
||||||
+ "exportsConvention": "as-is",
|
+ "exportsConvention": "as-is",
|
||||||
+ "localIdentName": "[uniqueName]-[id]-[local]",
|
+ "localIdentName": "[uniqueName]-[id]-[local]",
|
||||||
+ },
|
+ },
|
||||||
+ },
|
|
||||||
@@ ... @@
|
|
||||||
+ },
|
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
+ "css": Object {
|
+ "css": Object {
|
||||||
+ "import": true,
|
+ "import": true,
|
||||||
+ "namedExports": true,
|
+ "namedExports": true,
|
||||||
+ "url": true,
|
+ "url": true,
|
||||||
|
+ },
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
+ "exportsPresence": "error",
|
+ "exportsPresence": "error",
|
||||||
@@ ... @@
|
@@ ... @@
|
||||||
|
|
|
@ -1672,6 +1672,19 @@ Object {
|
||||||
"multiple": false,
|
"multiple": false,
|
||||||
"simpleType": "string",
|
"simpleType": "string",
|
||||||
},
|
},
|
||||||
|
"module-generator-json-json-parse": Object {
|
||||||
|
"configs": Array [
|
||||||
|
Object {
|
||||||
|
"description": "Use \`JSON.parse\` when the JSON string is longer than 20 characters.",
|
||||||
|
"multiple": false,
|
||||||
|
"path": "module.generator.json.JSONParse",
|
||||||
|
"type": "boolean",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"description": "Use \`JSON.parse\` when the JSON string is longer than 20 characters.",
|
||||||
|
"multiple": false,
|
||||||
|
"simpleType": "boolean",
|
||||||
|
},
|
||||||
"module-no-parse": Object {
|
"module-no-parse": Object {
|
||||||
"configs": Array [
|
"configs": Array [
|
||||||
Object {
|
Object {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
{"this is a large JSON object": "that should be converted to JSON.parse by default"}
|
|
@ -0,0 +1,5 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"this is a large JSON object": "that should be converted to JSON.parse by default"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,24 @@
|
||||||
|
it("should avoid JSON.parse", () => {
|
||||||
|
const JSONParse = jest.spyOn(JSON, 'parse');
|
||||||
|
JSONParse.mockClear();
|
||||||
|
|
||||||
|
const data = require('./data.json');
|
||||||
|
const data2 = require('data:application/json,{"this is a large JSON object": "that should be converted to JSON.parse by default"}');
|
||||||
|
const data3 = require('./data1.json');
|
||||||
|
|
||||||
|
expect(data).toMatchObject({["this is a large JSON object"]: "that should be converted to JSON.parse by default"});
|
||||||
|
expect(data2).toMatchObject({["this is a large JSON object"]: "that should be converted to JSON.parse by default"});
|
||||||
|
expect(data3).toMatchObject([{"this is a large JSON object": "that should be converted to JSON.parse by default"}]);
|
||||||
|
|
||||||
|
expect(JSONParse).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should JSON.parse when resourceQuery is JSONParse=true", () => {
|
||||||
|
const JSONParse = jest.spyOn(JSON, 'parse');
|
||||||
|
JSONParse.mockClear();
|
||||||
|
|
||||||
|
const data = require('./data.json?JSONParse=true');
|
||||||
|
|
||||||
|
expect(data).toMatchObject({["this is a large JSON object"]: "that should be converted to JSON.parse by default"});
|
||||||
|
expect(JSONParse).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
|
@ -0,0 +1,16 @@
|
||||||
|
/** @type {import("../../../../").Configuration} */
|
||||||
|
module.exports = {
|
||||||
|
devtool: false,
|
||||||
|
mode: "development",
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.json$/,
|
||||||
|
resourceQuery: /JSONParse=true/,
|
||||||
|
type: "json",
|
||||||
|
generator: { JSONParse: true }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
generator: { json: { JSONParse: false } }
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1 @@
|
||||||
|
{"123this is a large JSON object": "that should be converted to JSON.parse by default"}
|
|
@ -0,0 +1,5 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"this is a large JSON object": "that should be converted to JSON.parse by default"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,24 @@
|
||||||
|
it("should use JSON.parse", () => {
|
||||||
|
const JSONParse = jest.spyOn(JSON, 'parse');
|
||||||
|
JSONParse.mockClear();
|
||||||
|
|
||||||
|
const data = require('./data.json');
|
||||||
|
const data2 = require('data:application/json,{"this is a large JSON object": "that should be converted to JSON.parse by default"}');
|
||||||
|
const data3 = require('./data1.json');
|
||||||
|
|
||||||
|
expect(data).toMatchObject({["123this is a large JSON object"]: "that should be converted to JSON.parse by default"});
|
||||||
|
expect(data2).toMatchObject({["this is a large JSON object"]: "that should be converted to JSON.parse by default"});
|
||||||
|
expect(data3).toMatchObject([{"this is a large JSON object": "that should be converted to JSON.parse by default"}]);
|
||||||
|
|
||||||
|
expect(JSONParse).toHaveBeenCalledTimes(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not call JSON.parse when resourceQuery is JSONParse=false", () => {
|
||||||
|
const JSONParse = jest.spyOn(JSON, 'parse');
|
||||||
|
JSONParse.mockClear();
|
||||||
|
|
||||||
|
const data = require('./data.json?JSONParse=false');
|
||||||
|
|
||||||
|
expect(data).toMatchObject({["123this is a large JSON object"]: "that should be converted to JSON.parse by default"});
|
||||||
|
expect(JSONParse).not.toHaveBeenCalled();
|
||||||
|
});
|
|
@ -0,0 +1,16 @@
|
||||||
|
/** @type {import("../../../../").Configuration} */
|
||||||
|
module.exports = {
|
||||||
|
devtool: false,
|
||||||
|
mode: "development",
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.json$/,
|
||||||
|
resourceQuery: /JSONParse=false/,
|
||||||
|
type: "json",
|
||||||
|
generator: { JSONParse: false }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
generator: { json: { JSONParse: true } }
|
||||||
|
}
|
||||||
|
};
|
|
@ -5350,6 +5350,11 @@ declare interface GeneratorOptionsByModuleTypeKnown {
|
||||||
* No generator options are supported for this module type.
|
* No generator options are supported for this module type.
|
||||||
*/
|
*/
|
||||||
"javascript/esm"?: EmptyGeneratorOptions;
|
"javascript/esm"?: EmptyGeneratorOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generator options for json modules.
|
||||||
|
*/
|
||||||
|
json?: JsonGeneratorOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7419,6 +7424,16 @@ declare interface JavascriptParserOptions {
|
||||||
*/
|
*/
|
||||||
wrappedContextRegExp?: RegExp;
|
wrappedContextRegExp?: RegExp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generator options for json modules.
|
||||||
|
*/
|
||||||
|
declare interface JsonGeneratorOptions {
|
||||||
|
/**
|
||||||
|
* Use `JSON.parse` when the JSON string is longer than 20 characters.
|
||||||
|
*/
|
||||||
|
JSONParse?: boolean;
|
||||||
|
}
|
||||||
type JsonObjectFs = { [index: string]: JsonValueFs } & {
|
type JsonObjectFs = { [index: string]: JsonValueFs } & {
|
||||||
[index: string]:
|
[index: string]:
|
||||||
| undefined
|
| undefined
|
||||||
|
|
Loading…
Reference in New Issue