diff --git a/packages/core/core/src/requests/AssetGraphRequest.js b/packages/core/core/src/requests/AssetGraphRequest.js index d1fdbef58af..98c601faaad 100644 --- a/packages/core/core/src/requests/AssetGraphRequest.js +++ b/packages/core/core/src/requests/AssetGraphRequest.js @@ -108,6 +108,7 @@ export class AssetGraphBuilder { queue: PromiseQueue; changedAssets: Map; changedAssetsPropagation: Set; + prevChangedAssetsPropagation: ?Set; optionsRef: SharedReference; options: ParcelOptions; api: RunAPI; @@ -146,8 +147,9 @@ export class AssetGraphBuilder { this.previousSymbolPropagationErrors = prevResult?.previousSymbolPropagationErrors ?? new Map(); this.changedAssets = prevResult?.changedAssets ?? new Map(); - this.changedAssetsPropagation = - prevResult?.changedAssetsPropagation ?? new Set(); + this.changedAssetsPropagation = new Set(); + this.prevChangedAssetsPropagation = prevResult?.changedAssetsPropagation; + this.assetGraph = assetGraph; this.optionsRef = optionsRef; this.options = options; @@ -230,6 +232,17 @@ export class AssetGraphBuilder { visit(rootNodeId); await this.queue.run(); + if (this.prevChangedAssetsPropagation) { + // Add any previously seen Assets that have not been propagated yet to + // 'this.changedAssetsPropagation', but only if they still remain in the graph + // as they could have been removed since the last build + for (let assetId of this.prevChangedAssetsPropagation) { + if (this.assetGraph.hasContentKey(assetId)) { + this.changedAssetsPropagation.add(assetId); + } + } + } + if (errors.length) { this.api.storeResult( { diff --git a/packages/core/integration-tests/test/symbol-propagation.js b/packages/core/integration-tests/test/symbol-propagation.js new file mode 100644 index 00000000000..4a5a60aab1f --- /dev/null +++ b/packages/core/integration-tests/test/symbol-propagation.js @@ -0,0 +1,33 @@ +import assert from 'assert'; +import path from 'path'; +import {bundler, run, overlayFS, fsFixture} from '@parcel/test-utils'; + +describe('symbol propagation', () => { + it('should handle removed assets from previous failed builds', async () => { + await fsFixture(overlayFS, __dirname)` + broken.js: + module.exports = require('./missing.js'); + working.js: + module.exports = 'ITS WORKING'; + index.js: + module.exports = require('./broken.js');`; + + let b = bundler(path.join(__dirname, 'index.js'), { + inputFS: overlayFS, + shouldDisableCache: false, + }); + + await assert.rejects(() => b.run(), { + message: `Failed to resolve './missing.js' from './broken.js'`, + }); + + await overlayFS.writeFile( + path.join(__dirname, 'index.js'), + `module.exports = require('./working.js');`, + ); + + let {bundleGraph} = await b.run(); + + assert(await run(bundleGraph), 'ITS WORKING'); + }); +});