Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Commit 858d146

Browse files
committed
Merge pull request #7155 from adobe/pflynn/fix-slow-unwatch
Fix bug #7150 (Switching projects or quitting sometimes pauses for several seconds)
2 parents b64a2a1 + 93bee95 commit 858d146

3 files changed

Lines changed: 71 additions & 8 deletions

File tree

src/filesystem/FileSystem.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,9 @@ define(function (require, exports, module) {
350350
// entries always return cached data if it exists!
351351
this._index.visitAll(function (child) {
352352
if (child.fullPath.indexOf(entry.fullPath) === 0) {
353-
child._clearCachedData();
353+
// 'true' so entry doesn't try to clear its immediate childrens' caches too. That would be redundant
354+
// with the visitAll() here, and could be slow if we've already cleared its parent (#7150).
355+
child._clearCachedData(true);
354356
}
355357
}.bind(this));
356358

@@ -718,7 +720,8 @@ define(function (require, exports, module) {
718720
if (!watchedRoot || !watchedRoot.filter(directory.name, directory.parentPath)) {
719721
this._index.visitAll(function (entry) {
720722
if (entry.fullPath.indexOf(directory.fullPath) === 0) {
721-
entry._clearCachedData();
723+
// Passing 'true' for a similar reason as in _unwatchEntry() - see #7150
724+
entry._clearCachedData(true);
722725
}
723726
}.bind(this));
724727

@@ -773,7 +776,8 @@ define(function (require, exports, module) {
773776
if (!path) {
774777
// This is a "wholesale" change event; clear all caches
775778
this._index.visitAll(function (entry) {
776-
entry._clearCachedData();
779+
// Passing 'true' for a similar reason as in _unwatchEntry() - see #7150
780+
entry._clearCachedData(true);
777781
});
778782

779783
this._fireChangeEvent(null);

test/spec/FileSystem-test.js

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*/
2323

2424
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
25-
/*global define, describe, it, expect, beforeEach, afterEach, waits, waitsFor, runs, $, window, jasmine */
25+
/*global define, describe, it, expect, beforeEach, afterEach, waits, waitsFor, waitsForDone, runs, $, window, jasmine, spyOn */
2626

2727
define(function (require, exports, module) {
2828
"use strict";
@@ -32,7 +32,8 @@ define(function (require, exports, module) {
3232
FileSystem = require("filesystem/FileSystem"),
3333
FileSystemStats = require("filesystem/FileSystemStats"),
3434
FileSystemError = require("filesystem/FileSystemError"),
35-
MockFileSystemImpl = require("./MockFileSystemImpl");
35+
MockFileSystemImpl = require("./MockFileSystemImpl"),
36+
Async = require("utils/Async");
3637

3738

3839
describe("FileSystem", function () {
@@ -1342,13 +1343,70 @@ define(function (require, exports, module) {
13421343
});
13431344
});
13441345

1345-
it("should invalidate cached data after unwatch", function () {
1346+
it("should recursively invalidate cached data after unwatch", function () {
1347+
var file1 = fileSystem.getFileForPath("/file1.txt"),
1348+
subdir = fileSystem.getDirectoryForPath("/subdir"),
1349+
file4 = fileSystem.getFileForPath("/subdir/file4.txt"),
1350+
childSubdir = fileSystem.getDirectoryForPath("/subdir/child"),
1351+
file5 = fileSystem.getFileForPath("/subdir/child/file5.txt"),
1352+
entries = [file1, subdir, file4, childSubdir, file5],
1353+
unwatchCb = errorCallback();
1354+
1355+
runs(function () {
1356+
var readAllPromise = Async.doInParallel(entries, function (entry) {
1357+
// Confirm watched and no cached data yet
1358+
expect(entry._isWatched()).toBe(true);
1359+
expect(entry._contents).toBeFalsy();
1360+
1361+
// Read contents
1362+
var result = new $.Deferred(),
1363+
cb = function (err, contents) {
1364+
expect(err).toBeFalsy();
1365+
result.resolve();
1366+
};
1367+
if (entry.isFile) {
1368+
entry.read(cb);
1369+
} else {
1370+
entry.getContents(cb);
1371+
}
1372+
return result;
1373+
});
1374+
1375+
waitsForDone(readAllPromise);
1376+
});
1377+
runs(function () {
1378+
// Confirm all entries now have cached data
1379+
entries.forEach(function (entry) {
1380+
expect(entry._contents).toBeTruthy();
1381+
});
1382+
1383+
// Unwatch and count how many visitAll() calls it took
1384+
spyOn(fileSystem._index, "visitAll").andCallThrough();
1385+
1386+
fileSystem.unwatch(fileSystem.getDirectoryForPath("/"), unwatchCb);
1387+
});
1388+
waitsFor(function () { return unwatchCb.wasCalled; });
1389+
1390+
runs(function () {
1391+
// Confirm visitAll() didn't traverse the whole index multiple times (#7150).
1392+
// One call expected for _unwatchEntry() calling _clearCachedData(), one for unwatch() calling removeEntry().
1393+
expect(fileSystem._index.visitAll.callCount).toBe(2);
1394+
1395+
// Confirm all entries have become uncached
1396+
entries.forEach(function (entry) {
1397+
expect(entry._isWatched()).toBe(false);
1398+
expect(entry._contents).toBeFalsy();
1399+
});
1400+
});
1401+
});
1402+
1403+
it("should invalidate cached data after unwatch, but allow read again", function () {
13461404
var file,
13471405
cb0 = readCallback(),
13481406
cb1 = errorCallback(),
13491407
cb2 = readCallback(),
13501408
savedHash;
1351-
1409+
13521410
// confirm watched and empty cached data
13531411
runs(function () {
13541412
file = fileSystem.getFileForPath(filename);
@@ -1387,6 +1445,7 @@ define(function (require, exports, module) {
13871445
expect(cb2.error).toBeFalsy();
13881446
expect(cb2.data).toBe(cb0.data);
13891447
expect(file._isWatched()).toBe(false);
1448+
expect(file._contents).toBeFalsy();
13901449
expect(file._hash).toBeTruthy();
13911450
expect(readCalls).toBe(2);
13921451
});

test/spec/MockFileSystemImpl.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ define(function (require, exports, module) {
162162
if (options.expectedContents !== _model.readFile(path)) {
163163
cb(FileSystemError.CONTENTS_MODIFIED);
164164
return;
165-
}
165+
}
166166
} else {
167167
cb(FileSystemError.CONTENTS_MODIFIED);
168168
return;

0 commit comments

Comments
 (0)