| 
									
										
										
										
											2021-11-20 17:47:28 +08:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | require("./helpers/warmup-webpack"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const path = require("path"); | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | const { Volume, createFsFromVolume } = require("memfs"); | 
					
						
							| 
									
										
										
										
											2021-11-20 17:47:28 +08:00
										 |  |  | const webpack = require(".."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | jest.setTimeout(10000); | 
					
						
							| 
									
										
										
										
											2021-11-20 17:47:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | describe("Watch", () => { | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 	it("should only compile a single time", (done) => { | 
					
						
							| 
									
										
										
										
											2021-11-20 17:47:28 +08:00
										 |  |  | 		let counterBeforeCompile = 0; | 
					
						
							|  |  |  | 		let counterDone = 0; | 
					
						
							|  |  |  | 		let counterHandler = 0; | 
					
						
							|  |  |  | 		const compiler = webpack( | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				context: path.resolve(__dirname, "fixtures/watch"), | 
					
						
							|  |  |  | 				watch: true, | 
					
						
							|  |  |  | 				mode: "development", | 
					
						
							|  |  |  | 				snapshot: { | 
					
						
							|  |  |  | 					managedPaths: [/^(.+?[\\/]node_modules[\\/])/] | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				experiments: { | 
					
						
							|  |  |  | 					futureDefaults: true | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				module: { | 
					
						
							|  |  |  | 					// unsafeCache: false,
 | 
					
						
							|  |  |  | 					rules: [ | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							test: /\.js$/, | 
					
						
							|  |  |  | 							use: "some-loader" | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					] | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				plugins: [ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 					(c) => { | 
					
						
							| 
									
										
										
										
											2021-11-20 17:47:28 +08:00
										 |  |  | 						c.hooks.beforeCompile.tap("test", () => { | 
					
						
							|  |  |  | 							counterBeforeCompile++; | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 						c.hooks.done.tap("test", () => { | 
					
						
							|  |  |  | 							counterDone++; | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				] | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			(err, stats) => { | 
					
						
							|  |  |  | 				if (err) return done(err); | 
					
						
							|  |  |  | 				if (stats.hasErrors()) return done(new Error(stats.toString())); | 
					
						
							|  |  |  | 				counterHandler++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		compiler.outputFileSystem = createFsFromVolume(new Volume()); | 
					
						
							|  |  |  | 		setTimeout(() => { | 
					
						
							|  |  |  | 			expect(counterBeforeCompile).toBe(1); | 
					
						
							|  |  |  | 			expect(counterDone).toBe(1); | 
					
						
							|  |  |  | 			expect(counterHandler).toBe(1); | 
					
						
							|  |  |  | 			compiler.close(done); | 
					
						
							|  |  |  | 		}, 5000); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2025-08-04 23:09:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	it("should correctly emit asset when invalidation occurs again", (done) => { | 
					
						
							|  |  |  | 		function handleError(err) { | 
					
						
							|  |  |  | 			if (err) done(err); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		let calls = 0; | 
					
						
							|  |  |  | 		const compiler = webpack({ | 
					
						
							|  |  |  | 			mode: "development", | 
					
						
							|  |  |  | 			context: path.resolve(__dirname, "fixtures/watch"), | 
					
						
							|  |  |  | 			plugins: [ | 
					
						
							|  |  |  | 				(c) => { | 
					
						
							|  |  |  | 					// Ensure the second invalidation can occur during compiler running
 | 
					
						
							|  |  |  | 					let once = false; | 
					
						
							|  |  |  | 					c.hooks.afterCompile.tapAsync("LongTask", (_, cb) => { | 
					
						
							| 
									
										
										
										
											2025-08-24 18:50:59 +08:00
										 |  |  | 						if (once) return cb(); | 
					
						
							| 
									
										
										
										
											2025-08-04 23:09:45 +08:00
										 |  |  | 						once = true; | 
					
						
							|  |  |  | 						setTimeout(() => { | 
					
						
							|  |  |  | 							cb(); | 
					
						
							|  |  |  | 						}, 1000); | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				(c) => { | 
					
						
							|  |  |  | 					c.hooks.done.tap("Test", () => { | 
					
						
							|  |  |  | 						// Should emit assets twice, instead of once
 | 
					
						
							|  |  |  | 						expect(calls).toBe(2); | 
					
						
							|  |  |  | 						done(); | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			] | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		compiler.watch({}, handleError); | 
					
						
							|  |  |  | 		compiler.hooks.emit.tap("Test", () => { | 
					
						
							|  |  |  | 			calls++; | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// First invalidation
 | 
					
						
							|  |  |  | 		compiler.watching.invalidate(); | 
					
						
							|  |  |  | 		// Second invalidation while compiler is still running
 | 
					
						
							|  |  |  | 		setTimeout(() => { | 
					
						
							|  |  |  | 			compiler.watching.invalidate(); | 
					
						
							|  |  |  | 		}, 50); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2021-11-20 17:47:28 +08:00
										 |  |  | }); |