diff --git a/src/Bundler.js b/src/Bundler.js index 1734932d4b9..4e79bcee482 100644 --- a/src/Bundler.js +++ b/src/Bundler.js @@ -389,7 +389,7 @@ class Bundler extends EventEmitter { this.buildQueue.delete(asset); } - createBundleTree(asset, dep, bundle) { + createBundleTree(asset, dep, bundle, parentBundles = new Set()) { if (dep) { asset.parentDeps.add(dep); } @@ -405,7 +405,14 @@ class Bundler extends EventEmitter { this.moveAssetToBundle(asset, commonBundle); return; } - } else return; + } else { + return; + } + + // Detect circular bundles + if (parentBundles.has(asset.parentBundle)) { + return; + } } // Create the root bundle if it doesn't exist @@ -444,15 +451,22 @@ class Bundler extends EventEmitter { } asset.parentBundle = bundle; + parentBundles.add(bundle); for (let [dep, assetDep] of asset.depAssets) { - this.createBundleTree(assetDep, dep, bundle); + this.createBundleTree(assetDep, dep, bundle, parentBundles); } + parentBundles.delete(bundle); return bundle; } moveAssetToBundle(asset, commonBundle) { + // Never move the entry asset of a bundle, as it was explicitly requested to be placed in a separate bundle. + if (asset.parentBundle.entryAsset === asset) { + return; + } + for (let bundle of Array.from(asset.bundles)) { bundle.removeAsset(asset); commonBundle.getSiblingBundle(bundle.type).addAsset(asset); diff --git a/test/html.js b/test/html.js index 4a322479f7a..24c64f7b0ea 100644 --- a/test/html.js +++ b/test/html.js @@ -299,4 +299,36 @@ describe('html', function() { ] }); }); + + it('should support circular dependencies', async function() { + let b = await bundle(__dirname + '/integration/circular/index.html'); + + assertBundleTree(b, { + name: 'index.html', + assets: ['index.html'], + childBundles: [ + { + type: 'html', + assets: ['about.html'], + childBundles: [ + { + type: 'js', + assets: ['about.js', 'index.js'], + childBundles: [] + }, + { + type: 'html', + assets: ['test.html'], + childBundles: [] + } + ] + }, + { + type: 'js', + assets: ['about.js', 'index.js'], + childBundles: [] + } + ] + }); + }); }); diff --git a/test/integration/circular/.eslintrc.json b/test/integration/circular/.eslintrc.json new file mode 100644 index 00000000000..f89e231fa93 --- /dev/null +++ b/test/integration/circular/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "../.eslintrc.json", + "parserOptions": { + "sourceType": "module" + } +} \ No newline at end of file diff --git a/test/integration/circular/about.html b/test/integration/circular/about.html new file mode 100644 index 00000000000..83a39cf7df1 --- /dev/null +++ b/test/integration/circular/about.html @@ -0,0 +1,15 @@ + + + + Document + + + + On About + + Home + About + Test + + + diff --git a/test/integration/circular/about.js b/test/integration/circular/about.js new file mode 100644 index 00000000000..0423432d88b --- /dev/null +++ b/test/integration/circular/about.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line no-unused-vars +import index from './index'; diff --git a/test/integration/circular/index.html b/test/integration/circular/index.html new file mode 100644 index 00000000000..f4ec0e4c928 --- /dev/null +++ b/test/integration/circular/index.html @@ -0,0 +1,15 @@ + + + + Document + + + + On Home + + Home + About + Test + + + diff --git a/test/integration/circular/index.js b/test/integration/circular/index.js new file mode 100644 index 00000000000..86716399365 --- /dev/null +++ b/test/integration/circular/index.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line no-unused-vars +import about from './about'; diff --git a/test/integration/circular/test.html b/test/integration/circular/test.html new file mode 100644 index 00000000000..50e46356977 --- /dev/null +++ b/test/integration/circular/test.html @@ -0,0 +1,14 @@ + + + + Document + + + Test + + Home + About + Test + + +