Projekt

Obecné

Profil

Stáhnout (21.1 KB) Statistiky
| Větev: | Revize:
1
/*
2
	MIT License http://www.opensource.org/licenses/mit-license.php
3
	Author Tobias Koppers @sokra
4
*/
5
"use strict";
6

    
7
const parseJson = require("json-parse-better-errors");
8
const asyncLib = require("neo-async");
9
const path = require("path");
10
const { Source } = require("webpack-sources");
11
const util = require("util");
12
const {
13
	Tapable,
14
	SyncHook,
15
	SyncBailHook,
16
	AsyncParallelHook,
17
	AsyncSeriesHook
18
} = require("tapable");
19

    
20
const Compilation = require("./Compilation");
21
const Stats = require("./Stats");
22
const Watching = require("./Watching");
23
const NormalModuleFactory = require("./NormalModuleFactory");
24
const ContextModuleFactory = require("./ContextModuleFactory");
25
const ResolverFactory = require("./ResolverFactory");
26

    
27
const RequestShortener = require("./RequestShortener");
28
const { makePathsRelative } = require("./util/identifier");
29
const ConcurrentCompilationError = require("./ConcurrentCompilationError");
30
const { Logger } = require("./logging/Logger");
31

    
32
/** @typedef {import("../declarations/WebpackOptions").Entry} Entry */
33
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
34

    
35
/**
36
 * @typedef {Object} CompilationParams
37
 * @property {NormalModuleFactory} normalModuleFactory
38
 * @property {ContextModuleFactory} contextModuleFactory
39
 * @property {Set<string>} compilationDependencies
40
 */
