From edb8889dce54e31e8aadd9259bd39031bd1c493b Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Thu, 12 Sep 2024 17:08:38 +0100 Subject: [PATCH 01/10] Add tests for cyclical dependencies --- .../test/__snapshots__/build.js.snap | 14 ++++++++++++++ .../test/fixtures/cyclic-deps/a.js | 8 ++++++++ .../test/fixtures/cyclic-deps/index.js | 8 ++++++++ .../test/fixtures/cyclic-deps/webpack.config.js | 8 ++++++++ 4 files changed, 38 insertions(+) create mode 100644 packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/a.js create mode 100644 packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/index.js create mode 100644 packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/webpack.config.js diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index d3090daa89a476..c46acb8048f189 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -40,6 +40,13 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dependency-g ] `; +exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +" array(), 'version' => '659ee86bae9fb389a844', 'type' => 'module'); +" +`; + +exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-deps\` should produce expected output: External modules should match snapshot 1`] = `[]`; + exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` " array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => '293aebad4ca761cf396f', 'type' => 'module'); " @@ -394,6 +401,13 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dependency-g ] `; +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +" array(), 'version' => '174bed1cc91890a295ff'); +" +`; + +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-deps\` should produce expected output: External modules should match snapshot 1`] = `[]`; + exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` " array('wp-interactivity'), 'version' => 'ac0e2f1bcd3a6a0e7aff'); " diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/a.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/a.js new file mode 100644 index 00000000000000..1f0edffe27efd3 --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/a.js @@ -0,0 +1,8 @@ +/** + * Internal dependencies + */ +import { someFunction } from '.'; + +someFunction(); + +export const a = 'test'; diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/index.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/index.js new file mode 100644 index 00000000000000..603196339983e9 --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/index.js @@ -0,0 +1,8 @@ +/** + * Internal dependencies + */ +import { a } from './a'; + +export const someFunction = () => { + return a; +}; diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/webpack.config.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/webpack.config.js new file mode 100644 index 00000000000000..bfffff3ae78319 --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/webpack.config.js @@ -0,0 +1,8 @@ +/** + * Internal dependencies + */ +const DependencyExtractionWebpackPlugin = require( '../../..' ); + +module.exports = { + plugins: [ new DependencyExtractionWebpackPlugin() ], +}; From 67d06763750b6ca8600503e74d9fb202d226eb95 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Mon, 16 Sep 2024 13:14:20 +0100 Subject: [PATCH 02/10] Add the externals and make the test fail --- .../test/__snapshots__/build.js.snap | 22 +++++++++++-------- .../test/fixtures/cyclic-deps/index.js | 10 +++++++++ .../fixtures/cyclic-deps/webpack.config.js | 8 ++++++- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index c46acb8048f189..3ab48ffebd3dc7 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -40,13 +40,6 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dependency-g ] `; -exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -" array(), 'version' => '659ee86bae9fb389a844', 'type' => 'module'); -" -`; - -exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-deps\` should produce expected output: External modules should match snapshot 1`] = `[]`; - exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` " array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => '293aebad4ca761cf396f', 'type' => 'module'); " @@ -402,11 +395,22 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dependency-g `; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -" array(), 'version' => '174bed1cc91890a295ff'); +" array('wp-interactivity'), 'version' => '455f3cab924853d41b8b'); " `; -exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-deps\` should produce expected output: External modules should match snapshot 1`] = `[]`; +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-deps\` should produce expected output: External modules should match snapshot 1`] = ` +[ + { + "externalType": "window", + "request": [ + "wp", + "interactivity", + ], + "userRequest": "@wordpress/interactivity", + }, +] +`; exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` " array('wp-interactivity'), 'version' => 'ac0e2f1bcd3a6a0e7aff'); diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/index.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/index.js index 603196339983e9..01d7eff466bfbd 100644 --- a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/index.js +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/index.js @@ -3,6 +3,16 @@ */ import { a } from './a'; +/** + * WordPress dependencies + */ +import { store } from '@wordpress/interactivity'; + export const someFunction = () => { + store( 'test', { + state: { + a, + }, + } ); return a; }; diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/webpack.config.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/webpack.config.js index bfffff3ae78319..59d4c5d2ead3ab 100644 --- a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/webpack.config.js +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/webpack.config.js @@ -4,5 +4,11 @@ const DependencyExtractionWebpackPlugin = require( '../../..' ); module.exports = { - plugins: [ new DependencyExtractionWebpackPlugin() ], + plugins: [ + new DependencyExtractionWebpackPlugin( { + requestToExternalModule( request ) { + return request.startsWith( '@wordpress/' ); + }, + } ), + ], }; From 8fd700f3ec475a0256e2d941e68e0a89491871e3 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Mon, 16 Sep 2024 14:57:17 +0100 Subject: [PATCH 03/10] Add cycle detection in dependency path checking Enhanced the dependency resolution logic to detect cycles in the module graph, preventing infinite loops during static dependency path checks. Introduced a Set to track visited blocks and avoid revisiting them. --- .../lib/index.js | 40 ++++++++++++++----- .../test/__snapshots__/build.js.snap | 27 ++++++++++--- .../a.js | 0 .../index.js | 0 .../webpack.config.js | 0 5 files changed, 52 insertions(+), 15 deletions(-) rename packages/dependency-extraction-webpack-plugin/test/fixtures/{cyclic-deps => cyclic-external-deps}/a.js (100%) rename packages/dependency-extraction-webpack-plugin/test/fixtures/{cyclic-deps => cyclic-external-deps}/index.js (100%) rename packages/dependency-extraction-webpack-plugin/test/fixtures/{cyclic-deps => cyclic-external-deps}/webpack.config.js (100%) diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index 0e6f8a5fbc6ccc..1b90285579338f 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -352,12 +352,25 @@ class DependencyExtractionWebpackPlugin { /** * Can we trace a line of static dependencies from an entry to a module * - * @param {webpack.Compilation} compilation - * @param {webpack.DependenciesBlock} block + * @param {webpack.Compilation} compilation + * @param {webpack.DependenciesBlock} block + * @param {Set} visited * * @return {boolean} True if there is a static import path to the root */ - static hasStaticDependencyPathToRoot( compilation, block ) { + static hasStaticDependencyPathToRoot( + compilation, + block, + visited = new Set() + ) { + // If we've already visited this block, we're in a cycle + if ( visited.has( block ) ) { + return false; + } + + // Add the current block to the visited set + visited.add( block ); + const incomingConnections = [ ...compilation.moduleGraph.getIncomingConnections( block ), ].filter( @@ -369,8 +382,9 @@ class DependencyExtractionWebpackPlugin { ); // If we don't have non-entry, non-library incoming connections, - // we've reached a root of + // we've reached a root if ( ! incomingConnections.length ) { + visited.delete( block ); return true; } @@ -389,16 +403,24 @@ class DependencyExtractionWebpackPlugin { // All the dependencies were Async, the module was reached via a dynamic import if ( ! staticDependentModules.length ) { + visited.delete( block ); return false; } // Continue to explore any static dependencies - return staticDependentModules.some( ( parentStaticDependentModule ) => - DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( - compilation, - parentStaticDependentModule - ) + const result = staticDependentModules.some( + ( parentStaticDependentModule ) => + DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( + compilation, + parentStaticDependentModule, + visited + ) ); + + // Remove the current block from the visited set before returning + visited.delete( block ); + + return result; } } diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index 3ab48ffebd3dc7..80893ec4027c05 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -55,6 +55,21 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dynamic-depe ] `; +exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-external-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +" array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => '59584257c15ebb59974d', 'type' => 'module'); +" +`; + +exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-external-deps\` should produce expected output: External modules should match snapshot 1`] = ` +[ + { + "externalType": "import", + "request": "@wordpress/interactivity", + "userRequest": "@wordpress/interactivity", + }, +] +`; + exports[`DependencyExtractionWebpackPlugin modules Webpack \`dynamic-import\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` " array(array('id' => '@wordpress/blob', 'import' => 'dynamic')), 'version' => '4f59b7847b70a07b2710', 'type' => 'module'); " @@ -394,12 +409,12 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dependency-g ] `; -exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -" array('wp-interactivity'), 'version' => '455f3cab924853d41b8b'); +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +" array('wp-interactivity'), 'version' => 'ac0e2f1bcd3a6a0e7aff'); " `; -exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-deps\` should produce expected output: External modules should match snapshot 1`] = ` +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: External modules should match snapshot 1`] = ` [ { "externalType": "window", @@ -412,12 +427,12 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-deps\` shoul ] `; -exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -" array('wp-interactivity'), 'version' => 'ac0e2f1bcd3a6a0e7aff'); +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-external-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +" array('wp-interactivity'), 'version' => '455f3cab924853d41b8b'); " `; -exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-dynamic-dependency-graph\` should produce expected output: External modules should match snapshot 1`] = ` +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`cyclic-external-deps\` should produce expected output: External modules should match snapshot 1`] = ` [ { "externalType": "window", diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/a.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/a.js similarity index 100% rename from packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/a.js rename to packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/a.js diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/index.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/index.js similarity index 100% rename from packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/index.js rename to packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/index.js diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/webpack.config.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js similarity index 100% rename from packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-deps/webpack.config.js rename to packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js From 565481312eed1a4d0544f60f82e37a9e99859303 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 16 Sep 2024 18:07:05 +0200 Subject: [PATCH 04/10] Revert changes --- .../lib/index.js | 40 +++++-------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index 1b90285579338f..0e6f8a5fbc6ccc 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -352,25 +352,12 @@ class DependencyExtractionWebpackPlugin { /** * Can we trace a line of static dependencies from an entry to a module * - * @param {webpack.Compilation} compilation - * @param {webpack.DependenciesBlock} block - * @param {Set} visited + * @param {webpack.Compilation} compilation + * @param {webpack.DependenciesBlock} block * * @return {boolean} True if there is a static import path to the root */ - static hasStaticDependencyPathToRoot( - compilation, - block, - visited = new Set() - ) { - // If we've already visited this block, we're in a cycle - if ( visited.has( block ) ) { - return false; - } - - // Add the current block to the visited set - visited.add( block ); - + static hasStaticDependencyPathToRoot( compilation, block ) { const incomingConnections = [ ...compilation.moduleGraph.getIncomingConnections( block ), ].filter( @@ -382,9 +369,8 @@ class DependencyExtractionWebpackPlugin { ); // If we don't have non-entry, non-library incoming connections, - // we've reached a root + // we've reached a root of if ( ! incomingConnections.length ) { - visited.delete( block ); return true; } @@ -403,24 +389,16 @@ class DependencyExtractionWebpackPlugin { // All the dependencies were Async, the module was reached via a dynamic import if ( ! staticDependentModules.length ) { - visited.delete( block ); return false; } // Continue to explore any static dependencies - const result = staticDependentModules.some( - ( parentStaticDependentModule ) => - DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( - compilation, - parentStaticDependentModule, - visited - ) + return staticDependentModules.some( ( parentStaticDependentModule ) => + DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( + compilation, + parentStaticDependentModule + ) ); - - // Remove the current block from the visited set before returning - visited.delete( block ); - - return result; } } From b19c3e0b0a6c873c9ecb75a5360f63f92130da13 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 16 Sep 2024 18:16:41 +0200 Subject: [PATCH 05/10] Propose static WeakSet/WeakMap implementation. --- .../lib/index.js | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index 0e6f8a5fbc6ccc..7fb904427b9ae7 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -349,6 +349,9 @@ class DependencyExtractionWebpackPlugin { } } + static #staticDepsCurrent = new WeakSet(); + static #staticDepsCache = new WeakMap(); + /** * Can we trace a line of static dependencies from an entry to a module * @@ -358,6 +361,20 @@ class DependencyExtractionWebpackPlugin { * @return {boolean} True if there is a static import path to the root */ static hasStaticDependencyPathToRoot( compilation, block ) { + if ( DependencyExtractionWebpackPlugin.#staticDepsCache.has( block ) ) { + return DependencyExtractionWebpackPlugin.#staticDepsCache.get( + block + ); + } + + if ( + DependencyExtractionWebpackPlugin.#staticDepsCurrent.has( block ) + ) { + return false; + } + + DependencyExtractionWebpackPlugin.#staticDepsCurrent.add( block ); + const incomingConnections = [ ...compilation.moduleGraph.getIncomingConnections( block ), ].filter( @@ -371,6 +388,13 @@ class DependencyExtractionWebpackPlugin { // If we don't have non-entry, non-library incoming connections, // we've reached a root of if ( ! incomingConnections.length ) { + DependencyExtractionWebpackPlugin.#staticDepsCache.set( + block, + true + ); + DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( + block + ); return true; } @@ -389,16 +413,28 @@ class DependencyExtractionWebpackPlugin { // All the dependencies were Async, the module was reached via a dynamic import if ( ! staticDependentModules.length ) { + DependencyExtractionWebpackPlugin.#staticDepsCache.set( + block, + false + ); + DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( + block + ); return false; } // Continue to explore any static dependencies - return staticDependentModules.some( ( parentStaticDependentModule ) => - DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( - compilation, - parentStaticDependentModule - ) + const result = staticDependentModules.some( + ( parentStaticDependentModule ) => + DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( + compilation, + parentStaticDependentModule + ) ); + + DependencyExtractionWebpackPlugin.#staticDepsCache.set( block, result ); + DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( block ); + return result; } } From 3f8f2f411b28a661627fb27572d2cc20062f2262 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 16 Sep 2024 18:18:19 +0200 Subject: [PATCH 06/10] Add CHANGELOG entry --- packages/dependency-extraction-webpack-plugin/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 1da5f074301fd6..f49a4ae6607fcd 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Fix a bug where cycles in dependent modules could enter infinite recursion ([#65291](https://github.com/WordPress/gutenberg/pull/65291)). + ## 6.7.0 (2024-09-05) ## 6.6.0 (2024-08-21) From b5e33dbc0e6db4d4aab07de4d52b42ae6b9672ee Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 16 Sep 2024 18:19:32 +0200 Subject: [PATCH 07/10] Remove redundant plugin config in test --- .../lib/index.js | 46 ++----------------- .../cyclic-external-deps/webpack.config.js | 8 +--- 2 files changed, 6 insertions(+), 48 deletions(-) diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index 7fb904427b9ae7..0e6f8a5fbc6ccc 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -349,9 +349,6 @@ class DependencyExtractionWebpackPlugin { } } - static #staticDepsCurrent = new WeakSet(); - static #staticDepsCache = new WeakMap(); - /** * Can we trace a line of static dependencies from an entry to a module * @@ -361,20 +358,6 @@ class DependencyExtractionWebpackPlugin { * @return {boolean} True if there is a static import path to the root */ static hasStaticDependencyPathToRoot( compilation, block ) { - if ( DependencyExtractionWebpackPlugin.#staticDepsCache.has( block ) ) { - return DependencyExtractionWebpackPlugin.#staticDepsCache.get( - block - ); - } - - if ( - DependencyExtractionWebpackPlugin.#staticDepsCurrent.has( block ) - ) { - return false; - } - - DependencyExtractionWebpackPlugin.#staticDepsCurrent.add( block ); - const incomingConnections = [ ...compilation.moduleGraph.getIncomingConnections( block ), ].filter( @@ -388,13 +371,6 @@ class DependencyExtractionWebpackPlugin { // If we don't have non-entry, non-library incoming connections, // we've reached a root of if ( ! incomingConnections.length ) { - DependencyExtractionWebpackPlugin.#staticDepsCache.set( - block, - true - ); - DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( - block - ); return true; } @@ -413,28 +389,16 @@ class DependencyExtractionWebpackPlugin { // All the dependencies were Async, the module was reached via a dynamic import if ( ! staticDependentModules.length ) { - DependencyExtractionWebpackPlugin.#staticDepsCache.set( - block, - false - ); - DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( - block - ); return false; } // Continue to explore any static dependencies - const result = staticDependentModules.some( - ( parentStaticDependentModule ) => - DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( - compilation, - parentStaticDependentModule - ) + return staticDependentModules.some( ( parentStaticDependentModule ) => + DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( + compilation, + parentStaticDependentModule + ) ); - - DependencyExtractionWebpackPlugin.#staticDepsCache.set( block, result ); - DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( block ); - return result; } } diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js index 59d4c5d2ead3ab..bfffff3ae78319 100644 --- a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js @@ -4,11 +4,5 @@ const DependencyExtractionWebpackPlugin = require( '../../..' ); module.exports = { - plugins: [ - new DependencyExtractionWebpackPlugin( { - requestToExternalModule( request ) { - return request.startsWith( '@wordpress/' ); - }, - } ), - ], + plugins: [ new DependencyExtractionWebpackPlugin() ], }; From 44d6968fe3c29c8bca98e35ca1ff4d80554f7fb3 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 16 Sep 2024 18:20:47 +0200 Subject: [PATCH 08/10] Revert "Remove redundant plugin config in test" This reverts commit b5e33dbc0e6db4d4aab07de4d52b42ae6b9672ee. --- .../lib/index.js | 46 +++++++++++++++++-- .../cyclic-external-deps/webpack.config.js | 8 +++- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index 0e6f8a5fbc6ccc..7fb904427b9ae7 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -349,6 +349,9 @@ class DependencyExtractionWebpackPlugin { } } + static #staticDepsCurrent = new WeakSet(); + static #staticDepsCache = new WeakMap(); + /** * Can we trace a line of static dependencies from an entry to a module * @@ -358,6 +361,20 @@ class DependencyExtractionWebpackPlugin { * @return {boolean} True if there is a static import path to the root */ static hasStaticDependencyPathToRoot( compilation, block ) { + if ( DependencyExtractionWebpackPlugin.#staticDepsCache.has( block ) ) { + return DependencyExtractionWebpackPlugin.#staticDepsCache.get( + block + ); + } + + if ( + DependencyExtractionWebpackPlugin.#staticDepsCurrent.has( block ) + ) { + return false; + } + + DependencyExtractionWebpackPlugin.#staticDepsCurrent.add( block ); + const incomingConnections = [ ...compilation.moduleGraph.getIncomingConnections( block ), ].filter( @@ -371,6 +388,13 @@ class DependencyExtractionWebpackPlugin { // If we don't have non-entry, non-library incoming connections, // we've reached a root of if ( ! incomingConnections.length ) { + DependencyExtractionWebpackPlugin.#staticDepsCache.set( + block, + true + ); + DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( + block + ); return true; } @@ -389,16 +413,28 @@ class DependencyExtractionWebpackPlugin { // All the dependencies were Async, the module was reached via a dynamic import if ( ! staticDependentModules.length ) { + DependencyExtractionWebpackPlugin.#staticDepsCache.set( + block, + false + ); + DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( + block + ); return false; } // Continue to explore any static dependencies - return staticDependentModules.some( ( parentStaticDependentModule ) => - DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( - compilation, - parentStaticDependentModule - ) + const result = staticDependentModules.some( + ( parentStaticDependentModule ) => + DependencyExtractionWebpackPlugin.hasStaticDependencyPathToRoot( + compilation, + parentStaticDependentModule + ) ); + + DependencyExtractionWebpackPlugin.#staticDepsCache.set( block, result ); + DependencyExtractionWebpackPlugin.#staticDepsCurrent.delete( block ); + return result; } } diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js index bfffff3ae78319..59d4c5d2ead3ab 100644 --- a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js @@ -4,5 +4,11 @@ const DependencyExtractionWebpackPlugin = require( '../../..' ); module.exports = { - plugins: [ new DependencyExtractionWebpackPlugin() ], + plugins: [ + new DependencyExtractionWebpackPlugin( { + requestToExternalModule( request ) { + return request.startsWith( '@wordpress/' ); + }, + } ), + ], }; From 0c2de0de0d55ffbc8be10ad58a4121909d2239a8 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 16 Sep 2024 18:21:07 +0200 Subject: [PATCH 09/10] Remove redundant plugin config in test --- .../test/fixtures/cyclic-external-deps/webpack.config.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js index 59d4c5d2ead3ab..bfffff3ae78319 100644 --- a/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/cyclic-external-deps/webpack.config.js @@ -4,11 +4,5 @@ const DependencyExtractionWebpackPlugin = require( '../../..' ); module.exports = { - plugins: [ - new DependencyExtractionWebpackPlugin( { - requestToExternalModule( request ) { - return request.startsWith( '@wordpress/' ); - }, - } ), - ], + plugins: [ new DependencyExtractionWebpackPlugin() ], }; From 81d15af7118b2e5ec7b5c556d4e2cbc3b3ca11f7 Mon Sep 17 00:00:00 2001 From: Michal Czaplinski Date: Wed, 18 Sep 2024 16:49:03 +0100 Subject: [PATCH 10/10] Updated the snapshot files --- .../test/__snapshots__/build.js.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index 80893ec4027c05..c2403550c934fc 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -56,14 +56,14 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-dynamic-depe `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-external-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` -" array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => '59584257c15ebb59974d', 'type' => 'module'); +" array(array('id' => '@wordpress/interactivity', 'import' => 'dynamic')), 'version' => 'e1033c1bd62e8cb8d4c9', 'type' => 'module'); " `; exports[`DependencyExtractionWebpackPlugin modules Webpack \`cyclic-external-deps\` should produce expected output: External modules should match snapshot 1`] = ` [ { - "externalType": "import", + "externalType": "module", "request": "@wordpress/interactivity", "userRequest": "@wordpress/interactivity", },