webpack 4.1.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.
Files changed (118) hide show
  1. package/README.md +719 -721
  2. package/bin/webpack.js +69 -10
  3. package/lib/APIPlugin.js +84 -84
  4. package/lib/AmdMainTemplatePlugin.js +75 -77
  5. package/lib/AsyncDependencyToInitialChunkError.js +21 -23
  6. package/lib/BannerPlugin.js +101 -101
  7. package/lib/Chunk.js +477 -469
  8. package/lib/ChunkTemplate.js +51 -53
  9. package/lib/Compilation.js +1858 -1851
  10. package/lib/Compiler.js +493 -478
  11. package/lib/ConcurrentCompilationError.js +19 -0
  12. package/lib/ContextModule.js +696 -685
  13. package/lib/ContextModuleFactory.js +245 -243
  14. package/lib/DefinePlugin.js +197 -197
  15. package/lib/DelegatedModule.js +101 -101
  16. package/lib/DependenciesBlockVariable.js +51 -52
  17. package/lib/Dependency.js +53 -52
  18. package/lib/DllModule.js +54 -54
  19. package/lib/DllModuleFactory.js +29 -29
  20. package/lib/EnvironmentPlugin.js +65 -67
  21. package/lib/EvalDevToolModuleTemplatePlugin.js +60 -60
  22. package/lib/EvalSourceMapDevToolModuleTemplatePlugin.js +105 -105
  23. package/lib/ExportPropertyMainTemplatePlugin.js +40 -40
  24. package/lib/ExternalModule.js +159 -159
  25. package/lib/FunctionModuleTemplatePlugin.js +98 -98
  26. package/lib/HotModuleReplacement.runtime.js +631 -631
  27. package/lib/HotModuleReplacementPlugin.js +407 -406
  28. package/lib/HotUpdateChunkTemplate.js +78 -80
  29. package/lib/JavascriptGenerator.js +228 -229
  30. package/lib/JavascriptModulesPlugin.js +184 -158
  31. package/lib/JsonGenerator.js +42 -42
  32. package/lib/MainTemplate.js +406 -402
  33. package/lib/Module.js +343 -340
  34. package/lib/ModuleBuildError.js +42 -42
  35. package/lib/ModuleError.js +28 -28
  36. package/lib/ModuleFilenameHelpers.js +166 -166
  37. package/lib/ModuleTemplate.js +77 -79
  38. package/lib/ModuleWarning.js +30 -30
  39. package/lib/MultiCompiler.js +271 -259
  40. package/lib/MultiModule.js +78 -75
  41. package/lib/MultiModuleFactory.js +23 -23
  42. package/lib/MultiWatching.js +38 -37
  43. package/lib/NoModeWarning.js +23 -21
  44. package/lib/NormalModule.js +478 -470
  45. package/lib/NormalModuleFactory.js +483 -481
  46. package/lib/OptionsDefaulter.js +80 -86
  47. package/lib/Parser.js +2074 -2071
  48. package/lib/ProgressPlugin.js +231 -231
  49. package/lib/RawModule.js +54 -55
  50. package/lib/RecordIdsPlugin.js +160 -160
  51. package/lib/RemovedPluginError.js +13 -13
  52. package/lib/ResolverFactory.js +64 -67
  53. package/lib/RuntimeTemplate.js +267 -297
  54. package/lib/SetVarMainTemplatePlugin.js +57 -57
  55. package/lib/SourceMapDevToolPlugin.js +302 -308
  56. package/lib/Stats.js +1234 -1212
  57. package/lib/Template.js +205 -205
  58. package/lib/TemplatedPathPlugin.js +170 -143
  59. package/lib/UmdMainTemplatePlugin.js +264 -269
  60. package/lib/Watching.js +193 -193
  61. package/lib/WebAssemblyParser.js +50 -54
  62. package/lib/WebpackOptionsApply.js +401 -401
  63. package/lib/WebpackOptionsDefaulter.js +337 -317
  64. package/lib/WebpackOptionsValidationError.js +316 -319
  65. package/lib/debug/ProfilingPlugin.js +409 -405
  66. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +328 -311
  67. package/lib/dependencies/AMDRequireContextDependency.js +20 -20
  68. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +270 -241
  69. package/lib/dependencies/HarmonyAcceptImportDependency.js +23 -23
  70. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +620 -606
  71. package/lib/dependencies/HarmonyExportSpecifierDependency.js +53 -53
  72. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +214 -214
  73. package/lib/dependencies/HarmonyImportSpecifierDependency.js +154 -156
  74. package/lib/dependencies/ImportDependenciesBlock.js +17 -17
  75. package/lib/dependencies/ImportDependency.js +34 -34
  76. package/lib/dependencies/ImportEagerDependency.js +32 -32
  77. package/lib/dependencies/ImportParserPlugin.js +175 -179
  78. package/lib/dependencies/ImportWeakDependency.js +34 -34
  79. package/lib/dependencies/JsonExportsDependency.js +25 -25
  80. package/lib/dependencies/ModuleDependency.js +20 -20
  81. package/lib/dependencies/NullDependency.js +20 -20
  82. package/lib/dependencies/RequireContextDependency.js +22 -22
  83. package/lib/dependencies/RequireIncludeDependency.js +40 -40
  84. package/lib/dependencies/WebpackMissingModule.js +20 -22
  85. package/lib/node/NodeChunkTemplatePlugin.js +31 -31
  86. package/lib/node/NodeHotUpdateChunkTemplatePlugin.js +36 -36
  87. package/lib/node/NodeMainTemplatePlugin.js +320 -273
  88. package/lib/node/ReadFileCompileWasmMainTemplatePlugin.js +113 -115
  89. package/lib/optimize/AggressiveSplittingPlugin.js +281 -281
  90. package/lib/optimize/ConcatenatedModule.js +1364 -1366
  91. package/lib/optimize/RemoveParentModulesPlugin.js +114 -114
  92. package/lib/optimize/SplitChunksPlugin.js +519 -491
  93. package/lib/performance/SizeLimitsPlugin.js +105 -105
  94. package/lib/util/TrackingSet.js +35 -35
  95. package/lib/util/objectToMap.js +10 -10
  96. package/lib/wasm/WasmModuleTemplatePlugin.js +106 -106
  97. package/lib/web/JsonpChunkTemplatePlugin.js +47 -47
  98. package/lib/web/JsonpExportMainTemplatePlugin.js +47 -47
  99. package/lib/web/JsonpHotUpdateChunkTemplatePlugin.js +39 -39
  100. package/lib/web/JsonpMainTemplatePlugin.js +425 -403
  101. package/lib/webpack.js +182 -179
  102. package/lib/webworker/WebWorkerChunkTemplatePlugin.js +35 -35
  103. package/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js +40 -40
  104. package/lib/webworker/WebWorkerMainTemplatePlugin.js +177 -154
  105. package/package.json +9 -8
  106. package/schemas/WebpackOptions.json +1973 -1951
  107. package/schemas/ajv.absolutePath.js +55 -29
  108. package/schemas/plugins/BannerPlugin.json +85 -85
  109. package/schemas/plugins/DllPlugin.json +28 -28
  110. package/schemas/plugins/DllReferencePlugin.json +99 -99
  111. package/schemas/plugins/HashedModuleIdsPlugin.json +24 -24
  112. package/schemas/plugins/LoaderOptionsPlugin.json +26 -26
  113. package/schemas/plugins/SourceMapDevToolPlugin.json +187 -187
  114. package/schemas/plugins/WatchIgnorePlugin.json +16 -16
  115. package/schemas/plugins/debug/ProfilingPlugin.json +12 -12
  116. package/schemas/plugins/optimize/AggressiveSplittingPlugin.json +22 -22
  117. package/schemas/plugins/optimize/LimitChunkCountPlugin.json +15 -15
  118. package/schemas/plugins/optimize/MinChunkSizePlugin.json +13 -13