41

    
42
class Compiler extends Tapable {
43
	constructor(context) {
44
		super();
45
		this.hooks = {
46
			/** @type {SyncBailHook<Compilation>} */
47
			shouldEmit: new SyncBailHook(["compilation"]),
48
			/** @type {AsyncSeriesHook<Stats>} */
49
			done: new AsyncSeriesHook(["stats"]),
50
			/** @type {AsyncSeriesHook<>} */
51
			additionalPass: new AsyncSeriesHook([]),
52
			/** @type {AsyncSeriesHook<Compiler>} */
53
			beforeRun: new AsyncSeriesHook(["compiler"]),
54
			/** @type {AsyncSeriesHook<Compiler>} */
55
			run: new AsyncSeriesHook(["compiler"]),
56
			/** @type {AsyncSeriesHook<Compilation>} */
57
			emit: new AsyncSeriesHook(["compilation"]),
58
			/** @type {AsyncSeriesHook<string, Buffer>} */
59
			assetEmitted: new AsyncSeriesHook(["file", "content"]),
60
			/** @type {AsyncSeriesHook<Compilation>} */
61
			afterEmit: new AsyncSeriesHook(["compilation"]),
62

    
63
			/** @type {SyncHook<Compilation, CompilationParams>} */
64
			thisCompilation: new SyncHook(["compilation", "params"]),
65
			/** @type {SyncHook<Compilation, CompilationParams>} */
66
			compilation: new SyncHook(["compilation", "params"]),
67
			/** @type {SyncHook<NormalModuleFactory>} */
68
			normalModuleFactory: new SyncHook(["normalModuleFactory"]),
69
			/** @type {SyncHook<ContextModuleFactory>}  */
70
			contextModuleFactory: new SyncHook(["contextModulefactory"]),
71

    
72
			/** @type {AsyncSeriesHook<CompilationParams>} */
73
			beforeCompile: new AsyncSeriesHook(["params"]),
74
			/** @type {SyncHook<CompilationParams>} */
75
			compile: new SyncHook(["params"]),
76
			/** @type {AsyncParallelHook<Compilation>} */
77
			make: new AsyncParallelHook(["compilation"]),
78
			/** @type {AsyncSeriesHook<Compilation>} */
79
			afterCompile: new AsyncSeriesHook(["compilation"]),
80

    
81
			/** @type {AsyncSeriesHook<Compiler>} */
82
			watchRun: new AsyncSeriesHook(["compiler"]),
83
			/** @type {SyncHook<Error>} */
84
			failed: new SyncHook(["error"]),
85
			/** @type {SyncHook<string, string>} */
86
			invalid: new SyncHook(["filename", "changeTime"]),
87
			/** @type {SyncHook} */
88
			watchClose: new SyncHook([]),
89

    
90
			/** @type {SyncBailHook<string, string, any[]>} */
91
			infrastructureLog: new SyncBailHook(["origin", "type", "args"]),
92

    
93
			// TODO the following hooks are weirdly located here
94
			// TODO move them for webpack 5
95
			/** @type {SyncHook} */
96
			environment: new SyncHook([]),
97
			/** @type {SyncHook} */
98
			afterEnvironment: new SyncHook([]),
99
			/** @type {SyncHook<Compiler>} */
100
			afterPlugins: new SyncHook(["compiler"]),
101
			/** @type {SyncHook<Compiler>} */
102
			afterResolvers: new SyncHook(["compiler"]),
103
			/** @type {SyncBailHook<string, Entry>} */
104
			entryOption: new SyncBailHook(["context", "entry"])
105
		};
106
		// TODO webpack 5 remove this
107
		this.hooks.infrastructurelog = this.hooks.infrastructureLog;
108

    
109
		this._pluginCompat.tap("Compiler", options => {
110
			switch (options.name) {
111
				case "additional-pass":
112
				case "before-run":
113
				case "run":
114
				case "emit":
115
				case "after-emit":
116
				case "before-compile":
117
				case "make":
118
				case "after-compile":
119
				case "watch-run":
120
					options.async = true;
121
					break;
122
			}
123
		});
124

    
125
		/** @type {string=} */
126
		this.name = undefined;
127
		/** @type {Compilation=} */
128
		this.parentCompilation = undefined;
129
		/** @type {string} */
130
		this.outputPath = "";
131

    
132
		this.outputFileSystem = null;
133
		this.inputFileSystem = null;
134

    
135
		/** @type {string|null} */
136
		this.recordsInputPath = null;
137
		/** @type {string|null} */
138
		this.recordsOutputPath = null;
139
		this.records = {};
140
		this.removedFiles = new Set();
141
		/** @type {Map<string, number>} */
142
		this.fileTimestamps = new Map();
143
		/** @type {Map<string, number>} */
144
		this.contextTimestamps = new Map();
145
		/** @type {ResolverFactory} */
146
		this.resolverFactory = new ResolverFactory();
147

    
148
		this.infrastructureLogger = undefined;
149

    
150
		// TODO remove in webpack 5
151
		this.resolvers = {
152
			normal: {
153
				plugins: util.deprecate((hook, fn) => {
154
					this.resolverFactory.plugin("resolver normal", resolver => {
155
						resolver.plugin(hook, fn);
156
					});
157
				}, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n  resolver.plugin(/* … */);\n}); instead.'),
158
				apply: util.deprecate((...args) => {
159
					this.resolverFactory.plugin("resolver normal", resolver => {
160
						resolver.apply(...args);
161
					});
162
				}, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n  resolver.apply(/* … */);\n}); instead.')
163
			},
164
			loader: {
165
				plugins: util.deprecate((hook, fn) => {
166
					this.resolverFactory.plugin("resolver loader", resolver => {
167
						resolver.plugin(hook, fn);
168
					});
169
				}, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n  resolver.plugin(/* … */);\n}); instead.'),
170
				apply: util.deprecate((...args) => {
171
					this.resolverFactory.plugin("resolver loader", resolver => {
172
						resolver.apply(...args);
173
					});
174
				}, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n  resolver.apply(/* … */);\n}); instead.')
175
			},
176
			context: {
177
				plugins: util.deprecate((hook, fn) => {
178
					this.resolverFactory.plugin("resolver context", resolver => {
179
						resolver.plugin(hook, fn);
180
					});
181
				}, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n  resolver.plugin(/* … */);\n}); instead.'),
182
				apply: util.deprecate((...args) => {
183
					this.resolverFactory.plugin("resolver context", resolver => {
184
						resolver.apply(...args);
185
					});
186
				}, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n  resolver.apply(/* … */);\n}); instead.')
187
			}
188
		};
189

    
190
		/** @type {WebpackOptions} */
191
		this.options = /** @type {WebpackOptions} */ ({});
192

    
193
		this.context = context;
194

    
195
		this.requestShortener = new RequestShortener(context);
196

    
197
		/** @type {boolean} */
198
		this.running = false;
