@@ -2,6 +2,7 @@ const fs = require("node:fs");
22const path = require ( "node:path" ) ;
33const url = require ( "node:url" ) ;
44const puppeteer = require ( "puppeteer" ) ;
5+ const webpack = require ( "webpack" ) ;
56const BundleAnalyzerPlugin = require ( "../lib/BundleAnalyzerPlugin" ) ;
67const { isZstdSupported } = require ( "../src/sizeUtils" ) ;
78const {
@@ -95,26 +96,30 @@ describe("Plugin", () => {
9596 recursive : true ,
9697 } ) ;
9798 } ) ;
99+
100+ const NODE_MAJOR = Number . parseInt ( process . versions . node . split ( "." ) [ 0 ] , 10 ) ;
101+ const SKIP_WEBPACK_4 = NODE_MAJOR >= 20 ;
102+
103+ if ( ! SKIP_WEBPACK_4 ) {
104+ forEachWebpackVersion ( [ "4.44.2" ] , ( { it, webpackCompile } ) => {
105+ it ( "should support webpack config with custom `jsonpFunction` name" , async ( ) => {
106+ const config = makeWebpackConfig ( {
107+ multipleChunks : true ,
108+ } ) ;
98109
99- forEachWebpackVersion ( [ "4.44.2" ] , ( { it, webpackCompile } ) => {
100- // Webpack 5 doesn't support `jsonpFunction` option
101- it ( "should support webpack config with custom `jsonpFunction` name" , async ( ) => {
102- const config = makeWebpackConfig ( {
103- multipleChunks : true ,
104- } ) ;
105-
106- config . output . jsonpFunction = "somethingCompletelyDifferent" ;
110+ config . output . jsonpFunction = "somethingCompletelyDifferent" ;
107111
108- await webpackCompile ( config ) ;
112+ await webpackCompile ( config ) ;
109113
110- await expectValidReport ( {
111- parsedSize : 1349 ,
112- gzipSize : 358 ,
114+ await expectValidReport ( {
115+ parsedSize : 1349 ,
116+ gzipSize : 358 ,
117+ } ) ;
113118 } ) ;
114119 } ) ;
115- } ) ;
120+ }
116121
117- /* eslint jest/no-standalone-expect: ["error", { additionalTestBlockFunctions: ["forEachWebpackVersion"] }] */
122+ /* eslint jest/no-standalone-expect: ["error", { additionalTestBlockFunctions: ["forEachWebpackVersion", "runTest" ] }] */
118123 forEachWebpackVersion ( ( { it, webpackCompile } ) => {
119124 it ( "should allow to generate json report" , async ( ) => {
120125 const config = makeWebpackConfig ( {
@@ -182,7 +187,8 @@ describe("Plugin", () => {
182187 } ) ;
183188
184189 describe ( "reportTitle" , ( ) => {
185- it ( "should have a sensible default" , async ( ) => {
190+ const runTest = SKIP_WEBPACK_4 ? it . skip : it ;
191+ runTest ( "should have a sensible default" , async ( ) => {
186192 const config = makeWebpackConfig ( ) ;
187193 await webpackCompile ( config , "4.44.2" ) ;
188194 const generatedReportTitle = await getTitleFromReport ( ) ;
@@ -191,7 +197,7 @@ describe("Plugin", () => {
191197 ) ;
192198 } ) ;
193199
194- it ( "should support a string value" , async ( ) => {
200+ runTest ( "should support a string value" , async ( ) => {
195201 const reportTitle = "A string report title" ;
196202 const config = makeWebpackConfig ( {
197203 analyzerOpts : {
@@ -203,7 +209,7 @@ describe("Plugin", () => {
203209 expect ( generatedReportTitle ) . toBe ( reportTitle ) ;
204210 } ) ;
205211
206- it ( "should support a function value" , async ( ) => {
212+ runTest ( "should support a function value" , async ( ) => {
207213 const reportTitleResult = "A string report title" ;
208214 const config = makeWebpackConfig ( {
209215 analyzerOpts : {
@@ -215,7 +221,7 @@ describe("Plugin", () => {
215221 expect ( generatedReportTitle ) . toBe ( reportTitleResult ) ;
216222 } ) ;
217223
218- it ( "should propagate an error in a function " , async ( ) => {
224+ runTest ( "should log an error when reportTitle throws " , async ( ) => {
219225 const reportTitleError = new Error ( "test" ) ;
220226 const config = makeWebpackConfig ( {
221227 analyzerOpts : {
@@ -225,33 +231,36 @@ describe("Plugin", () => {
225231 } ,
226232 } ) ;
227233
228- let error = null ;
229- try {
230- await webpackCompile ( config , "4.44.2" ) ;
231- } catch ( err ) {
232- error = err ;
233- }
234+ const errorSpy = jest
235+ . spyOn ( console , "error" )
236+ . mockImplementation ( ( ) => { } ) ;
237+ await webpackCompile ( config , "4.44.2" ) ;
238+
239+ expect ( errorSpy ) . toHaveBeenCalledWith (
240+ expect . stringContaining ( "action failed: test" ) ,
241+ ) ;
234242
235- expect ( error ) . toBe ( reportTitleError ) ;
243+ errorSpy . mockRestore ( ) ;
236244 } ) ;
237245 } ) ;
238246
239247 describe ( "compressionAlgorithm" , ( ) => {
240- it ( "should default to gzip" , async ( ) => {
248+ const runTest = SKIP_WEBPACK_4 ? it . skip : it ;
249+ runTest ( "should default to gzip" , async ( ) => {
241250 const config = makeWebpackConfig ( { analyzerOpts : { } } ) ;
242251 await webpackCompile ( config , "4.44.2" ) ;
243252 await expectValidReport ( { parsedSize : 1317 , gzipSize : 341 } ) ;
244253 } ) ;
245254
246- it ( "should support gzip" , async ( ) => {
255+ runTest ( "should support gzip" , async ( ) => {
247256 const config = makeWebpackConfig ( {
248257 analyzerOpts : { compressionAlgorithm : "gzip" } ,
249258 } ) ;
250259 await webpackCompile ( config , "4.44.2" ) ;
251260 await expectValidReport ( { parsedSize : 1317 , gzipSize : 341 } ) ;
252261 } ) ;
253262
254- it ( "should support brotli" , async ( ) => {
263+ runTest ( "should support brotli" , async ( ) => {
255264 const config = makeWebpackConfig ( {
256265 analyzerOpts : { compressionAlgorithm : "brotli" } ,
257266 } ) ;
@@ -264,7 +273,7 @@ describe("Plugin", () => {
264273 } ) ;
265274
266275 if ( isZstdSupported ) {
267- it ( "should support zstd" , async ( ) => {
276+ runTest ( "should support zstd" , async ( ) => {
268277 const config = makeWebpackConfig ( {
269278 analyzerOpts : { compressionAlgorithm : "zstd" } ,
270279 } ) ;
@@ -279,4 +288,41 @@ describe("Plugin", () => {
279288 }
280289 } ) ;
281290 } ) ;
282- } ) ;
291+
292+ describe ( "Issue #499" , ( ) => {
293+ it ( "should not cause WebpackLogger 'done hook' error when callback throws" , ( done ) => {
294+ expect . assertions ( 1 ) ;
295+
296+ const compiler = webpack ( {
297+ mode : "development" ,
298+ entry : __filename ,
299+ plugins : [ new BundleAnalyzerPlugin ( { analyzerMode : "disabled" } ) ] ,
300+ } ) ;
301+
302+ let webpackLoggerError = false ;
303+ const originalConsoleError = console . error ;
304+
305+ console . error = ( ...args ) => {
306+ const message = args . join ( " " ) ;
307+ if ( message . includes ( "No such label 'done hook'" ) ) {
308+ webpackLoggerError = true ;
309+ }
310+ originalConsoleError . apply ( console , args ) ;
311+ } ;
312+
313+ compiler . run ( ( ) => {
314+ try {
315+ throw new Error ( "Intentional test error" ) ;
316+ } catch {
317+ // Swallow expected error
318+ }
319+ } ) ;
320+
321+ setTimeout ( ( ) => {
322+ console . error = originalConsoleError ;
323+ expect ( webpackLoggerError ) . toBe ( false ) ;
324+ done ( ) ;
325+ } , 1000 ) ;
326+ } ) ;
327+ } ) ;
328+ } ) ;
0 commit comments