Skip to content

Commit 6554ad5

Browse files
cpojerFacebook Github Bot
authored and
Facebook Github Bot
committed
Kill fastfs
Summary: This kills fastfs in favor of Jest's hasteFS. It gets rid of a ton of code, including the mocking code in ResolutionRequest which we don't need any more. Next step after this is to rewrite HasteMap, ModuleCache, Module/Package. We are getting closer to a nicer and faster world! :) Here is what I did: * Use Jest's HasteFS instead of fastfs. A fresh instance is received every time something changes on the FS. * HasteFS is not shared with everything any more. Only one reference is kept in DependencyGraph and there are a few smaller functions that are passed around (getClosestPackage and dirExists). Note: `dirExists` now does fs access instead of an offline check. This sucks but stat calls aren't slow and aren't going to be a bottleneck in ResolutionRequest, I promise! When it is time to tackle a ResolutionRequest rewrite with jest-resolve, this will go away. "It gets worse before it gets better" :) The ModuleGraph equivalent does *not* do fs access and retains the previous way of doing things because we shouldn't do online fs access there. * Add flow annotations to ResolutionRequest. This required a few tiny hacks for now because of ModuleGraph's duck typing. I'll get rid of this soon. * Updated ModuleGraph to work with the new code, also created a mock HasteFS instance there. * I fixed a few tiny mock issues for `fs` to make the tests work; I had to add one tiny little internal update to `dgraph._hasteFS._files` because the file watching in the tests isn't real. It is instrumented through some function calls, therefore the hasteFS instance doesn't get automatically updated. One way to solve this is to add `JestHasteMap.emit('change', …)` for testing but I didn't want to cut a Jest release just for that. #movefast (Note: I will likely land this in 1.5 weeks from now after my vacation and I have yet to fully test all the product flows. Please give me feedback so I can make sure this is solid!) Reviewed By: davidaurelio Differential Revision: D4204082 fbshipit-source-id: d6dc9fcb77ac224df4554a59f0fce241c01b0512
1 parent 911c05a commit 6554ad5

File tree

21 files changed

+392
-960
lines changed

21 files changed

+392
-960
lines changed

local-cli/server/util/attachHMRServer.js

+11-14
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ function attachHMRServer({httpServer, path, packagerServer}) {
136136
inverseDependenciesCache,
137137
};
138138