199

    
200
		/** @type {boolean} */
201
		this.watchMode = false;
202

    
203
		/** @private @type {WeakMap<Source, { sizeOnlySource: SizeOnlySource, writtenTo: Map<string, number> }>} */
204
		this._assetEmittingSourceCache = new WeakMap();
205
		/** @private @type {Map<string, number>} */
206
		this._assetEmittingWrittenFiles = new Map();
207
	}
208

    
209
	/**
210
	 * @param {string | (function(): string)} name name of the logger, or function called once to get the logger name
211
	 * @returns {Logger} a logger with that name
212
	 */
213
	getInfrastructureLogger(name) {
214
		if (!name) {
215
			throw new TypeError(
216
				"Compiler.getInfrastructureLogger(name) called without a name"
217
			);
218
		}
219
		return new Logger((type, args) => {
220
			if (typeof name === "function") {
221
				name = name();
222
				if (!name) {
223
					throw new TypeError(
224
						"Compiler.getInfrastructureLogger(name) called with a function not returning a name"
225
					);
226
				}
227
			}
228
			if (this.hooks.infrastructureLog.call(name, type, args) === undefined) {
229
				if (this.infrastructureLogger !== undefined) {
230
					this.infrastructureLogger(name, type, args);
231
				}
232
			}
233
		});
234
	}
235

    
236
	watch(watchOptions, handler) {
237
		if (this.running) return handler(new ConcurrentCompilationError());
238

    
239
		this.running = true;
240
		this.watchMode = true;
241
		this.fileTimestamps = new Map();
242
		this.contextTimestamps = new Map();
243
		this.removedFiles = new Set();
244
		return new Watching(this, watchOptions, handler);
245
	}
246

    
247
	run(callback) {
248
		if (this.running) return callback(new ConcurrentCompilationError());
249

    
250
		const finalCallback = (err, stats) => {
251
			this.running = false;
252

    
253
			if (err) {
254
				this.hooks.failed.call(err);
255
			}
256

    
257
			if (callback !== undefined) return callback(err, stats);
258
		};
259

    
260
		const startTime = Date.now();
261

    
262
		this.running = true;
263

    
264
		const onCompiled = (err, compilation) => {
265
			if (err) return finalCallback(err);
266

    
267
			if (this.hooks.shouldEmit.call(compilation) === false) {
268
				const stats = new Stats(compilation);
269
				stats.startTime = startTime;
270
				stats.endTime = Date.now();
271
				this.hooks.done.callAsync(stats, err => {
272
					if (err) return finalCallback(err);
273
					return finalCallback(null, stats);
274
				});
275
				return;
276
			}
277

    
278
			this.emitAssets(compilation, err => {
279
				if (err) return finalCallback(err);
280

    
281
				if (compilation.hooks.needAdditionalPass.call()) {
282
					compilation.needAdditionalPass = true;
283

    
284
					const stats = new Stats(compilation);
285
					stats.startTime = startTime;
286
					stats.endTime = Date.now();
287
					this.hooks.done.callAsync(stats, err => {
288
						if (err) return finalCallback(err);
289

    
290
						this.hooks.additionalPass.callAsync(err => {
291
							if (err) return finalCallback(err);
292
							this.compile(onCompiled);
293
						});
294
					});
295
					return;
296
				}
297

    
298
				this.emitRecords(err => {
299
					if (err) return finalCallback(err);
300

    
301
					const stats = new Stats(compilation);
302
					stats.startTime = startTime;
303
					stats.endTime = Date.now();
304
					this.hooks.done.callAsync(stats, err => {
305
						if (err) return finalCallback(err);
306
						return finalCallback(null, stats);
307
					});
308
				});
309
			});
310
		};
311

    
312
		this.hooks.beforeRun.callAsync(this, err => {
313
			if (err) return finalCallback(err);
314

    
315
			this.hooks.run.callAsync(this, err => {
316
				if (err) return finalCallback(err);
317

    
318
				this.readRecords(err => {
319
					if (err) return finalCallback(err);
320

    
321
					this.compile(onCompiled);
322
				});
323
			});
324
		});
325
	}
