webpack 4.3.0 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/webpack.js +69 -10
- package/lib/APIPlugin.js +2 -2
- package/lib/AmdMainTemplatePlugin.js +4 -6
- package/lib/AsyncDependencyToInitialChunkError.js +1 -3
- package/lib/Compilation.js +8 -4
- package/lib/Compiler.js +7 -10
- package/lib/ContextModule.js +19 -7
- package/lib/DefinePlugin.js +2 -2
- package/lib/Dependency.js +53 -52
- package/lib/EnvironmentPlugin.js +1 -3
- package/lib/ExternalModule.js +3 -3
- package/lib/HotUpdateChunkTemplate.js +1 -1
- package/lib/JavascriptGenerator.js +7 -7
- package/lib/JavascriptModulesPlugin.js +6 -6
- package/lib/MainTemplate.js +2 -2
- package/lib/Module.js +343 -340
- package/lib/ModuleFilenameHelpers.js +1 -1
- package/lib/MultiModule.js +4 -1
- package/lib/NoModeWarning.js +23 -21
- package/lib/NormalModule.js +9 -0
- package/lib/NormalModuleFactory.js +1 -1
- package/lib/Parser.js +7 -3
- package/lib/ProgressPlugin.js +231 -231
- package/lib/RecordIdsPlugin.js +2 -2
- package/lib/RuntimeTemplate.js +15 -45
- package/lib/Stats.js +2 -0
- package/lib/Template.js +1 -1
- package/lib/TemplatedPathPlugin.js +1 -3
- package/lib/UmdMainTemplatePlugin.js +41 -45
- package/lib/WebAssemblyParser.js +1 -5
- package/lib/WebpackOptionsApply.js +2 -2
- package/lib/WebpackOptionsDefaulter.js +10 -8
- package/lib/WebpackOptionsValidationError.js +6 -8
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +13 -13
- package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +1 -1
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +5 -11
- package/lib/dependencies/HarmonyExportSpecifierDependency.js +3 -3
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +4 -6
- package/lib/dependencies/ImportParserPlugin.js +2 -6
- package/lib/dependencies/RequireIncludeDependency.js +1 -1
- package/lib/dependencies/WebpackMissingModule.js +1 -3
- package/lib/node/ReadFileCompileWasmMainTemplatePlugin.js +1 -3
- package/lib/optimize/ConcatenatedModule.js +19 -20
- package/lib/optimize/SplitChunksPlugin.js +30 -14
- package/lib/performance/SizeLimitsPlugin.js +105 -105
- package/lib/web/JsonpChunkTemplatePlugin.js +5 -5
- package/lib/web/JsonpMainTemplatePlugin.js +2 -2
- package/package.json +7 -6
- package/schemas/WebpackOptions.json +23 -16
- package/schemas/ajv.absolutePath.js +1 -1
@@ -85,7 +85,9 @@ module.exports = class SplitChunksPlugin {
|
|
85
85
|
|
86
86
|
static normalizeOptions(options = {}) {
|
87
87
|
return {
|
88
|
-
|
88
|
+
chunksFilter: SplitChunksPlugin.normalizeChunksFilter(
|
89
|
+
options.chunks || "all"
|
90
|
+
),
|
89
91
|
minSize: options.minSize || 0,
|
90
92
|
minChunks: options.minChunks || 1,
|
91
93
|
maxAsyncRequests: options.maxAsyncRequests || 1,
|
@@ -135,6 +137,19 @@ module.exports = class SplitChunksPlugin {
|
|
135
137
|
if (typeof name === "function") return name;
|
136
138
|
}
|
137
139
|
|
140
|
+
static normalizeChunksFilter(chunks) {
|
141
|
+
if (chunks === "initial") {
|
142
|
+
return chunk => chunk.canBeInitial();
|
143
|
+
}
|
144
|
+
if (chunks === "async") {
|
145
|
+
return chunk => !chunk.canBeInitial();
|
146
|
+
}
|
147
|
+
if (chunks === "all") {
|
148
|
+
return () => true;
|
149
|
+
}
|
150
|
+
if (typeof chunks === "function") return chunks;
|
151
|
+
}
|
152
|
+
|
138
153
|
static normalizeCacheGroups({ cacheGroups, automaticNameDelimiter }) {
|
139
154
|
if (typeof cacheGroups === "function") {
|
140
155
|
return cacheGroups;
|
@@ -162,6 +177,11 @@ module.exports = class SplitChunksPlugin {
|
|
162
177
|
r
|
163
178
|
);
|
164
179
|
if (result.name) result.getName = () => result.name;
|
180
|
+
if (result.chunks) {
|
181
|
+
result.chunksFilter = SplitChunksPlugin.normalizeChunksFilter(
|
182
|
+
result.chunks
|
183
|
+
);
|
184
|
+
}
|
165
185
|
results.push(result);
|
166
186
|
}
|
167
187
|
}
|
@@ -174,7 +194,9 @@ module.exports = class SplitChunksPlugin {
|
|
174
194
|
name: option.name,
|
175
195
|
automaticNameDelimiter
|
176
196
|
}),
|
177
|
-
|
197
|
+
chunksFilter: SplitChunksPlugin.normalizeChunksFilter(
|
198
|
+
option.chunks
|
199
|
+
),
|
178
200
|
enforce: option.enforce,
|
179
201
|
minSize: option.minSize,
|
180
202
|
minChunks: option.minChunks,
|
@@ -264,7 +286,8 @@ module.exports = class SplitChunksPlugin {
|
|
264
286
|
const cacheGroup = {
|
265
287
|
key: cacheGroupSource.key,
|
266
288
|
priority: cacheGroupSource.priority || 0,
|
267
|
-
|
289
|
+
chunksFilter:
|
290
|
+
cacheGroupSource.chunksFilter || this.options.chunksFilter,
|
268
291
|
minSize:
|
269
292
|
cacheGroupSource.minSize !== undefined
|
270
293
|
? cacheGroupSource.minSize
|
@@ -304,16 +327,9 @@ module.exports = class SplitChunksPlugin {
|
|
304
327
|
// Break if minimum number of chunks is not reached
|
305
328
|
if (chunkIndices.length < cacheGroup.minChunks) continue;
|
306
329
|
// Select chunks by configuration
|
307
|
-
const selectedChunks =
|
308
|
-
cacheGroup.
|
309
|
-
|
310
|
-
chunk.canBeInitial()
|
311
|
-
)
|
312
|
-
: cacheGroup.chunks === "async"
|
313
|
-
? Array.from(chunkCombination).filter(
|
314
|
-
chunk => !chunk.canBeInitial()
|
315
|
-
)
|
316
|
-
: Array.from(chunkCombination);
|
330
|
+
const selectedChunks = Array.from(chunkCombination).filter(
|
331
|
+
cacheGroup.chunksFilter
|
332
|
+
);
|
317
333
|
// Break if minimum number of chunks is not reached
|
318
334
|
if (selectedChunks.length < cacheGroup.minChunks) continue;
|
319
335
|
// Determine name for split chunk
|
@@ -420,7 +436,7 @@ module.exports = class SplitChunksPlugin {
|
|
420
436
|
? Math.min(
|
421
437
|
item.cacheGroup.maxInitialRequests,
|
422
438
|
item.cacheGroup.maxAsyncRequests
|
423
|
-
|
439
|
+
)
|
424
440
|
: item.cacheGroup.maxAsyncRequests;
|
425
441
|
if (isFinite(maxRequests) && getRequests(chunk) >= maxRequests)
|
426
442
|
continue;
|
@@ -1,105 +1,105 @@
|
|
1
|
-
/*
|
2
|
-
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
-
Author Sean Larkin @thelarkinn
|
4
|
-
*/
|
5
|
-
"use strict";
|
6
|
-
const EntrypointsOverSizeLimitWarning = require("./EntrypointsOverSizeLimitWarning");
|
7
|
-
const AssetsOverSizeLimitWarning = require("./AssetsOverSizeLimitWarning");
|
8
|
-
const NoAsyncChunksWarning = require("./NoAsyncChunksWarning");
|
9
|
-
|
10
|
-
module.exports = class SizeLimitsPlugin {
|
11
|
-
constructor(options) {
|
12
|
-
this.hints = options.hints;
|
13
|
-
this.maxAssetSize = options.maxAssetSize;
|
14
|
-
this.maxEntrypointSize = options.maxEntrypointSize;
|
15
|
-
this.assetFilter = options.assetFilter;
|
16
|
-
}
|
17
|
-
apply(compiler) {
|
18
|
-
const entrypointSizeLimit = this.maxEntrypointSize;
|
19
|
-
const assetSizeLimit = this.maxAssetSize;
|
20
|
-
const hints = this.hints;
|
21
|
-
const assetFilter = this.assetFilter || (asset => !asset.endsWith(".map"));
|
22
|
-
|
23
|
-
compiler.hooks.afterEmit.tap("SizeLimitsPlugin", compilation => {
|
24
|
-
const warnings = [];
|
25
|
-
|
26
|
-
const getEntrypointSize = entrypoint =>
|
27
|
-
entrypoint.getFiles().reduce((currentSize, file) => {
|
28
|
-
if (assetFilter(file) && compilation.assets[file]) {
|
29
|
-
return currentSize + compilation.assets[file].size();
|
30
|
-
}
|
31
|
-
|
32
|
-
return currentSize;
|
33
|
-
}, 0);
|
34
|
-
|
35
|
-
const assetsOverSizeLimit = [];
|
36
|
-
for (const assetName of Object.keys(compilation.assets)) {
|
37
|
-
if (!assetFilter(assetName)) {
|
38
|
-
continue;
|
39
|
-
}
|
40
|
-
|
41
|
-
const asset = compilation.assets[assetName];
|
42
|
-
const size = asset.size();
|
43
|
-
if (size > assetSizeLimit) {
|
44
|
-
assetsOverSizeLimit.push({
|
45
|
-
name: assetName,
|
46
|
-
size: size
|
47
|
-
});
|
48
|
-
asset.isOverSizeLimit = true;
|
49
|
-
}
|
50
|
-
}
|
51
|
-
|
52
|
-
const entrypointsOverLimit = [];
|
53
|
-
for (const pair of compilation.entrypoints) {
|
54
|
-
const name = pair[0];
|
55
|
-
const entry = pair[1];
|
56
|
-
const size = getEntrypointSize(entry
|
57
|
-
|
58
|
-
if (size > entrypointSizeLimit) {
|
59
|
-
entrypointsOverLimit.push({
|
60
|
-
name: name,
|
61
|
-
size: size,
|
62
|
-
files: entry.getFiles().filter(assetFilter)
|
63
|
-
});
|
64
|
-
entry.isOverSizeLimit = true;
|
65
|
-
}
|
66
|
-
}
|
67
|
-
|
68
|
-
if (hints) {
|
69
|
-
// 1. Individual Chunk: Size < 250kb
|
70
|
-
// 2. Collective Initial Chunks [entrypoint] (Each Set?): Size < 250kb
|
71
|
-
// 3. No Async Chunks
|
72
|
-
// if !1, then 2, if !2 return
|
73
|
-
if (assetsOverSizeLimit.length > 0) {
|
74
|
-
warnings.push(
|
75
|
-
new AssetsOverSizeLimitWarning(assetsOverSizeLimit, assetSizeLimit)
|
76
|
-
);
|
77
|
-
}
|
78
|
-
if (entrypointsOverLimit.length > 0) {
|
79
|
-
warnings.push(
|
80
|
-
new EntrypointsOverSizeLimitWarning(
|
81
|
-
entrypointsOverLimit,
|
82
|
-
entrypointSizeLimit
|
83
|
-
)
|
84
|
-
);
|
85
|
-
}
|
86
|
-
|
87
|
-
if (warnings.length > 0) {
|
88
|
-
const hasAsyncChunks =
|
89
|
-
compilation.chunks.filter(chunk => !chunk.canBeInitial()).length >
|
90
|
-
0;
|
91
|
-
|
92
|
-
if (!hasAsyncChunks) {
|
93
|
-
warnings.push(new NoAsyncChunksWarning());
|
94
|
-
}
|
95
|
-
|
96
|
-
if (hints === "error") {
|
97
|
-
compilation.errors.push(...warnings);
|
98
|
-
} else {
|
99
|
-
compilation.warnings.push(...warnings);
|
100
|
-
}
|
101
|
-
}
|
102
|
-
}
|
103
|
-
});
|
104
|
-
}
|
105
|
-
};
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Sean Larkin @thelarkinn
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
const EntrypointsOverSizeLimitWarning = require("./EntrypointsOverSizeLimitWarning");
|
7
|
+
const AssetsOverSizeLimitWarning = require("./AssetsOverSizeLimitWarning");
|
8
|
+
const NoAsyncChunksWarning = require("./NoAsyncChunksWarning");
|
9
|
+
|
10
|
+
module.exports = class SizeLimitsPlugin {
|
11
|
+
constructor(options) {
|
12
|
+
this.hints = options.hints;
|
13
|
+
this.maxAssetSize = options.maxAssetSize;
|
14
|
+
this.maxEntrypointSize = options.maxEntrypointSize;
|
15
|
+
this.assetFilter = options.assetFilter;
|
16
|
+
}
|
17
|
+
apply(compiler) {
|
18
|
+
const entrypointSizeLimit = this.maxEntrypointSize;
|
19
|
+
const assetSizeLimit = this.maxAssetSize;
|
20
|
+
const hints = this.hints;
|
21
|
+
const assetFilter = this.assetFilter || (asset => !asset.endsWith(".map"));
|
22
|
+
|
23
|
+
compiler.hooks.afterEmit.tap("SizeLimitsPlugin", compilation => {
|
24
|
+
const warnings = [];
|
25
|
+
|
26
|
+
const getEntrypointSize = entrypoint =>
|
27
|
+
entrypoint.getFiles().reduce((currentSize, file) => {
|
28
|
+
if (assetFilter(file) && compilation.assets[file]) {
|
29
|
+
return currentSize + compilation.assets[file].size();
|
30
|
+
}
|
31
|
+
|
32
|
+
return currentSize;
|
33
|
+
}, 0);
|
34
|
+
|
35
|
+
const assetsOverSizeLimit = [];
|
36
|
+
for (const assetName of Object.keys(compilation.assets)) {
|
37
|
+
if (!assetFilter(assetName)) {
|
38
|
+
continue;
|
39
|
+
}
|
40
|
+
|
41
|
+
const asset = compilation.assets[assetName];
|
42
|
+
const size = asset.size();
|
43
|
+
if (size > assetSizeLimit) {
|
44
|
+
assetsOverSizeLimit.push({
|
45
|
+
name: assetName,
|
46
|
+
size: size
|
47
|
+
});
|
48
|
+
asset.isOverSizeLimit = true;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
const entrypointsOverLimit = [];
|
53
|
+
for (const pair of compilation.entrypoints) {
|
54
|
+
const name = pair[0];
|
55
|
+
const entry = pair[1];
|
56
|
+
const size = getEntrypointSize(entry);
|
57
|
+
|
58
|
+
if (size > entrypointSizeLimit) {
|
59
|
+
entrypointsOverLimit.push({
|
60
|
+
name: name,
|
61
|
+
size: size,
|
62
|
+
files: entry.getFiles().filter(assetFilter)
|
63
|
+
});
|
64
|
+
entry.isOverSizeLimit = true;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
if (hints) {
|
69
|
+
// 1. Individual Chunk: Size < 250kb
|
70
|
+
// 2. Collective Initial Chunks [entrypoint] (Each Set?): Size < 250kb
|
71
|
+
// 3. No Async Chunks
|
72
|
+
// if !1, then 2, if !2 return
|
73
|
+
if (assetsOverSizeLimit.length > 0) {
|
74
|
+
warnings.push(
|
75
|
+
new AssetsOverSizeLimitWarning(assetsOverSizeLimit, assetSizeLimit)
|
76
|
+
);
|
77
|
+
}
|
78
|
+
if (entrypointsOverLimit.length > 0) {
|
79
|
+
warnings.push(
|
80
|
+
new EntrypointsOverSizeLimitWarning(
|
81
|
+
entrypointsOverLimit,
|
82
|
+
entrypointSizeLimit
|
83
|
+
)
|
84
|
+
);
|
85
|
+
}
|
86
|
+
|
87
|
+
if (warnings.length > 0) {
|
88
|
+
const hasAsyncChunks =
|
89
|
+
compilation.chunks.filter(chunk => !chunk.canBeInitial()).length >
|
90
|
+
0;
|
91
|
+
|
92
|
+
if (!hasAsyncChunks) {
|
93
|
+
warnings.push(new NoAsyncChunksWarning());
|
94
|
+
}
|
95
|
+
|
96
|
+
if (hints === "error") {
|
97
|
+
compilation.errors.push(...warnings);
|
98
|
+
} else {
|
99
|
+
compilation.warnings.push(...warnings);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
});
|
104
|
+
}
|
105
|
+
};
|
@@ -15,11 +15,11 @@ class JsonpChunkTemplatePlugin {
|
|
15
15
|
const globalObject = chunkTemplate.outputOptions.globalObject;
|
16
16
|
const source = new ConcatSource();
|
17
17
|
source.add(
|
18
|
-
`(${globalObject}[${JSON.stringify(
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
)},`
|
18
|
+
`(${globalObject}[${JSON.stringify(
|
19
|
+
jsonpFunction
|
20
|
+
)}] = ${globalObject}[${JSON.stringify(
|
21
|
+
jsonpFunction
|
22
|
+
)}] || []).push([${JSON.stringify(chunk.ids)},`
|
23
23
|
);
|
24
24
|
source.add(modules);
|
25
25
|
const entries = [chunk.entryModule].filter(Boolean).map(m =>
|
@@ -265,7 +265,7 @@ class JsonpMainTemplatePlugin {
|
|
265
265
|
"",
|
266
266
|
"// run deferred modules when all chunks ready",
|
267
267
|
"return checkDeferredModules();"
|
268
|
-
|
268
|
+
])
|
269
269
|
: ""
|
270
270
|
]),
|
271
271
|
"};",
|
@@ -299,7 +299,7 @@ class JsonpMainTemplatePlugin {
|
|
299
299
|
"return result;"
|
300
300
|
]),
|
301
301
|
"}"
|
302
|
-
|
302
|
+
])
|
303
303
|
: ""
|
304
304
|
]);
|
305
305
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "webpack",
|
3
|
-
"version": "4.
|
3
|
+
"version": "4.4.0",
|
4
4
|
"author": "Tobias Koppers @sokra",
|
5
5
|
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
|
6
6
|
"license": "MIT",
|
@@ -34,9 +34,10 @@
|
|
34
34
|
"coveralls": "^2.11.2",
|
35
35
|
"css-loader": "^0.28.3",
|
36
36
|
"es6-promise-polyfill": "^1.1.1",
|
37
|
-
"eslint": "^4.
|
38
|
-
"eslint-
|
39
|
-
"eslint-plugin-
|
37
|
+
"eslint": "^4.19.1",
|
38
|
+
"eslint-config-prettier": "^2.9.0",
|
39
|
+
"eslint-plugin-node": "^6.0.1",
|
40
|
+
"eslint-plugin-prettier": "^2.6.0",
|
40
41
|
"express": "~4.13.1",
|
41
42
|
"file-loader": "^1.1.6",
|
42
43
|
"glob": "^7.1.2",
|
@@ -50,7 +51,7 @@
|
|
50
51
|
"lodash": "^4.17.4",
|
51
52
|
"mocha": "^3.2.0",
|
52
53
|
"mocha-lcov-reporter": "^1.0.0",
|
53
|
-
"prettier": "^1.
|
54
|
+
"prettier": "^1.11.1",
|
54
55
|
"raw-loader": "~0.5.0",
|
55
56
|
"react": "^15.2.1",
|
56
57
|
"react-dom": "^15.2.1",
|
@@ -104,7 +105,7 @@
|
|
104
105
|
"lint-files": "npm run lint && npm run schema-lint",
|
105
106
|
"lint": "eslint lib bin hot buildin \"test/*.js\" \"test/**/webpack.config.js\" \"examples/**/webpack.config.js\" \"schemas/**/*.js\"",
|
106
107
|
"fix": "npm run lint -- --fix",
|
107
|
-
"pretty-files": "prettier \"lib
|
108
|
+
"pretty-files": "prettier \"lib/**/*.js\" \"bin/*.js\" \"hot/*.js\" \"buildin/*.js\" \"test/*.js\" \"test/**/webpack.config.js\" \"examples/**/webpack.config.js\" \"schemas/**/*.js\" --write",
|
108
109
|
"schema-lint": "mocha test/*.lint.js --opts test/lint-mocha.opts",
|
109
110
|
"benchmark": "mocha --max-old-space-size=4096 --harmony --trace-deprecation test/*.benchmark.js -R spec",
|
110
111
|
"cover": "npm run cover:init && npm run cover:all && npm run cover:report",
|
@@ -324,14 +324,7 @@
|
|
324
324
|
},
|
325
325
|
"chunkFilename": {
|
326
326
|
"description": "The filename of non-entry chunks as relative path inside the `output.path` directory.",
|
327
|
-
"
|
328
|
-
{
|
329
|
-
"type": "string"
|
330
|
-
},
|
331
|
-
{
|
332
|
-
"instanceof": "Function"
|
333
|
-
}
|
334
|
-
],
|
327
|
+
"type": "string",
|
335
328
|
"absolutePath": false
|
336
329
|
},
|
337
330
|
"webassemblyModuleFilename": {
|
@@ -1337,10 +1330,17 @@
|
|
1337
1330
|
"properties": {
|
1338
1331
|
"chunks": {
|
1339
1332
|
"description": "Select chunks for determining shared modules (defaults to \"async\", \"initial\" and \"all\" requires adding these chunks to the HTML)",
|
1340
|
-
"
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1333
|
+
"oneOf": [
|
1334
|
+
{
|
1335
|
+
"enum": [
|
1336
|
+
"initial",
|
1337
|
+
"async",
|
1338
|
+
"all"
|
1339
|
+
]
|
1340
|
+
},
|
1341
|
+
{
|
1342
|
+
"instanceof": "Function"
|
1343
|
+
}
|
1344
1344
|
]
|
1345
1345
|
},
|
1346
1346
|
"minSize": {
|
@@ -1427,10 +1427,17 @@
|
|
1427
1427
|
},
|
1428
1428
|
"chunks": {
|
1429
1429
|
"description": "Select chunks for determining cache group content (defaults to \"initial\", \"initial\" and \"all\" requires adding these chunks to the HTML)",
|
1430
|
-
"
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1430
|
+
"oneOf": [
|
1431
|
+
{
|
1432
|
+
"enum": [
|
1433
|
+
"initial",
|
1434
|
+
"async",
|
1435
|
+
"all"
|
1436
|
+
]
|
1437
|
+
},
|
1438
|
+
{
|
1439
|
+
"instanceof": "Function"
|
1440
|
+
}
|
1434
1441
|
]
|
1435
1442
|
},
|
1436
1443
|
"enforce": {
|
@@ -12,7 +12,7 @@ const getErrorFor = (shouldBeAbsolute, data, schema) => {
|
|
12
12
|
? `The provided value ${JSON.stringify(data)} is not an absolute path!`
|
13
13
|
: `A relative path is expected. However, the provided value ${JSON.stringify(
|
14
14
|
data
|
15
|
-
|
15
|
+
)} is an absolute path!`;
|
16
16
|
|
17
17
|
return errorMessage(schema, data, message);
|
18
18
|
};
|