diff --git a/lib/FileSystemInfo.js b/lib/FileSystemInfo.js index 1b989fd77c3..87221acfa25 100644 --- a/lib/FileSystemInfo.js +++ b/lib/FileSystemInfo.js @@ -208,6 +208,12 @@ class SnapshotIterable { class Snapshot { constructor() { this._flags = 0; + /** @type {Iterable | undefined} */ + this._cachedFileIterable = undefined; + /** @type {Iterable | undefined} */ + this._cachedContextIterable = undefined; + /** @type {Iterable | undefined} */ + this._cachedMissingIterable = undefined; /** @type {number | undefined} */ this.startTime = undefined; /** @type {Map | undefined} */ @@ -418,31 +424,43 @@ class Snapshot { * @returns {Iterable} iterable */ getFileIterable() { - return this._createIterable(s => [ - s.fileTimestamps, - s.fileHashes, - s.fileTshs, - s.managedFiles - ]); + if (this._cachedFileIterable === undefined) { + this._cachedFileIterable = this._createIterable(s => [ + s.fileTimestamps, + s.fileHashes, + s.fileTshs, + s.managedFiles + ]); + } + return this._cachedFileIterable; } /** * @returns {Iterable} iterable */ getContextIterable() { - return this._createIterable(s => [ - s.contextTimestamps, - s.contextHashes, - s.contextTshs, - s.managedContexts - ]); + if (this._cachedContextIterable === undefined) { + this._cachedContextIterable = this._createIterable(s => [ + s.contextTimestamps, + s.contextHashes, + s.contextTshs, + s.managedContexts + ]); + } + return this._cachedContextIterable; } /** * @returns {Iterable} iterable */ getMissingIterable() { - return this._createIterable(s => [s.missingExistence, s.managedMissing]); + if (this._cachedMissingIterable === undefined) { + this._cachedMissingIterable = this._createIterable(s => [ + s.missingExistence, + s.managedMissing + ]); + } + return this._cachedMissingIterable; } } diff --git a/test/FileSystemInfo.unittest.js b/test/FileSystemInfo.unittest.js index 934990b65f5..fbca60f9cfe 100644 --- a/test/FileSystemInfo.unittest.js +++ b/test/FileSystemInfo.unittest.js @@ -363,4 +363,50 @@ ${details(snapshot)}`) } }); } + + describe("stable iterables identity", () => { + const options = { timestamp: true }; + + /** + * @param {function((WebpackError | null)=, (Snapshot | null)=): void} callback callback function + */ + function getSnapshot(callback) { + const fs = createFs(); + const fsInfo = createFsInfo(fs); + fsInfo.createSnapshot( + Date.now() + 10000, + files, + directories, + missing, + options, + callback + ); + } + + it("should return same iterable for getFileIterable()", done => { + getSnapshot((err, snapshot) => { + if (err) done(err); + expect(snapshot.getFileIterable()).toEqual(snapshot.getFileIterable()); + done(); + }); + }); + + it("should return same iterable for getContextIterable()", done => { + getSnapshot((err, snapshot) => { + if (err) done(err); + expect(snapshot.getContextIterable()).toEqual( + snapshot.getContextIterable() + ); + done(); + }); + }); + + it("should return same iterable for getMissingIterable()", done => { + getSnapshot((err, snapshot) => { + if (err) done(err); + expect(snapshot.getFileIterable()).toEqual(snapshot.getFileIterable()); + done(); + }); + }); + }); });