326

    
327
	runAsChild(callback) {
328
		this.compile((err, compilation) => {
329
			if (err) return callback(err);
330

    
331
			this.parentCompilation.children.push(compilation);
332
			for (const { name, source, info } of compilation.getAssets()) {
333
				this.parentCompilation.emitAsset(name, source, info);
334
			}
335

    
336
			const entries = Array.from(
337
				compilation.entrypoints.values(),
338
				ep => ep.chunks
339
			).reduce((array, chunks) => {
340
				return array.concat(chunks);
341
			}, []);
342

    
343
			return callback(null, entries, compilation);
344
		});
345
	}
346

    
347
	purgeInputFileSystem() {
348
		if (this.inputFileSystem && this.inputFileSystem.purge) {
349
			this.inputFileSystem.purge();
350
		}
351
	}
352

    
353
	emitAssets(compilation, callback) {
354
		let outputPath;
355
		const emitFiles = err => {
356
			if (err) return callback(err);
357

    
358
			asyncLib.forEachLimit(
359
				compilation.getAssets(),
360
				15,
361
				({ name: file, source }, callback) => {
362
					let targetFile = file;
363
					const queryStringIdx = targetFile.indexOf("?");
364
					if (queryStringIdx >= 0) {
365
						targetFile = targetFile.substr(0, queryStringIdx);
366
					}
367

    
368
					const writeOut = err => {
369
						if (err) return callback(err);
370
						const targetPath = this.outputFileSystem.join(
371
							outputPath,
372
							targetFile
373
						);
374
						// TODO webpack 5 remove futureEmitAssets option and make it on by default
375
						if (this.options.output.futureEmitAssets) {
376
							// check if the target file has already been written by this Compiler
377
							const targetFileGeneration = this._assetEmittingWrittenFiles.get(
378
								targetPath
379
							);
380

    
381
							// create an cache entry for this Source if not already existing
382
							let cacheEntry = this._assetEmittingSourceCache.get(source);
383
							if (cacheEntry === undefined) {
384
								cacheEntry = {
385
									sizeOnlySource: undefined,
386
									writtenTo: new Map()
387
								};
388
								this._assetEmittingSourceCache.set(source, cacheEntry);
389
							}
390

    
391
							// if the target file has already been written
392
							if (targetFileGeneration !== undefined) {
393
								// check if the Source has been written to this target file
394
								const writtenGeneration = cacheEntry.writtenTo.get(targetPath);
395
								if (writtenGeneration === targetFileGeneration) {
396
									// if yes, we skip writing the file
397
									// as it's already there
398
									// (we assume one doesn't remove files while the Compiler is running)
399

    
400
									compilation.updateAsset(file, cacheEntry.sizeOnlySource, {
401
										size: cacheEntry.sizeOnlySource.size()
402
									});
403

    
404
									return callback();
405
								}
406
							}
407

    
408
							// TODO webpack 5: if info.immutable check if file already exists in output
409
							// skip emitting if it's already there
410

    
411
							// get the binary (Buffer) content from the Source
412
							/** @type {Buffer} */
413
							let content;
414
							if (typeof source.buffer === "function") {
415
								content = source.buffer();
416
							} else {
417
								const bufferOrString = source.source();
418
								if (Buffer.isBuffer(bufferOrString)) {
419
									content = bufferOrString;
420
								} else {
421
									content = Buffer.from(bufferOrString, "utf8");
422
								}
423
							}
424

    
425
							// Create a replacement resource which only allows to ask for size
426
							// This allows to GC all memory allocated by the Source
427
							// (expect when the Source is stored in any other cache)
428
							cacheEntry.sizeOnlySource = new SizeOnlySource(content.length);
429
							compilation.updateAsset(file, cacheEntry.sizeOnlySource, {
430
								size: content.length
431
							});
432

    
433
							// Write the file to output file system
434
							this.outputFileSystem.writeFile(targetPath, content, err => {
435
								if (err) return callback(err);
436

    
437
								// information marker that the asset has been emitted
438
								compilation.emittedAssets.add(file);
439

    
440
								// cache the information that the Source has been written to that location
441
								const newGeneration =
442
									targetFileGeneration === undefined
443
										? 1
444
										: targetFileGeneration + 1;
445
								cacheEntry.writtenTo.set(targetPath, newGeneration);
446
								this._assetEmittingWrittenFiles.set(targetPath, newGeneration);
447
								this.hooks.assetEmitted.callAsync(file, content, callback);
448
							});
449
						} else {
450
							if (source.existsAt === targetPath) {
451
								source.emitted = false;
452
								return callback();
453
							}
454
							let content = source.source();
455

    
456
							if (!Buffer.isBuffer(content)) {
457
								content = Buffer.from(content, "utf8");
458
							}
459

    
460
							source.existsAt = targetPath;
461
							source.emitted = true;
462
							this.outputFileSystem.writeFile(targetPath, content, err => {
463
								if (err) return callback(err);
464
								this.hooks.assetEmitted.callAsync(file, content, callback);
465
							});
466
						}
467
					};
468

    
469
					if (targetFile.match(/\/|\\/)) {
470
						const dir = path.dirname(targetFile);
471
						this.outputFileSystem.mkdirp(
472
							this.outputFileSystem.join(outputPath, dir),
473
							writeOut
474
						);
475
					} else {
476
						writeOut();
477
					}
478
				},
479
				err => {
480
					if (err) return callback(err);
481

    
482
					this.hooks.afterEmit.callAsync(compilation, err => {
483
						if (err) return callback(err);
484

    
485
						return callback();
486
					});
487
				}
488
			);
489
		};
490

    
491
		this.hooks.emit.callAsync(compilation, err => {
492
			if (err) return callback(err);
493
			outputPath = compilation.getPath(this.outputPath);
494
			this.outputFileSystem.mkdirp(outputPath, emitFiles);
495
		});
496
	}