139-
packagerServer.setHMRFileChangeListener((filename, stat) => {
139+
packagerServer.setHMRFileChangeListener((type, filename) => {
140140
if (!client) {
141141
return;
142142
}
@@ -151,14 +151,14 @@ function attachHMRServer({httpServer, path, packagerServer}) {
151151
}
152152

153153
client.ws.send(JSON.stringify({type: 'update-start'}));
154-
stat.then(() => {
155-
return packagerServer.getShallowDependencies({
156-
entryFile: filename,
157-
platform: client.platform,
158-
dev: true,
159-
hot: true,
160-
})
161-
.then(deps => {
154+
const promise = type === 'delete'
155+
? Promise.resolve()
156+
: packagerServer.getShallowDependencies({
157+
entryFile: filename,
158+
platform: client.platform,
159+
dev: true,
160+
hot: true,
161+
}).then(deps => {
162162
if (!client) {
163163
return [];
164164
}
@@ -300,11 +300,8 @@ function attachHMRServer({httpServer, path, packagerServer}) {
300300
print(createEntry('HMR Server sending update to client'));
301301
client.ws.send(update);
302302
});
303-
},
304-
() => {
305-
// do nothing, file was removed
306-
},
307-
).then(() => {
303+
304+
promise.then(() => {
308305
client.ws.send(JSON.stringify({type: 'update-done'}));
309306
});
310307
});

packager/react-packager/src/Bundler/index.js

-4
Original file line numberDiff line numberDiff line change
@@ -502,10 +502,6 @@ class Bundler {
502502
});
503503
}
504504

505-
stat(filePath: string) {
506-
return this._resolver.stat(filePath);
507-
}
508-
509505
getModuleForPath(entryFile: string) {
510506
return this._resolver.getModuleForPath(entryFile);
511507
}

packager/react-packager/src/ModuleGraph/node-haste/FastFS.js packager/react-packager/src/ModuleGraph/node-haste/HasteFS.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
const {dirname, join, parse} = require('path');
1515

16-
module.exports = class FastFS {
16+
module.exports = class HasteFS {
1717
directories: Set<string>;
1818
directoryEntries: Map<string, Array<string>>;
1919
files: Set<string>;
@@ -40,7 +40,7 @@ module.exports = class FastFS {
4040
return this.directories.has(path);
4141
}
4242

43-
fileExists(path: string) {
43+
exists(path: string) {
4444
return this.files.has(path);
4545
}
4646

packager/react-packager/src/ModuleGraph/node-haste/ModuleCache.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@ const Module = require('./Module');
1515
const Package = require('./Package');
1616

1717
import type {PackageData, TransformedFile} from '../types.flow';
18-
import type {FastFS} from './node-haste.flow';
1918

2019
type GetFn<T> = (path: string) => Promise<T>;
20+
type GetClosestPackageFn = (filePath: string) => ?string;
2121

2222
module.exports = class ModuleCache {
23-
fastfs: FastFS;
23+
_getClosestPackage: GetClosestPackageFn;
2424
getPackageData: GetFn<PackageData>;
2525
getTransformedFile: GetFn<TransformedFile>;
2626
modules: Map<string, Module>;
2727
packages: Map<string, Package>;
2828

29-
constructor(fastfs: FastFS, getTransformedFile: GetFn<TransformedFile>) {
30-
this.fastfs = fastfs;
29+
constructor(getClosestPackage: GetClosestPackageFn, getTransformedFile: GetFn<TransformedFile>) {
30+
this._getClosestPackage = getClosestPackage;
3131
this.getTransformedFile = getTransformedFile;
3232
this.getPackageData = path => getTransformedFile(path).then(
3333
f => f.package || Promise.reject(new Error(`"${path}" does not exist`))
@@ -59,7 +59,7 @@ module.exports = class ModuleCache {
5959
}
6060

6161
getPackageOf(filePath: string) {
62-
const candidate = this.fastfs.closest(filePath, 'package.json');
62+
const candidate = this._getClosestPackage(filePath);
6363
return candidate != null ? this.getPackage(candidate) : null;
6464
}
6565
};

packager/react-packager/src/ModuleGraph/node-haste/node-haste.flow.js

+3-22
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*
99
* @flow
1010
*/
11+
'use strict';
1112

1213
'use strict';
1314

@@ -57,7 +58,7 @@ export type FastFS = {
5758
type HasteMapOptions = {|
5859
allowRelativePaths: boolean,
5960
extensions: Extensions,
60-
fastfs: FastFS,
61+
files: Array<string>,
6162
helpers: DependencyGraphHelpers,
6263
moduleCache: ModuleCache,
6364
platforms: Platforms,
@@ -66,26 +67,6 @@ type HasteMapOptions = {|
6667

6768
declare class HasteMap {
6869
// node-haste/DependencyGraph/HasteMap.js
69-
constructor(options: HasteMapOptions): void,
7070
build(): Promise<Object>,
71+
constructor(options: HasteMapOptions): void,
7172
}
72-
export type HasteMapT = HasteMap;
73-
74-
type ResolutionRequestOptions = {|
75-
platform: Platform,
76-
platforms: Platforms,
77-
preferNativePlatform: true,
78-
hasteMap: HasteMap,
79-
helpers: DependencyGraphHelpers,
80-
moduleCache: ModuleCache,
81-
fastfs: FastFS,
82-
shouldThrowOnUnresolvedErrors: () => true,
83-
extraNodeModules: {[id: ModuleID]: Path},
84-
|};
85-
86-
declare class ResolutionRequest {
87-
// node-haste/DependencyGraph/ResolutionRequest.js
88-
constructor(options: ResolutionRequestOptions): void,
89-
resolveDependency(from: Module, to: ModuleID): Promise<Module>,
90-
}
91-
export type ResolutionRequestT = ResolutionRequest;

packager/react-packager/src/ModuleGraph/node-haste/node-haste.js

+13-9
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313

1414
import type { // eslint-disable-line sort-requires
1515
Extensions,
16-
HasteMapT,
1716
Path,
18-
ResolutionRequestT,
1917
} from './node-haste.flow';
2018

2119
import type {
@@ -24,11 +22,12 @@ import type {
2422
} from '../types.flow';
2523

2624
const DependencyGraphHelpers = require('../../node-haste/DependencyGraph/DependencyGraphHelpers');
27-
const FastFS = require('./FastFS');
28-
const HasteMap: Class<HasteMapT> = require('../../node-haste/DependencyGraph/HasteMap');
25+
const HasteFS = require('./HasteFS');
26+
const HasteMap = require('../../node-haste/DependencyGraph/HasteMap');
2927
const Module = require('./Module');
3028
const ModuleCache = require('./ModuleCache');
31-
const ResolutionRequest: Class<ResolutionRequestT> = require('../../node-haste/DependencyGraph/ResolutionRequest');
29+
const ResolutionRequest = require('../../node-haste/DependencyGraph/ResolutionRequest');
30+
3231
const defaults = require('../../../../defaults');
3332

3433
type ResolveOptions = {|
@@ -57,12 +56,15 @@ exports.createResolveFn = function(options: ResolveOptions): ResolveFn {
5756
providesModuleNodeModules: defaults.providesModuleNodeModules,
5857
});
5958

60-
const fastfs = new FastFS(files);
61-
const moduleCache = new ModuleCache(fastfs, getTransformedFile);
59+
const hasteFS = new HasteFS(files);
60+
const moduleCache = new ModuleCache(
61+
filePath => hasteFS.closest(filePath, 'package.json'),
62+
getTransformedFile,
63+
);
6264
const hasteMap = new HasteMap({
6365
allowRelativePaths: true,
6466
extensions: ['js', 'json'],
65-
fastfs,
67+
files,
6668
helpers,
6769
moduleCache,
6870
platforms,
@@ -75,8 +77,10 @@ exports.createResolveFn = function(options: ResolveOptions): ResolveFn {
7577
let resolutionRequest = resolutionRequests[platform];
7678
if (!resolutionRequest) {
7779
resolutionRequest = resolutionRequests[platform] = new ResolutionRequest({
80+
dirExists: filePath => hasteFS.dirExists(filePath),
81+
entryPath: '',
7882
extraNodeModules,
79-
fastfs,
83+
hasteFS,
8084
hasteMap,
8185
helpers,
8286
moduleCache,

packager/react-packager/src/Resolver/index.js

-4
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,6 @@ class Resolver {
123123
return this._depGraph.getShallowDependencies(entryFile, transformOptions);
124124
}
125125

126-
stat(filePath) {
127-
return this._depGraph.getFS().stat(filePath);
128-
}
129-
130126
getModuleForPath(entryFile) {
131127
return this._depGraph.getModuleForPath(entryFile);
132128
}

packager/react-packager/src/Server/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ class Server {
347347
if (this._hmrFileChangeListener) {
348348
// Clear cached bundles in case user reloads
349349
this._clearBundles();
350-
this._hmrFileChangeListener(filePath, this._bundler.stat(filePath));
350+
this._hmrFileChangeListener(type, filePath);
351351
return;
352352
} else if (type !== 'change' && filePath.indexOf(NODE_MODULES) !== -1) {
353353
// node module resolution can be affected by added or removed files

packager/react-packager/src/node-haste/AssetModule.js

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
19
'use strict';
210

311
const Module = require('./Module');
12+
413
const getAssetDataFromName = require('./lib/getAssetDataFromName');
514

615
class AssetModule extends Module {

packager/react-packager/src/node-haste/DependencyGraph/HasteMap.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@ const PACKAGE_JSON = path.sep + 'package.json';
2121
class HasteMap extends EventEmitter {
2222
constructor({
2323
extensions,
24-
fastfs,
24+
files,
2525
moduleCache,
2626
preferNativePlatform,
2727
helpers,
2828
platforms,
2929
}) {
3030
super();
3131
this._extensions = extensions;
32-
this._fastfs = fastfs;
33-
this._moduleCache = moduleCache;
34-
this._preferNativePlatform = preferNativePlatform;
32+
this._files = files;
3533
this._helpers = helpers;
34+
this._moduleCache = moduleCache;
3635
this._platforms = platforms;
36+
this._preferNativePlatform = preferNativePlatform;
3737

3838
this._processHastePackage = throat(1, this._processHastePackage.bind(this));
3939
this._processHasteModule = throat(1, this._processHasteModule.bind(this));
@@ -42,7 +42,7 @@ class HasteMap extends EventEmitter {
4242
build() {
4343
this._map = Object.create(null);
4444
const promises = [];
45-
this._fastfs.getAllFiles().forEach(filePath => {
45+
this._files.forEach(filePath => {
4646
if (!this._helpers.isNodeModulesDir(filePath)) {
4747
if (this._extensions.indexOf(path.extname(filePath).substr(1)) !== -1) {
4848
promises.push(this._processHasteModule(filePath));

0 commit comments

Comments
 (0)