@@ -1,470 +1,478 @@
1
- /*
2
- MIT License http://www.opensource.org/licenses/mit-license.php
3
- Author Tobias Koppers @sokra
4
- */
5
- "use strict";
6
-
7
- const path = require("path");
8
- const NativeModule = require("module");
9
-
10
- const SourceMapSource = require("webpack-sources").SourceMapSource;
11
- const OriginalSource = require("webpack-sources").OriginalSource;
12
- const RawSource = require("webpack-sources").RawSource;
13
- const CachedSource = require("webpack-sources").CachedSource;
14
- const LineToLineMappedSource = require("webpack-sources")
15
- .LineToLineMappedSource;
16
-
17
- const WebpackError = require("./WebpackError");
18
- const Module = require("./Module");
19
- const ModuleParseError = require("./ModuleParseError");
20
- const ModuleBuildError = require("./ModuleBuildError");
21
- const ModuleError = require("./ModuleError");
22
- const ModuleWarning = require("./ModuleWarning");
23
-
24
- const runLoaders = require("loader-runner").runLoaders;
25
- const getContext = require("loader-runner").getContext;
26
-
27
- const asString = buf => {
28
- if (Buffer.isBuffer(buf)) {
29
- return buf.toString("utf-8");
30
- }
31
- return buf;
32
- };
33
-
34
- const asBuffer = str => {
35
- if (!Buffer.isBuffer(str)) {
36
- return Buffer.from(str, "utf-8");
37
- }
38
- return str;
39
- };
40
-
41
- const contextify = (context, request) => {
42
- return request
43
- .split("!")
44
- .map(r => {
45
- const splitPath = r.split("?");
46
- splitPath[0] = path.relative(context, splitPath[0]);
47
- if (path.sep === "\\") splitPath[0] = splitPath[0].replace(/\\/g, "/");
48
- if (splitPath[0].indexOf("../") !== 0) splitPath[0] = "./" + splitPath[0];
49
- return splitPath.join("?");
50
- })
51
- .join("!");
52
- };
53
-
54
- class NonErrorEmittedError extends WebpackError {
55
- constructor(error) {
56
- super();
57
-
58
- this.name = "NonErrorEmittedError";
59
- this.message = "(Emitted value instead of an instance of Error) " + error;
60
-
61
- Error.captureStackTrace(this, this.constructor);
62
- }
63
- }
64
-
65
- const dependencyTemplatesHashMap = new WeakMap();
66
-
67
- class NormalModule extends Module {
68
- constructor({
69
- type,
70
- request,
71
- userRequest,
72
- rawRequest,
73
- loaders,
74
- resource,
75
- parser,
76
- generator,
77
- resolveOptions
78
- }) {
79
- super(type, getContext(resource));
80
-
81
- // Info from Factory
82
- this.request = request;
83
- this.userRequest = userRequest;
84
- this.rawRequest = rawRequest;
85
- this.binary = type.startsWith("webassembly");
86
- this.parser = parser;
87
- this.generator = generator;
88
- this.resource = resource;
89
- this.loaders = loaders;
90
- if (resolveOptions !== undefined) this.resolveOptions = resolveOptions;
91
-
92
- // Info from Build
93
- this.error = null;
94
- this._source = null;
95
- this.buildTimestamp = undefined;
96
- this._cachedSource = undefined;
97
- this._cachedSourceHash = undefined;
98
-
99
- // Options for the NormalModule set by plugins
100
- // TODO refactor this -> options object filled from Factory
101
- this.useSourceMap = false;
102
- this.lineToLine = false;
103
-
104
- // Cache
105
- this._lastSuccessfulBuildMeta = {};
106
- }
107
-
108
- identifier() {
109
- return this.request;
110
- }
111
-
112
- readableIdentifier(requestShortener) {
113
- return requestShortener.shorten(this.userRequest);
114
- }
115
-
116
- libIdent(options) {
117
- return contextify(options.context, this.userRequest);
118
- }
119
-
120
- nameForCondition() {
121
- const idx = this.resource.indexOf("?");
122
- if (idx >= 0) return this.resource.substr(0, idx);
123
- return this.resource;
124
- }
125
-
126
- createSourceForAsset(name, content, sourceMap) {
127
- if (!sourceMap) {
128
- return new RawSource(content);
129
- }
130
-
131
- if (typeof sourceMap === "string") {
132
- return new OriginalSource(content, sourceMap);
133
- }
134
-
135
- return new SourceMapSource(content, name, sourceMap);
136
- }
137
-
138
- createLoaderContext(resolver, options, compilation, fs) {
139
- const loaderContext = {
140
- version: 2,
141
- emitWarning: warning => {
142
- if (!(warning instanceof Error))
143
- warning = new NonErrorEmittedError(warning);
144
- this.warnings.push(new ModuleWarning(this, warning));
145
- },
146
- emitError: error => {
147
- if (!(error instanceof Error)) error = new NonErrorEmittedError(error);
148
- this.errors.push(new ModuleError(this, error));
149
- },
150
- exec: (code, filename) => {
151
- const module = new NativeModule(filename, this);
152
- module.paths = NativeModule._nodeModulePaths(this.context);
153
- module.filename = filename;
154
- module._compile(code, filename);
155
- return module.exports;
156
- },
157
- resolve(context, request, callback) {
158
- resolver.resolve({}, context, request, {}, callback);
159
- },
160
- emitFile: (name, content, sourceMap) => {
161
- if (!this.buildInfo.assets) this.buildInfo.assets = Object.create(null);
162
- this.buildInfo.assets[name] = this.createSourceForAsset(
163
- name,
164
- content,
165
- sourceMap
166
- );
167
- },
168
- rootContext: options.context,
169
- webpack: true,
170
- sourceMap: !!this.useSourceMap,
171
- _module: this,
172
- _compilation: compilation,
173
- _compiler: compilation.compiler,
174
- fs: fs
175
- };
176
-
177
- compilation.hooks.normalModuleLoader.call(loaderContext, this);
178
- if (options.loader) Object.assign(loaderContext, options.loader);
179
-
180
- return loaderContext;
181
- }
182
-
183
- createSource(source, resourceBuffer, sourceMap) {
184
- // if there is no identifier return raw source
185
- if (!this.identifier) {
186
- return new RawSource(source);
187
- }
188
-
189
- // from here on we assume we have an identifier
190
- const identifier = this.identifier();
191
-
192
- if (this.lineToLine && resourceBuffer) {
193
- return new LineToLineMappedSource(
194
- source,
195
- identifier,
196
- asString(resourceBuffer)
197
- );
198
- }
199
-
200
- if (this.useSourceMap && sourceMap) {
201
- return new SourceMapSource(source, identifier, sourceMap);
202
- }
203
-
204
- if (Buffer.isBuffer(source)) {
205
- return new RawSource(source);
206
- }
207
-
208
- return new OriginalSource(source, identifier);
209
- }
210
-
211
- doBuild(options, compilation, resolver, fs, callback) {
212
- const loaderContext = this.createLoaderContext(
213
- resolver,
214
- options,
215
- compilation,
216
- fs
217
- );
218
-
219
- runLoaders(
220
- {
221
- resource: this.resource,
222
- loaders: this.loaders,
223
- context: loaderContext,
224
- readResource: fs.readFile.bind(fs)
225
- },
226
- (err, result) => {
227
- if (result) {
228
- this.buildInfo.cacheable = result.cacheable;
229
- this.buildInfo.fileDependencies = new Set(result.fileDependencies);
230
- this.buildInfo.contextDependencies = new Set(
231
- result.contextDependencies
232
- );
233
- }
234
-
235
- if (err) {
236
- const error = new ModuleBuildError(this, err);
237
- return callback(error);
238
- }
239
-
240
- const resourceBuffer = result.resourceBuffer;
241
- const source = result.result[0];
242
- const sourceMap = result.result.length >= 1 ? result.result[1] : null;
243
- const extraInfo = result.result.length >= 2 ? result.result[2] : null;
244
-
245
- if (!Buffer.isBuffer(source) && typeof source !== "string") {
246
- const error = new ModuleBuildError(
247
- this,
248
- new Error("Final loader didn't return a Buffer or String")
249
- );
250
- return callback(error);
251
- }
252
-
253
- this._source = this.createSource(
254
- this.binary ? asBuffer(source) : asString(source),
255
- resourceBuffer,
256
- sourceMap
257
- );
258
- this._ast =
259
- typeof extraInfo === "object" &&
260
- extraInfo !== null &&
261
- extraInfo.webpackAST !== undefined
262
- ? extraInfo.webpackAST
263
- : null;
264
- return callback();
265
- }
266
- );
267
- }
268
-
269
- markModuleAsErrored(error) {
270
- // Restore build meta from successful build to keep importing state
271
- this.buildMeta = Object.assign({}, this._lastSuccessfulBuildMeta);
272
-
273
- this.error = error;
274
- this.errors.push(this.error);
275
- this._source = new RawSource(
276
- "throw new Error(" + JSON.stringify(this.error.message) + ");"
277
- );
278
- this._ast = null;
279
- }
280
-
281
- applyNoParseRule(rule, content) {
282
- // must start with "rule" if rule is a string
283
- if (typeof rule === "string") {
284
- return content.indexOf(rule) === 0;
285
- }
286
-
287
- if (typeof rule === "function") {
288
- return rule(content);
289
- }
290
- // we assume rule is a regexp
291
- return rule.test(content);
292
- }
293
-
294
- // check if module should not be parsed
295
- // returns "true" if the module should !not! be parsed
296
- // returns "false" if the module !must! be parsed
297
- shouldPreventParsing(noParseRule, request) {
298
- // if no noParseRule exists, return false
299
- // the module !must! be parsed.
300
- if (!noParseRule) {
301
- return false;
302
- }
303
-
304
- // we only have one rule to check
305
- if (!Array.isArray(noParseRule)) {
306
- // returns "true" if the module is !not! to be parsed
307
- return this.applyNoParseRule(noParseRule, request);
308
- }
309
-
310
- for (let i = 0; i < noParseRule.length; i++) {
311
- const rule = noParseRule[i];
312
- // early exit on first truthy match
313
- // this module is !not! to be parsed
314
- if (this.applyNoParseRule(rule, request)) {
315
- return true;
316
- }
317
- }
318
- // no match found, so this module !should! be parsed
319
- return false;
320
- }
321
-
322
- build(options, compilation, resolver, fs, callback) {
323
- this.buildTimestamp = Date.now();
324
- this.built = true;
325
- this._source = null;
326
- this._ast = null;
327
- this.error = null;
328
- this.errors.length = 0;
329
- this.warnings.length = 0;
330
- this.buildMeta = {};
331
- this.buildInfo = {
332
- cacheable: false,
333
- fileDependencies: new Set(),
334
- contextDependencies: new Set()
335
- };
336
-
337
- return this.doBuild(options, compilation, resolver, fs, err => {
338
- this._cachedSource = undefined;
339
- this._cachedSourceHash = undefined;
340
-
341
- // if we have an error mark module as failed and exit
342
- if (err) {
343
- this.markModuleAsErrored(err);
344
- return callback();
345
- }
346
-
347
- // check if this module should !not! be parsed.
348
- // if so, exit here;
349
- const noParseRule = options.module && options.module.noParse;
350
- if (this.shouldPreventParsing(noParseRule, this.request)) {
351
- return callback();
352
- }
353
-
354
- const handleParseError = e => {
355
- const source = this._source.source();
356
- const error = new ModuleParseError(this, source, e);
357
- this.markModuleAsErrored(error);
358
- return callback();
359
- };
360
-
361
- const handleParseResult = result => {
362
- this._lastSuccessfulBuildMeta = this.buildMeta;
363
- return callback();
364
- };
365
-
366
- try {
367
- const result = this.parser.parse(
368
- this._ast || this._source.source(),
369
- {
370
- current: this,
371
- module: this,
372
- compilation: compilation,
373
- options: options
374
- },
375
- (err, result) => {
376
- if (err) {
377
- handleParseError(err);
378
- } else {
379
- handleParseResult(result);
380
- }
381
- }
382
- );
383
- if (result !== undefined) {
384
- // parse is sync
385
- handleParseResult(result);
386
- }
387
- } catch (e) {
388
- handleParseError(e);
389
- }
390
- });
391
- }
392
-
393
- getHashDigest(dependencyTemplates) {
394
- let dtHash = dependencyTemplatesHashMap.get("hash");
395
- return `${this.hash}-${dtHash}`;
396
- }
397
-
398
- source(dependencyTemplates, runtimeTemplate) {
399
- const hashDigest = this.getHashDigest(dependencyTemplates);
400
- if (this._cachedSourceHash === hashDigest) {
401
- // We can reuse the cached source
402
- return this._cachedSource;
403
- }
404
-
405
- const source = this.generator.generate(
406
- this,
407
- dependencyTemplates,
408
- runtimeTemplate
409
- );
410
-
411
- const cachedSource = new CachedSource(source);
412
- this._cachedSource = cachedSource;
413
- this._cachedSourceHash = hashDigest;
414
- return cachedSource;
415
- }
416
-
417
- originalSource() {
418
- return this._source;
419
- }
420
-
421
- needRebuild(fileTimestamps, contextTimestamps) {
422
- // always try to rebuild in case of an error
423
- if (this.error) return true;
424
-
425
- // always rebuild when module is not cacheable
426
- if (!this.buildInfo.cacheable) return true;
427
-
428
- // Check timestamps of all dependencies
429
- // Missing timestamp -> need rebuild
430
- // Timestamp bigger than buildTimestamp -> need rebuild
431
- for (const file of this.buildInfo.fileDependencies) {
432
- const timestamp = fileTimestamps.get(file);
433
- if (!timestamp) return true;
434
- if (timestamp >= this.buildTimestamp) return true;
435
- }
436
- for (const file of this.buildInfo.contextDependencies) {
437
- const timestamp = contextTimestamps.get(file);
438
- if (!timestamp) return true;
439
- if (timestamp >= this.buildTimestamp) return true;
440
- }
441
- // elsewise -> no rebuild needed
442
- return false;
443
- }
444
-
445
- size() {
446
- return this._source ? this._source.size() : -1;
447
- }
448
-
449
- updateHashWithSource(hash) {
450
- if (!this._source) {
451
- hash.update("null");
452
- return;
453
- }
454
- hash.update("source");
455
- this._source.updateHash(hash);
456
- }
457
-
458
- updateHashWithMeta(hash) {
459
- hash.update("meta");
460
- hash.update(JSON.stringify(this.buildMeta));
461
- }
462
-
463
- updateHash(hash) {
464
- this.updateHashWithSource(hash);
465
- this.updateHashWithMeta(hash);
466
- super.updateHash(hash);
467
- }
468
- }
469
-
470
- module.exports = NormalModule;
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+ "use strict";
6
+
7
+ const path = require("path");
8
+ const NativeModule = require("module");
9
+
10
+ const {
11
+ CachedSource,
12
+ LineToLineMappedSource,
13
+ OriginalSource,
14
+ RawSource,
15
+ SourceMapSource
16
+ } = require("webpack-sources");
17
+ const { getContext, runLoaders } = require("loader-runner");
18
+
19
+ const WebpackError = require("./WebpackError");
20
+ const Module = require("./Module");
21
+ const ModuleParseError = require("./ModuleParseError");
22
+ const ModuleBuildError = require("./ModuleBuildError");
23
+ const ModuleError = require("./ModuleError");
24
+ const ModuleWarning = require("./ModuleWarning");
25
+
26
+ const asString = buf => {
27
+ if (Buffer.isBuffer(buf)) {
28
+ return buf.toString("utf-8");
29
+ }
30
+ return buf;
31
+ };
32
+
33
+ const asBuffer = str => {
34
+ if (!Buffer.isBuffer(str)) {
35
+ return Buffer.from(str, "utf-8");
36
+ }
37
+ return str;
38
+ };
39
+
40
+ const contextify = (context, request) => {
41
+ return request
42
+ .split("!")
43
+ .map(r => {
44
+ const splitPath = r.split("?");
45
+ splitPath[0] = path.relative(context, splitPath[0]);
46
+ if (path.sep === "\\") splitPath[0] = splitPath[0].replace(/\\/g, "/");
47
+ if (splitPath[0].indexOf("../") !== 0) splitPath[0] = "./" + splitPath[0];
48
+ return splitPath.join("?");
49
+ })
50
+ .join("!");
51
+ };
52
+
53
+ class NonErrorEmittedError extends WebpackError {
54
+ constructor(error) {
55
+ super();
56
+
57
+ this.name = "NonErrorEmittedError";
58
+ this.message = "(Emitted value instead of an instance of Error) " + error;
59
+
60
+ Error.captureStackTrace(this, this.constructor);
61
+ }
62
+ }
63
+
64
+ const dependencyTemplatesHashMap = new WeakMap();
65
+
66
+ class NormalModule extends Module {
67
+ constructor({
68
+ type,
69
+ request,
70
+ userRequest,
71
+ rawRequest,
72
+ loaders,
73
+ resource,
74
+ parser,
75
+ generator,
76
+ resolveOptions
77
+ }) {
78
+ super(type, getContext(resource));
79
+
80
+ // Info from Factory
81
+ this.request = request;
82
+ this.userRequest = userRequest;
83
+ this.rawRequest = rawRequest;
84
+ this.binary = type.startsWith("webassembly");
85
+ this.parser = parser;
86
+ this.generator = generator;
87
+ this.resource = resource;
88
+ this.loaders = loaders;
89
+ if (resolveOptions !== undefined) this.resolveOptions = resolveOptions;
90
+
91
+ // Info from Build
92
+ this.error = null;
93
+ this._source = null;
94
+ this.buildTimestamp = undefined;
95
+ this._cachedSource = undefined;
96
+ this._cachedSourceHash = undefined;
97
+
98
+ // Options for the NormalModule set by plugins
99
+ // TODO refactor this -> options object filled from Factory
100
+ this.useSourceMap = false;
101
+ this.lineToLine = false;
102
+
103
+ // Cache
104
+ this._lastSuccessfulBuildMeta = {};
105
+ }
106
+
107
+ identifier() {
108
+ return this.request;
109
+ }
110
+
111
+ readableIdentifier(requestShortener) {
112
+ return requestShortener.shorten(this.userRequest);
113
+ }
114
+
115
+ libIdent(options) {
116
+ return contextify(options.context, this.userRequest);
117
+ }
118
+
119
+ nameForCondition() {
120
+ const idx = this.resource.indexOf("?");
121
+ if (idx >= 0) return this.resource.substr(0, idx);
122
+ return this.resource;
123
+ }
124
+
125
+ updateCacheModule(module) {
126
+ this.userRequest = module.userRequest;
127
+ this.parser = module.parser;
128
+ this.generator = module.generator;
129
+ this.resource = module.resource;
130
+ this.loaders = module.loaders;
131
+ this.resolveOptions = module.resolveOptions;
132
+ }
133
+
134
+ createSourceForAsset(name, content, sourceMap) {
135
+ if (!sourceMap) {
136
+ return new RawSource(content);
137
+ }
138
+
139
+ if (typeof sourceMap === "string") {
140
+ return new OriginalSource(content, sourceMap);
141
+ }
142
+
143
+ return new SourceMapSource(content, name, sourceMap);
144
+ }
145
+
146
+ createLoaderContext(resolver, options, compilation, fs) {
147
+ const loaderContext = {
148
+ version: 2,
149
+ emitWarning: warning => {
150
+ if (!(warning instanceof Error))
151
+ warning = new NonErrorEmittedError(warning);
152
+ this.warnings.push(new ModuleWarning(this, warning));
153
+ },
154
+ emitError: error => {
155
+ if (!(error instanceof Error)) error = new NonErrorEmittedError(error);
156
+ this.errors.push(new ModuleError(this, error));
157
+ },
158
+ exec: (code, filename) => {
159
+ const module = new NativeModule(filename, this);
160
+ module.paths = NativeModule._nodeModulePaths(this.context);
161
+ module.filename = filename;
162
+ module._compile(code, filename);
163
+ return module.exports;
164
+ },
165
+ resolve(context, request, callback) {
166
+ resolver.resolve({}, context, request, {}, callback);
167
+ },
168
+ emitFile: (name, content, sourceMap) => {
169
+ if (!this.buildInfo.assets) this.buildInfo.assets = Object.create(null);
170
+ this.buildInfo.assets[name] = this.createSourceForAsset(
171
+ name,
172
+ content,
173
+ sourceMap
174
+ );
175
+ },
176
+ rootContext: options.context,
177
+ webpack: true,
178
+ sourceMap: !!this.useSourceMap,
179
+ _module: this,
180
+ _compilation: compilation,
181
+ _compiler: compilation.compiler,
182
+ fs: fs
183
+ };
184
+
185
+ compilation.hooks.normalModuleLoader.call(loaderContext, this);
186
+ if (options.loader) Object.assign(loaderContext, options.loader);
187
+
188
+ return loaderContext;
189
+ }
190
+
191
+ createSource(source, resourceBuffer, sourceMap) {
192
+ // if there is no identifier return raw source
193
+ if (!this.identifier) {
194
+ return new RawSource(source);
195
+ }
196
+
197
+ // from here on we assume we have an identifier
198
+ const identifier = this.identifier();
199
+
200
+ if (this.lineToLine && resourceBuffer) {
201
+ return new LineToLineMappedSource(
202
+ source,
203
+ identifier,
204
+ asString(resourceBuffer)
205
+ );
206
+ }
207
+
208
+ if (this.useSourceMap && sourceMap) {
209
+ return new SourceMapSource(source, identifier, sourceMap);
210
+ }
211
+
212
+ if (Buffer.isBuffer(source)) {
213
+ return new RawSource(source);
214
+ }
215
+
216
+ return new OriginalSource(source, identifier);
217
+ }
218
+
219
+ doBuild(options, compilation, resolver, fs, callback) {
220
+ const loaderContext = this.createLoaderContext(
221
+ resolver,
222
+ options,
223
+ compilation,
224
+ fs
225
+ );
226
+
227
+ runLoaders(
228
+ {
229
+ resource: this.resource,
230
+ loaders: this.loaders,
231
+ context: loaderContext,
232
+ readResource: fs.readFile.bind(fs)
233
+ },
234
+ (err, result) => {
235
+ if (result) {
236
+ this.buildInfo.cacheable = result.cacheable;
237
+ this.buildInfo.fileDependencies = new Set(result.fileDependencies);
238
+ this.buildInfo.contextDependencies = new Set(
239
+ result.contextDependencies
240
+ );
241
+ }
242
+
243
+ if (err) {
244
+ const error = new ModuleBuildError(this, err);
245
+ return callback(error);
246
+ }
247
+
248
+ const resourceBuffer = result.resourceBuffer;
249
+ const source = result.result[0];
250
+ const sourceMap = result.result.length >= 1 ? result.result[1] : null;
251
+ const extraInfo = result.result.length >= 2 ? result.result[2] : null;
252
+
253
+ if (!Buffer.isBuffer(source) && typeof source !== "string") {
254
+ const error = new ModuleBuildError(
255
+ this,
256
+ new Error("Final loader didn't return a Buffer or String")
257
+ );
258
+ return callback(error);
259
+ }
260
+
261
+ this._source = this.createSource(
262
+ this.binary ? asBuffer(source) : asString(source),
263
+ resourceBuffer,
264
+ sourceMap
265
+ );
266
+ this._ast =
267
+ typeof extraInfo === "object" &&
268
+ extraInfo !== null &&
269
+ extraInfo.webpackAST !== undefined
270
+ ? extraInfo.webpackAST
271
+ : null;
272
+ return callback();
273
+ }
274
+ );
275
+ }
276
+
277
+ markModuleAsErrored(error) {
278
+ // Restore build meta from successful build to keep importing state
279
+ this.buildMeta = Object.assign({}, this._lastSuccessfulBuildMeta);
280
+
281
+ this.error = error;
282
+ this.errors.push(this.error);
283
+ this._source = new RawSource(
284
+ "throw new Error(" + JSON.stringify(this.error.message) + ");"
285
+ );
286
+ this._ast = null;
287
+ }
288
+
289
+ applyNoParseRule(rule, content) {
290
+ // must start with "rule" if rule is a string
291
+ if (typeof rule === "string") {
292
+ return content.indexOf(rule) === 0;
293
+ }
294
+
295
+ if (typeof rule === "function") {
296
+ return rule(content);
297
+ }
298
+ // we assume rule is a regexp
299
+ return rule.test(content);
300
+ }
301
+
302
+ // check if module should not be parsed
303
+ // returns "true" if the module should !not! be parsed
304
+ // returns "false" if the module !must! be parsed
305
+ shouldPreventParsing(noParseRule, request) {
306
+ // if no noParseRule exists, return false
307
+ // the module !must! be parsed.
308
+ if (!noParseRule) {
309
+ return false;
310
+ }
311
+
312
+ // we only have one rule to check
313
+ if (!Array.isArray(noParseRule)) {
314
+ // returns "true" if the module is !not! to be parsed
315
+ return this.applyNoParseRule(noParseRule, request);
316
+ }
317
+
318
+ for (let i = 0; i < noParseRule.length; i++) {
319
+ const rule = noParseRule[i];
320
+ // early exit on first truthy match
321
+ // this module is !not! to be parsed
322
+ if (this.applyNoParseRule(rule, request)) {
323
+ return true;
324
+ }
325
+ }
326
+ // no match found, so this module !should! be parsed
327
+ return false;
328
+ }
329
+
330
+ build(options, compilation, resolver, fs, callback) {
331
+ this.buildTimestamp = Date.now();
332
+ this.built = true;
333
+ this._source = null;
334
+ this._ast = null;
335
+ this.error = null;
336
+ this.errors.length = 0;
337
+ this.warnings.length = 0;
338
+ this.buildMeta = {};
339
+ this.buildInfo = {
340
+ cacheable: false,
341
+ fileDependencies: new Set(),
342
+ contextDependencies: new Set()
343
+ };
344
+
345
+ return this.doBuild(options, compilation, resolver, fs, err => {
346
+ this._cachedSource = undefined;
347
+ this._cachedSourceHash = undefined;
348
+
349
+ // if we have an error mark module as failed and exit
350
+ if (err) {
351
+ this.markModuleAsErrored(err);
352
+ return callback();
353
+ }
354
+
355
+ // check if this module should !not! be parsed.
356
+ // if so, exit here;
357
+ const noParseRule = options.module && options.module.noParse;
358
+ if (this.shouldPreventParsing(noParseRule, this.request)) {
359
+ return callback();
360
+ }
361
+
362
+ const handleParseError = e => {
363
+ const source = this._source.source();
364
+ const error = new ModuleParseError(this, source, e);
365
+ this.markModuleAsErrored(error);
366
+ return callback();
367
+ };
368
+
369
+ const handleParseResult = result => {
370
+ this._lastSuccessfulBuildMeta = this.buildMeta;
371
+ return callback();
372
+ };
373
+
374
+ try {
375
+ const result = this.parser.parse(
376
+ this._ast || this._source.source(),
377
+ {
378
+ current: this,
379
+ module: this,
380
+ compilation: compilation,
381
+ options: options
382
+ },
383
+ (err, result) => {
384
+ if (err) {
385
+ handleParseError(err);
386
+ } else {
387
+ handleParseResult(result);
388
+ }
389
+ }
390
+ );
391
+ if (result !== undefined) {
392
+ // parse is sync
393
+ handleParseResult(result);
394
+ }
395
+ } catch (e) {
396
+ handleParseError(e);
397
+ }
398
+ });
399
+ }
400
+
401
+ getHashDigest(dependencyTemplates) {
402
+ let dtHash = dependencyTemplatesHashMap.get("hash");
403
+ return `${this.hash}-${dtHash}`;
404
+ }
405
+
406
+ source(dependencyTemplates, runtimeTemplate) {
407
+ const hashDigest = this.getHashDigest(dependencyTemplates);
408
+ if (this._cachedSourceHash === hashDigest) {
409
+ // We can reuse the cached source
410
+ return this._cachedSource;
411
+ }
412
+
413
+ const source = this.generator.generate(
414
+ this,
415
+ dependencyTemplates,
416
+ runtimeTemplate
417
+ );
418
+
419
+ const cachedSource = new CachedSource(source);
420
+ this._cachedSource = cachedSource;
421
+ this._cachedSourceHash = hashDigest;
422
+ return cachedSource;
423
+ }
424
+
425
+ originalSource() {
426
+ return this._source;
427
+ }
428
+
429
+ needRebuild(fileTimestamps, contextTimestamps) {
430
+ // always try to rebuild in case of an error
431
+ if (this.error) return true;
432
+
433
+ // always rebuild when module is not cacheable
434
+ if (!this.buildInfo.cacheable) return true;
435
+
436
+ // Check timestamps of all dependencies
437
+ // Missing timestamp -> need rebuild
438
+ // Timestamp bigger than buildTimestamp -> need rebuild
439
+ for (const file of this.buildInfo.fileDependencies) {
440
+ const timestamp = fileTimestamps.get(file);
441
+ if (!timestamp) return true;
442
+ if (timestamp >= this.buildTimestamp) return true;
443
+ }
444
+ for (const file of this.buildInfo.contextDependencies) {
445
+ const timestamp = contextTimestamps.get(file);
446
+ if (!timestamp) return true;
447
+ if (timestamp >= this.buildTimestamp) return true;
448
+ }
449
+ // elsewise -> no rebuild needed
450
+ return false;
451
+ }
452
+
453
+ size() {
454
+ return this._source ? this._source.size() : -1;
455
+ }
456
+
457
+ updateHashWithSource(hash) {
458
+ if (!this._source) {
459
+ hash.update("null");
460
+ return;
461
+ }
462
+ hash.update("source");
463
+ this._source.updateHash(hash);
464
+ }
465
+
466
+ updateHashWithMeta(hash) {
467
+ hash.update("meta");
468
+ hash.update(JSON.stringify(this.buildMeta));
469
+ }
470
+
471
+ updateHash(hash) {
472
+ this.updateHashWithSource(hash);
473
+ this.updateHashWithMeta(hash);
474
+ super.updateHash(hash);
475
+ }
476
+ }
477
+
478
+ module.exports = NormalModule;