497

    
498
	emitRecords(callback) {
499
		if (!this.recordsOutputPath) return callback();
500
		const idx1 = this.recordsOutputPath.lastIndexOf("/");
501
		const idx2 = this.recordsOutputPath.lastIndexOf("\\");
502
		let recordsOutputPathDirectory = null;
503
		if (idx1 > idx2) {
504
			recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1);
505
		} else if (idx1 < idx2) {
506
			recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2);
507
		}
508

    
509
		const writeFile = () => {
510
			this.outputFileSystem.writeFile(
511
				this.recordsOutputPath,
512
				JSON.stringify(this.records, undefined, 2),
513
				callback
514
			);
515
		};
516

    
517
		if (!recordsOutputPathDirectory) {
518
			return writeFile();
519
		}
520
		this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => {
521
			if (err) return callback(err);
522
			writeFile();
523
		});
524
	}
525

    
526
	readRecords(callback) {
527
		if (!this.recordsInputPath) {
528
			this.records = {};
529
			return callback();
530
		}
531
		this.inputFileSystem.stat(this.recordsInputPath, err => {
532
			// It doesn't exist
533
			// We can ignore this.
534
			if (err) return callback();
535

    
536
			this.inputFileSystem.readFile(this.recordsInputPath, (err, content) => {
537
				if (err) return callback(err);
538

    
539
				try {
540
					this.records = parseJson(content.toString("utf-8"));
541
				} catch (e) {
542
					e.message = "Cannot parse records: " + e.message;
543
					return callback(e);
544
				}
545

    
546
				return callback();
547
			});
548
		});
549
	}
550

    
551
	createChildCompiler(
552
		compilation,
553
		compilerName,
554
		compilerIndex,
555
		outputOptions,
556
		plugins
557
	) {
558
		const childCompiler = new Compiler(this.context);
559
		if (Array.isArray(plugins)) {
560
			for (const plugin of plugins) {
561
				plugin.apply(childCompiler);
562
			}
563
		}
564
		for (const name in this.hooks) {
565
			if (
566
				![
567
					"make",
568
					"compile",
569
					"emit",
570
					"afterEmit",
571
					"invalid",
572
					"done",
573
					"thisCompilation"
574
				].includes(name)
575
			) {
576
				if (childCompiler.hooks[name]) {
577
					childCompiler.hooks[name].taps = this.hooks[name].taps.slice();
578
				}
579
			}
580
		}
581
		childCompiler.name = compilerName;
582
		childCompiler.outputPath = this.outputPath;
583
		childCompiler.inputFileSystem = this.inputFileSystem;
584
		childCompiler.outputFileSystem = null;
585
		childCompiler.resolverFactory = this.resolverFactory;
586
		childCompiler.fileTimestamps = this.fileTimestamps;
587
		childCompiler.contextTimestamps = this.contextTimestamps;
588

    
589
		const relativeCompilerName = makePathsRelative(this.context, compilerName);
590
		if (!this.records[relativeCompilerName]) {
591
			this.records[relativeCompilerName] = [];
592
		}
593
		if (this.records[relativeCompilerName][compilerIndex]) {
594
			childCompiler.records = this.records[relativeCompilerName][compilerIndex];
595
		} else {
596
			this.records[relativeCompilerName].push((childCompiler.records = {}));
597
		}
598

    
599
		childCompiler.options = Object.create(this.options);
600
		childCompiler.options.output = Object.create(childCompiler.options.output);
601
		for (const name in outputOptions) {
602
			childCompiler.options.output[name] = outputOptions[name];
603
		}
604
		childCompiler.parentCompilation = compilation;
605

    
606
		compilation.hooks.childCompiler.call(
607
			childCompiler,
608
			compilerName,
609
			compilerIndex
610
		);
611

    
612
		return childCompiler;
613
	}
