Skip to content

Commit 2303c10

Browse files
robhoganfacebook-github-bot
authored andcommitted
Watcher - don't emit symlink events if enableSymlinks: false
Summary: D42454225 (b1bef3d) introduced whole-graph invalidation on symlink changes, with the intention being that this would only occur if `resolver.unstable_enableSymlinks` was `true`. Unfortunately the event suppression added alongside it in D42454225 (b1bef3d) was broken, due to use of `type` (change type) vs `metadata.type` (file type). Additionally, the previous suppression came too late in file processing - so that even if it had used `metadata.type`, a symlink would be added to the `FileSystem` instance even though no change would be emitted to Metro. This could've caused existence checks to succeed that should fail with `enableSymlinks: false` (and would fail after a recrawl, because crawlers exclude symlinks). This diff moves symlink event detection up to the start of `onChange` processing, and returns early. Changelog: * **Fix**: Don't over-invalidate on symlink changes if resolution through symlinks is not enabled Reviewed By: motiz88 Differential Revision: D43620608 fbshipit-source-id: 4e63258b246308766adf97beef3f7082caab6269
1 parent b422ed6 commit 2303c10

File tree

2 files changed

+71
-6
lines changed

2 files changed

+71
-6
lines changed

packages/metro-file-map/src/__tests__/index-test.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,74 @@ describe('HasteMap', () => {
15521552
expect(eventsQueue).toHaveLength(1);
15531553
});
15541554

1555+
hm_it(
1556+
'suppresses backend symlink events if enableSymlinks: false',
1557+
async hm => {
1558+
const {fileSystem} = await hm.build();
1559+
const fruitsRoot = path.join('/', 'project', 'fruits');
1560+
const e = mockEmitters[fruitsRoot];
1561+
mockFs[path.join(fruitsRoot, 'Tomato.js')] = `
1562+
// Tomato!
1563+
`;
1564+
e.emit('all', 'change', 'Tomato.js', fruitsRoot, MOCK_CHANGE_FILE);
1565+
e.emit(
1566+
'all',
1567+
'change',
1568+
'LinkToStrawberry.js',
1569+
fruitsRoot,
1570+
MOCK_CHANGE_LINK,
1571+
);
1572+
const {eventsQueue} = await waitForItToChange(hm);
1573+
expect(eventsQueue).toEqual([
1574+
{
1575+
filePath: path.join(fruitsRoot, 'Tomato.js'),
1576+
metadata: MOCK_CHANGE_FILE,
1577+
type: 'change',
1578+
},
1579+
]);
1580+
expect(
1581+
fileSystem.linkStats(path.join(fruitsRoot, 'LinkToStrawberry.js')),
1582+
).toBeNull();
1583+
},
1584+
);
1585+
1586+
hm_it(
1587+
'emits symlink events if enableSymlinks: true',
1588+
async hm => {
1589+
const {fileSystem} = await hm.build();
1590+
const fruitsRoot = path.join('/', 'project', 'fruits');
1591+
const e = mockEmitters[fruitsRoot];
1592+
mockFs[path.join(fruitsRoot, 'Tomato.js')] = `
1593+
// Tomato!
1594+
`;
1595+
e.emit('all', 'change', 'Tomato.js', fruitsRoot, MOCK_CHANGE_FILE);
1596+
e.emit(
1597+
'all',
1598+
'change',
1599+
'LinkToStrawberry.js',
1600+
fruitsRoot,
1601+
MOCK_CHANGE_LINK,
1602+
);
1603+
const {eventsQueue} = await waitForItToChange(hm);
1604+
expect(eventsQueue).toEqual([
1605+
{
1606+
filePath: path.join(fruitsRoot, 'Tomato.js'),
1607+
metadata: MOCK_CHANGE_FILE,
1608+
type: 'change',
1609+
},
1610+
{
1611+
filePath: path.join(fruitsRoot, 'LinkToStrawberry.js'),
1612+
metadata: MOCK_CHANGE_LINK,
1613+
type: 'change',
1614+
},
1615+
]);
1616+
expect(
1617+
fileSystem.linkStats(path.join(fruitsRoot, 'LinkToStrawberry.js')),
1618+
).toEqual({fileType: 'l', modifiedTime: 46});
1619+
},
1620+
{config: {enableSymlinks: true}},
1621+
);
1622+
15551623
hm_it(
15561624
'emits a change even if a file in node_modules has changed',
15571625
async hm => {

packages/metro-file-map/src/index.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,9 @@ export default class HasteMap extends EventEmitter {
943943
// Ignore all directory events
944944
(metadata.type === 'd' ||
945945
// Ignore regular files with unwatched extensions
946-
(metadata.type === 'f' && !hasWatchedExtension(filePath)))
946+
(metadata.type === 'f' && !hasWatchedExtension(filePath)) ||
947+
// Don't emit events relating to symlinks if enableSymlinks: false
948+
(!this._options.enableSymlinks && metadata?.type === 'l'))
947949
) {
948950
return;
949951
}
@@ -993,11 +995,6 @@ export default class HasteMap extends EventEmitter {
993995
const linkStats = fileSystem.linkStats(relativeFilePath);
994996

995997
const enqueueEvent = (metadata: ChangeEventMetadata) => {
996-
// Don't emit events relating to symlinks if enableSymlinks: false
997-
if (!this._options.enableSymlinks && type === 'l') {
998-
return null;
999-
}
1000-
1001998
eventsQueue.push({
1002999
filePath: absoluteFilePath,
10031000
metadata,

0 commit comments

Comments
 (0)