614

    
615
	isChild() {
616
		return !!this.parentCompilation;
617
	}
618

    
619
	createCompilation() {
620
		return new Compilation(this);
621
	}
622

    
623
	newCompilation(params) {
624
		const compilation = this.createCompilation();
625
		compilation.fileTimestamps = this.fileTimestamps;
626
		compilation.contextTimestamps = this.contextTimestamps;
627
		compilation.name = this.name;
628
		compilation.records = this.records;
629
		compilation.compilationDependencies = params.compilationDependencies;
630
		this.hooks.thisCompilation.call(compilation, params);
631
		this.hooks.compilation.call(compilation, params);
632
		return compilation;
633
	}
634

    
635
	createNormalModuleFactory() {
636
		const normalModuleFactory = new NormalModuleFactory(
637
			this.options.context,
638
			this.resolverFactory,
639
			this.options.module || {}
640
		);
641
		this.hooks.normalModuleFactory.call(normalModuleFactory);
642
		return normalModuleFactory;
643
	}
644

    
645
	createContextModuleFactory() {
646
		const contextModuleFactory = new ContextModuleFactory(this.resolverFactory);
647
		this.hooks.contextModuleFactory.call(contextModuleFactory);
648
		return contextModuleFactory;
649
	}
650

    
651
	newCompilationParams() {
652
		const params = {
653
			normalModuleFactory: this.createNormalModuleFactory(),
654
			contextModuleFactory: this.createContextModuleFactory(),
655
			compilationDependencies: new Set()
656
		};
657
		return params;
658
	}
659

    
660
	compile(callback) {
661
		const params = this.newCompilationParams();
662
		this.hooks.beforeCompile.callAsync(params, err => {
663
			if (err) return callback(err);
664

    
665
			this.hooks.compile.call(params);
666

    
667
			const compilation = this.newCompilation(params);
668

    
669
			this.hooks.make.callAsync(compilation, err => {
670
				if (err) return callback(err);
671

    
672
				compilation.finish(err => {
673
					if (err) return callback(err);
674

    
675
					compilation.seal(err => {
676
						if (err) return callback(err);
677

    
678
						this.hooks.afterCompile.callAsync(compilation, err => {
679
							if (err) return callback(err);
680

    
681
							return callback(null, compilation);
682
						});
683
					});
684
				});
685
			});
686
		});
687
	}
688
}
689

    
690
module.exports = Compiler;
691

    
692
class SizeOnlySource extends Source {
693
	constructor(size) {
694
		super();
695
		this._size = size;
696
	}
697

    
698
	_error() {
699
		return new Error(
700
			"Content and Map of this Source is no longer available (only size() is supported)"
701
		);
702
	}
703

    
704
	size() {
705
		return this._size;
706
	}
707

    
708
	/**
709
	 * @param {any} options options
710
	 * @returns {string} the source
711
	 */
712
	source(options) {
713
		throw this._error();
714
	}
715

    
716
	node() {
717
		throw this._error();
718
	}
719

    
720
	listMap() {
721
		throw this._error();
722
	}
723

    
724
	map() {
725
		throw this._error();
726
	}
727

    
728
	listNode() {
729
		throw this._error();
730
	}
731

    
732
	updateHash() {
733
		throw this._error();
734
	}
735
}
(18-18/144)