metro-file-map 0.73.1 → 0.73.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/src/ModuleMap.js.flow +2 -2
- package/src/Watcher.js +344 -0
- package/src/Watcher.js.flow +305 -0
- package/src/crawlers/node.js.flow +2 -1
- package/src/crawlers/watchman/index.js.flow +3 -3
- package/src/index.js +81 -161
- package/src/index.js.flow +79 -132
- package/src/watchers/FSEventsWatcher.js +4 -0
- package/src/watchers/FSEventsWatcher.js.flow +4 -0
- package/src/watchers/NodeWatcher.js +112 -141
- package/src/watchers/NodeWatcher.js.flow +347 -0
- package/src/watchers/WatchmanWatcher.js +37 -8
- package/src/watchers/WatchmanWatcher.js.flow +31 -8
- package/src/watchers/common.js.flow +4 -4
|
@@ -100,7 +100,7 @@ module.exports = async function watchmanCrawl({
|
|
|
100
100
|
roots: $ReadOnlyArray<Path>,
|
|
101
101
|
): Promise<WatchmanRoots> {
|
|
102
102
|
perfLogger?.point('watchmanCrawl/getWatchmanRoots_start');
|
|
103
|
-
const watchmanRoots = new Map();
|
|
103
|
+
const watchmanRoots = new Map<string, Array<string>>();
|
|
104
104
|
await Promise.all(
|
|
105
105
|
roots.map(async (root, index) => {
|
|
106
106
|
perfLogger?.point(`watchmanCrawl/watchProject_${index}_start`);
|
|
@@ -205,8 +205,8 @@ module.exports = async function watchmanCrawl({
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
let files = data.files;
|
|
208
|
-
let removedFiles = new Map();
|
|
209
|
-
const changedFiles = new Map();
|
|
208
|
+
let removedFiles = new Map<Path, FileMetaData>();
|
|
209
|
+
const changedFiles = new Map<Path, FileMetaData>();
|
|
210
210
|
let results: Map<string, WatchmanQueryResponse>;
|
|
211
211
|
let isFresh = false;
|
|
212
212
|
let queryError: ?Error;
|
package/src/index.js
CHANGED
|
@@ -52,15 +52,7 @@ var _rootRelativeCacheKeys = _interopRequireDefault(
|
|
|
52
52
|
|
|
53
53
|
var _ModuleMap = _interopRequireDefault(require("./ModuleMap"));
|
|
54
54
|
|
|
55
|
-
var
|
|
56
|
-
require("./watchers/FSEventsWatcher")
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
var _NodeWatcher = _interopRequireDefault(require("./watchers/NodeWatcher"));
|
|
60
|
-
|
|
61
|
-
var _WatchmanWatcher = _interopRequireDefault(
|
|
62
|
-
require("./watchers/WatchmanWatcher")
|
|
63
|
-
);
|
|
55
|
+
var _Watcher = require("./Watcher");
|
|
64
56
|
|
|
65
57
|
var _worker = require("./worker");
|
|
66
58
|
|
|
@@ -132,16 +124,9 @@ function _interopRequireDefault(obj) {
|
|
|
132
124
|
* @format
|
|
133
125
|
* @oncall react_native
|
|
134
126
|
*/
|
|
135
|
-
// $FlowFixMe[untyped-import] - it's a fork: https://github.com/facebook/jest/pull/10919
|
|
136
127
|
// $FlowFixMe[untyped-import] - jest-regex-util
|
|
137
128
|
// $FlowFixMe[untyped-import] - jest-worker
|
|
138
129
|
// $FlowFixMe[untyped-import] - this is a polyfill
|
|
139
|
-
const nodeCrawl = require("./crawlers/node");
|
|
140
|
-
|
|
141
|
-
const watchmanCrawl = require("./crawlers/watchman");
|
|
142
|
-
|
|
143
|
-
const debug = require("debug")("Metro:FileMap");
|
|
144
|
-
|
|
145
130
|
const DuplicateHasteCandidatesError =
|
|
146
131
|
_ModuleMap.default.DuplicateHasteCandidatesError;
|
|
147
132
|
exports.DuplicateHasteCandidatesError = DuplicateHasteCandidatesError;
|
|
@@ -150,7 +135,6 @@ exports.DuplicateHasteCandidatesError = DuplicateHasteCandidatesError;
|
|
|
150
135
|
// filesystem state and build parameters).
|
|
151
136
|
const CACHE_BREAKER = "2";
|
|
152
137
|
const CHANGE_INTERVAL = 30;
|
|
153
|
-
const MAX_WAIT_TIME = 240000;
|
|
154
138
|
const NODE_MODULES = path.sep + "node_modules" + path.sep;
|
|
155
139
|
const PACKAGE_JSON = path.sep + "package.json";
|
|
156
140
|
const VCS_DIRECTORIES = [".git", ".hg"]
|
|
@@ -309,6 +293,7 @@ class HasteMap extends _events.default {
|
|
|
309
293
|
};
|
|
310
294
|
this._options = {
|
|
311
295
|
...buildParameters,
|
|
296
|
+
healthCheck: options.healthCheck,
|
|
312
297
|
maxWorkers: options.maxWorkers,
|
|
313
298
|
perfLogger: options.perfLogger,
|
|
314
299
|
resetCache: options.resetCache,
|
|
@@ -337,7 +322,6 @@ class HasteMap extends _events.default {
|
|
|
337
322
|
}
|
|
338
323
|
|
|
339
324
|
this._buildPromise = null;
|
|
340
|
-
this._watchers = [];
|
|
341
325
|
this._worker = null;
|
|
342
326
|
(_this$_options$perfLo = this._options.perfLogger) === null ||
|
|
343
327
|
_this$_options$perfLo === void 0
|
|
@@ -511,7 +495,37 @@ class HasteMap extends _events.default {
|
|
|
511
495
|
hasteMap = this._createEmptyMap();
|
|
512
496
|
}
|
|
513
497
|
|
|
514
|
-
|
|
498
|
+
const {
|
|
499
|
+
computeSha1,
|
|
500
|
+
enableSymlinks,
|
|
501
|
+
extensions,
|
|
502
|
+
forceNodeFilesystemAPI,
|
|
503
|
+
ignorePattern,
|
|
504
|
+
perfLogger,
|
|
505
|
+
roots,
|
|
506
|
+
rootDir,
|
|
507
|
+
watch,
|
|
508
|
+
watchmanDeferStates,
|
|
509
|
+
} = this._options;
|
|
510
|
+
this._watcher = new _Watcher.Watcher({
|
|
511
|
+
abortSignal: this._crawlerAbortController.signal,
|
|
512
|
+
computeSha1,
|
|
513
|
+
console: this._console,
|
|
514
|
+
enableSymlinks,
|
|
515
|
+
extensions,
|
|
516
|
+
forceNodeFilesystemAPI,
|
|
517
|
+
healthCheckFilePrefix: this._options.healthCheck.filePrefix,
|
|
518
|
+
ignore: (path) => this._ignore(path),
|
|
519
|
+
ignorePattern,
|
|
520
|
+
initialData: hasteMap,
|
|
521
|
+
perfLogger,
|
|
522
|
+
roots,
|
|
523
|
+
rootDir,
|
|
524
|
+
useWatchman: await this._shouldUseWatchman(),
|
|
525
|
+
watch,
|
|
526
|
+
watchmanDeferStates,
|
|
527
|
+
});
|
|
528
|
+
return this._watcher.crawl().then((result) => {
|
|
515
529
|
var _this$_options$perfLo8;
|
|
516
530
|
|
|
517
531
|
(_this$_options$perfLo8 = this._options.perfLogger) === null ||
|
|
@@ -893,154 +907,38 @@ class HasteMap extends _events.default {
|
|
|
893
907
|
|
|
894
908
|
return this._worker;
|
|
895
909
|
}
|
|
896
|
-
|
|
897
|
-
async _crawl(hasteMap) {
|
|
898
|
-
var _this$_options$perfLo13;
|
|
899
|
-
|
|
900
|
-
(_this$_options$perfLo13 = this._options.perfLogger) === null ||
|
|
901
|
-
_this$_options$perfLo13 === void 0
|
|
902
|
-
? void 0
|
|
903
|
-
: _this$_options$perfLo13.point("crawl_start");
|
|
904
|
-
const options = this._options;
|
|
905
|
-
|
|
906
|
-
const ignore = (filePath) => this._ignore(filePath);
|
|
907
|
-
|
|
908
|
-
const crawl = (await this._shouldUseWatchman()) ? watchmanCrawl : nodeCrawl;
|
|
909
|
-
const crawlerOptions = {
|
|
910
|
-
abortSignal: this._crawlerAbortController.signal,
|
|
911
|
-
computeSha1: options.computeSha1,
|
|
912
|
-
data: hasteMap,
|
|
913
|
-
enableSymlinks: options.enableSymlinks,
|
|
914
|
-
extensions: options.extensions,
|
|
915
|
-
forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,
|
|
916
|
-
ignore,
|
|
917
|
-
perfLogger: options.perfLogger,
|
|
918
|
-
rootDir: options.rootDir,
|
|
919
|
-
roots: options.roots,
|
|
920
|
-
};
|
|
921
|
-
|
|
922
|
-
const retry = (error) => {
|
|
923
|
-
if (crawl === watchmanCrawl) {
|
|
924
|
-
this._console.warn(
|
|
925
|
-
"metro-file-map: Watchman crawl failed. Retrying once with node " +
|
|
926
|
-
"crawler.\n" +
|
|
927
|
-
" Usually this happens when watchman isn't running. Create an " +
|
|
928
|
-
"empty `.watchmanconfig` file in your project's root folder or " +
|
|
929
|
-
"initialize a git or hg repository in your project.\n" +
|
|
930
|
-
" " +
|
|
931
|
-
error.toString()
|
|
932
|
-
);
|
|
933
|
-
|
|
934
|
-
return nodeCrawl(crawlerOptions).catch((e) => {
|
|
935
|
-
throw new Error(
|
|
936
|
-
"Crawler retry failed:\n" +
|
|
937
|
-
` Original error: ${error.message}\n` +
|
|
938
|
-
` Retry error: ${e.message}\n`
|
|
939
|
-
);
|
|
940
|
-
});
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
throw error;
|
|
944
|
-
};
|
|
945
|
-
|
|
946
|
-
const logEnd = (result) => {
|
|
947
|
-
var _this$_options$perfLo14;
|
|
948
|
-
|
|
949
|
-
(_this$_options$perfLo14 = this._options.perfLogger) === null ||
|
|
950
|
-
_this$_options$perfLo14 === void 0
|
|
951
|
-
? void 0
|
|
952
|
-
: _this$_options$perfLo14.point("crawl_end");
|
|
953
|
-
return result;
|
|
954
|
-
};
|
|
955
|
-
|
|
956
|
-
try {
|
|
957
|
-
return crawl(crawlerOptions).catch(retry).then(logEnd);
|
|
958
|
-
} catch (error) {
|
|
959
|
-
return retry(error).then(logEnd);
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
910
|
/**
|
|
963
911
|
* Watch mode
|
|
964
912
|
*/
|
|
965
913
|
|
|
966
914
|
async _watch(hasteMap) {
|
|
967
|
-
var _this$_options$
|
|
915
|
+
var _this$_options$perfLo13, _this$_options$perfLo15;
|
|
968
916
|
|
|
969
|
-
(_this$_options$
|
|
970
|
-
_this$_options$
|
|
917
|
+
(_this$_options$perfLo13 = this._options.perfLogger) === null ||
|
|
918
|
+
_this$_options$perfLo13 === void 0
|
|
971
919
|
? void 0
|
|
972
|
-
: _this$_options$
|
|
920
|
+
: _this$_options$perfLo13.point("watch_start");
|
|
973
921
|
|
|
974
922
|
if (!this._options.watch) {
|
|
975
|
-
var _this$_options$
|
|
923
|
+
var _this$_options$perfLo14;
|
|
976
924
|
|
|
977
|
-
(_this$_options$
|
|
978
|
-
_this$_options$
|
|
925
|
+
(_this$_options$perfLo14 = this._options.perfLogger) === null ||
|
|
926
|
+
_this$_options$perfLo14 === void 0
|
|
979
927
|
? void 0
|
|
980
|
-
: _this$_options$
|
|
928
|
+
: _this$_options$perfLo14.point("watch_end");
|
|
981
929
|
return;
|
|
982
930
|
} // In watch mode, we'll only warn about module collisions and we'll retain
|
|
983
931
|
// all files, even changes to node_modules.
|
|
984
932
|
|
|
985
933
|
this._options.throwOnModuleCollision = false;
|
|
986
|
-
this._options.retainAllFiles = true;
|
|
987
|
-
|
|
988
|
-
const WatcherImpl = (await this._shouldUseWatchman())
|
|
989
|
-
? _WatchmanWatcher.default
|
|
990
|
-
: _FSEventsWatcher.default.isSupported()
|
|
991
|
-
? _FSEventsWatcher.default
|
|
992
|
-
: _NodeWatcher.default;
|
|
993
|
-
let watcher = "node";
|
|
994
|
-
|
|
995
|
-
if (WatcherImpl === _WatchmanWatcher.default) {
|
|
996
|
-
watcher = "watchman";
|
|
997
|
-
} else if (WatcherImpl === _FSEventsWatcher.default) {
|
|
998
|
-
watcher = "fsevents";
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
debug(`Using watcher: ${watcher}`);
|
|
1002
|
-
(_this$_options$perfLo17 = this._options.perfLogger) === null ||
|
|
1003
|
-
_this$_options$perfLo17 === void 0
|
|
1004
|
-
? void 0
|
|
1005
|
-
: _this$_options$perfLo17.annotate({
|
|
1006
|
-
string: {
|
|
1007
|
-
watcher,
|
|
1008
|
-
},
|
|
1009
|
-
});
|
|
934
|
+
this._options.retainAllFiles = true;
|
|
1010
935
|
const extensions = this._options.extensions;
|
|
1011
|
-
const ignorePattern = this._options.ignorePattern;
|
|
1012
936
|
const rootDir = this._options.rootDir;
|
|
1013
937
|
let changeQueue = Promise.resolve();
|
|
1014
938
|
let eventsQueue = []; // We only need to copy the entire haste map once on every "frame".
|
|
1015
939
|
|
|
1016
940
|
let mustCopy = true;
|
|
1017
941
|
|
|
1018
|
-
const createWatcher = (root) => {
|
|
1019
|
-
const watcherOptions = {
|
|
1020
|
-
dot: true,
|
|
1021
|
-
glob: [
|
|
1022
|
-
// Ensure we always include package.json files, which are crucial for
|
|
1023
|
-
/// module resolution.
|
|
1024
|
-
"**/package.json",
|
|
1025
|
-
...extensions.map((extension) => "**/*." + extension),
|
|
1026
|
-
],
|
|
1027
|
-
ignored: ignorePattern,
|
|
1028
|
-
watchmanDeferStates: this._options.watchmanDeferStates,
|
|
1029
|
-
};
|
|
1030
|
-
const watcher = new WatcherImpl(root, watcherOptions);
|
|
1031
|
-
return new Promise((resolve, reject) => {
|
|
1032
|
-
const rejectTimeout = setTimeout(
|
|
1033
|
-
() => reject(new Error("Failed to start watch mode.")),
|
|
1034
|
-
MAX_WAIT_TIME
|
|
1035
|
-
);
|
|
1036
|
-
watcher.once("ready", () => {
|
|
1037
|
-
clearTimeout(rejectTimeout);
|
|
1038
|
-
watcher.on("all", onChange);
|
|
1039
|
-
resolve(watcher);
|
|
1040
|
-
});
|
|
1041
|
-
});
|
|
1042
|
-
};
|
|
1043
|
-
|
|
1044
942
|
const emitChange = () => {
|
|
1045
943
|
if (eventsQueue.length) {
|
|
1046
944
|
mustCopy = true;
|
|
@@ -1213,17 +1111,36 @@ class HasteMap extends _events.default {
|
|
|
1213
1111
|
};
|
|
1214
1112
|
|
|
1215
1113
|
this._changeInterval = setInterval(emitChange, CHANGE_INTERVAL);
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
this._watchers = watchers;
|
|
1221
|
-
(_this$_options$perfLo18 = this._options.perfLogger) === null ||
|
|
1222
|
-
_this$_options$perfLo18 === void 0
|
|
1223
|
-
? void 0
|
|
1224
|
-
: _this$_options$perfLo18.point("watch_end");
|
|
1225
|
-
}
|
|
1114
|
+
(0, _invariant.default)(
|
|
1115
|
+
this._watcher != null,
|
|
1116
|
+
"Expected _watcher to have been initialised by _buildFileMap"
|
|
1226
1117
|
);
|
|
1118
|
+
await this._watcher.watch(onChange);
|
|
1119
|
+
|
|
1120
|
+
if (this._options.healthCheck.enabled) {
|
|
1121
|
+
const performHealthCheck = () => {
|
|
1122
|
+
if (!this._watcher) {
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
this._watcher
|
|
1127
|
+
.checkHealth(this._options.healthCheck.timeout)
|
|
1128
|
+
.then((result) => {
|
|
1129
|
+
this.emit("healthCheck", result);
|
|
1130
|
+
});
|
|
1131
|
+
};
|
|
1132
|
+
|
|
1133
|
+
performHealthCheck();
|
|
1134
|
+
this._healthCheckInterval = setInterval(
|
|
1135
|
+
performHealthCheck,
|
|
1136
|
+
this._options.healthCheck.interval
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
(_this$_options$perfLo15 = this._options.perfLogger) === null ||
|
|
1141
|
+
_this$_options$perfLo15 === void 0
|
|
1142
|
+
? void 0
|
|
1143
|
+
: _this$_options$perfLo15.point("watch_end");
|
|
1227
1144
|
}
|
|
1228
1145
|
/**
|
|
1229
1146
|
* This function should be called when the file under `filePath` is removed
|
|
@@ -1290,12 +1207,15 @@ class HasteMap extends _events.default {
|
|
|
1290
1207
|
clearInterval(this._changeInterval);
|
|
1291
1208
|
}
|
|
1292
1209
|
|
|
1293
|
-
if (
|
|
1210
|
+
if (this._healthCheckInterval) {
|
|
1211
|
+
clearInterval(this._healthCheckInterval);
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
if (!this._watcher) {
|
|
1294
1215
|
return;
|
|
1295
1216
|
}
|
|
1296
1217
|
|
|
1297
|
-
await
|
|
1298
|
-
this._watchers = [];
|
|
1218
|
+
await this._watcher.close();
|
|
1299
1219
|
|
|
1300
1220
|
this._crawlerAbortController.abort();
|
|
1301
1221
|
}
|
|
@@ -1326,14 +1246,14 @@ class HasteMap extends _events.default {
|
|
|
1326
1246
|
)
|
|
1327
1247
|
.then(() => true)
|
|
1328
1248
|
.catch((e) => {
|
|
1329
|
-
var _this$_options$
|
|
1249
|
+
var _this$_options$perfLo16, _e$message;
|
|
1330
1250
|
|
|
1331
1251
|
// TODO: Advise people to either install Watchman or set
|
|
1332
1252
|
// `useWatchman: false` here?
|
|
1333
|
-
(_this$_options$
|
|
1334
|
-
_this$_options$
|
|
1253
|
+
(_this$_options$perfLo16 = this._options.perfLogger) === null ||
|
|
1254
|
+
_this$_options$perfLo16 === void 0
|
|
1335
1255
|
? void 0
|
|
1336
|
-
: _this$_options$
|
|
1256
|
+
: _this$_options$perfLo16.annotate({
|
|
1337
1257
|
string: {
|
|
1338
1258
|
watchmanFailedCapabilityCheck:
|
|
1339
1259
|
(_e$message =
|
package/src/index.js.flow
CHANGED
|
@@ -15,7 +15,6 @@ import type {
|
|
|
15
15
|
CacheManagerFactory,
|
|
16
16
|
ChangeEvent,
|
|
17
17
|
Console,
|
|
18
|
-
CrawlerOptions,
|
|
19
18
|
EventsQueue,
|
|
20
19
|
FileData,
|
|
21
20
|
FileMetaData,
|
|
@@ -31,8 +30,8 @@ import type {
|
|
|
31
30
|
SerializableModuleMap,
|
|
32
31
|
WorkerMetadata,
|
|
33
32
|
} from './flow-types';
|
|
34
|
-
import type {WatcherOptions} from './watchers/common';
|
|
35
33
|
import type {Stats} from 'graceful-fs';
|
|
34
|
+
import type {HealthCheckResult} from './Watcher';
|
|
36
35
|
|
|
37
36
|
import {DiskCacheManager} from './cache/DiskCacheManager';
|
|
38
37
|
import H from './constants';
|
|
@@ -45,10 +44,7 @@ import getPlatformExtension from './lib/getPlatformExtension';
|
|
|
45
44
|
import normalizePathSep from './lib/normalizePathSep';
|
|
46
45
|
import rootRelativeCacheKeys from './lib/rootRelativeCacheKeys';
|
|
47
46
|
import HasteModuleMap from './ModuleMap';
|
|
48
|
-
import
|
|
49
|
-
// $FlowFixMe[untyped-import] - it's a fork: https://github.com/facebook/jest/pull/10919
|
|
50
|
-
import NodeWatcher from './watchers/NodeWatcher';
|
|
51
|
-
import WatchmanWatcher from './watchers/WatchmanWatcher';
|
|
47
|
+
import {Watcher} from './Watcher';
|
|
52
48
|
import {getSha1, worker} from './worker';
|
|
53
49
|
import EventEmitter from 'events';
|
|
54
50
|
import invariant from 'invariant';
|
|
@@ -60,15 +56,12 @@ import * as path from 'path';
|
|
|
60
56
|
// $FlowFixMe[untyped-import] - this is a polyfill
|
|
61
57
|
import AbortController from 'abort-controller';
|
|
62
58
|
|
|
63
|
-
const nodeCrawl = require('./crawlers/node');
|
|
64
|
-
const watchmanCrawl = require('./crawlers/watchman');
|
|
65
|
-
const debug = require('debug')('Metro:FileMap');
|
|
66
|
-
|
|
67
59
|
export type {
|
|
68
60
|
BuildParameters,
|
|
69
61
|
FileData,
|
|
70
62
|
HasteFS,
|
|
71
63
|
HasteMap,
|
|
64
|
+
HealthCheckResult,
|
|
72
65
|
InternalData,
|
|
73
66
|
ModuleMapData,
|
|
74
67
|
ModuleMapItem,
|
|
@@ -101,10 +94,20 @@ export type InputOptions = $ReadOnly<{
|
|
|
101
94
|
watch?: ?boolean,
|
|
102
95
|
console?: Console,
|
|
103
96
|
cacheManagerFactory?: ?CacheManagerFactory,
|
|
97
|
+
|
|
98
|
+
healthCheck: HealthCheckOptions,
|
|
99
|
+
}>;
|
|
100
|
+
|
|
101
|
+
type HealthCheckOptions = $ReadOnly<{
|
|
102
|
+
enabled: boolean,
|
|
103
|
+
interval: number,
|
|
104
|
+
timeout: number,
|
|
105
|
+
filePrefix: string,
|
|
104
106
|
}>;
|
|
105
107
|
|
|
106
108
|
type InternalOptions = {
|
|
107
109
|
...BuildParameters,
|
|
110
|
+
healthCheck: HealthCheckOptions,
|
|
108
111
|
perfLogger: ?PerfLogger,
|
|
109
112
|
resetCache: ?boolean,
|
|
110
113
|
maxWorkers: number,
|
|
@@ -114,10 +117,6 @@ type InternalOptions = {
|
|
|
114
117
|
watchmanDeferStates: $ReadOnlyArray<string>,
|
|
115
118
|
};
|
|
116
119
|
|
|
117
|
-
interface Watcher {
|
|
118
|
-
close(): Promise<void>;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
120
|
type WorkerInterface = {worker: typeof worker, getSha1: typeof getSha1};
|
|
122
121
|
|
|
123
122
|
export const DuplicateHasteCandidatesError =
|
|
@@ -140,7 +139,6 @@ export type {
|
|
|
140
139
|
const CACHE_BREAKER = '2';
|
|
141
140
|
|
|
142
141
|
const CHANGE_INTERVAL = 30;
|
|
143
|
-
const MAX_WAIT_TIME = 240000;
|
|
144
142
|
const NODE_MODULES = path.sep + 'node_modules' + path.sep;
|
|
145
143
|
const PACKAGE_JSON = path.sep + 'package.json';
|
|
146
144
|
const VCS_DIRECTORIES = ['.git', '.hg']
|
|
@@ -237,10 +235,11 @@ export default class HasteMap extends EventEmitter {
|
|
|
237
235
|
_changeInterval: ?IntervalID;
|
|
238
236
|
_console: Console;
|
|
239
237
|
_options: InternalOptions;
|
|
240
|
-
|
|
238
|
+
_watcher: ?Watcher;
|
|
241
239
|
_worker: ?WorkerInterface;
|
|
242
240
|
_cacheManager: CacheManager;
|
|
243
241
|
_crawlerAbortController: typeof AbortController;
|
|
242
|
+
_healthCheckInterval: ?IntervalID;
|
|
244
243
|
|
|
245
244
|
static create(options: InputOptions): HasteMap {
|
|
246
245
|
return new HasteMap(options);
|
|
@@ -297,6 +296,7 @@ export default class HasteMap extends EventEmitter {
|
|
|
297
296
|
|
|
298
297
|
this._options = {
|
|
299
298
|
...buildParameters,
|
|
299
|
+
healthCheck: options.healthCheck,
|
|
300
300
|
maxWorkers: options.maxWorkers,
|
|
301
301
|
perfLogger: options.perfLogger,
|
|
302
302
|
resetCache: options.resetCache,
|
|
@@ -322,7 +322,6 @@ export default class HasteMap extends EventEmitter {
|
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
this._buildPromise = null;
|
|
325
|
-
this._watchers = [];
|
|
326
325
|
this._worker = null;
|
|
327
326
|
this._options.perfLogger?.point('constructor_end');
|
|
328
327
|
this._crawlerAbortController = new AbortController();
|
|
@@ -455,7 +454,40 @@ export default class HasteMap extends EventEmitter {
|
|
|
455
454
|
} catch {
|
|
456
455
|
hasteMap = this._createEmptyMap();
|
|
457
456
|
}
|
|
458
|
-
|
|
457
|
+
|
|
458
|
+
const {
|
|
459
|
+
computeSha1,
|
|
460
|
+
enableSymlinks,
|
|
461
|
+
extensions,
|
|
462
|
+
forceNodeFilesystemAPI,
|
|
463
|
+
ignorePattern,
|
|
464
|
+
perfLogger,
|
|
465
|
+
roots,
|
|
466
|
+
rootDir,
|
|
467
|
+
watch,
|
|
468
|
+
watchmanDeferStates,
|
|
469
|
+
} = this._options;
|
|
470
|
+
|
|
471
|
+
this._watcher = new Watcher({
|
|
472
|
+
abortSignal: this._crawlerAbortController.signal,
|
|
473
|
+
computeSha1,
|
|
474
|
+
console: this._console,
|
|
475
|
+
enableSymlinks,
|
|
476
|
+
extensions,
|
|
477
|
+
forceNodeFilesystemAPI,
|
|
478
|
+
healthCheckFilePrefix: this._options.healthCheck.filePrefix,
|
|
479
|
+
ignore: path => this._ignore(path),
|
|
480
|
+
ignorePattern,
|
|
481
|
+
initialData: hasteMap,
|
|
482
|
+
perfLogger,
|
|
483
|
+
roots,
|
|
484
|
+
rootDir,
|
|
485
|
+
useWatchman: await this._shouldUseWatchman(),
|
|
486
|
+
watch,
|
|
487
|
+
watchmanDeferStates,
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
return this._watcher.crawl().then(result => {
|
|
459
491
|
this._options.perfLogger?.point('buildFileMap_end');
|
|
460
492
|
return result;
|
|
461
493
|
});
|
|
@@ -788,66 +820,6 @@ export default class HasteMap extends EventEmitter {
|
|
|
788
820
|
return this._worker;
|
|
789
821
|
}
|
|
790
822
|
|
|
791
|
-
async _crawl(hasteMap: InternalData): Promise<?(
|
|
792
|
-
| Promise<{
|
|
793
|
-
changedFiles?: FileData,
|
|
794
|
-
hasteMap: InternalData,
|
|
795
|
-
removedFiles: FileData,
|
|
796
|
-
}>
|
|
797
|
-
| {changedFiles?: FileData, hasteMap: InternalData, removedFiles: FileData}
|
|
798
|
-
)> {
|
|
799
|
-
this._options.perfLogger?.point('crawl_start');
|
|
800
|
-
const options = this._options;
|
|
801
|
-
const ignore = (filePath: string) => this._ignore(filePath);
|
|
802
|
-
const crawl = (await this._shouldUseWatchman()) ? watchmanCrawl : nodeCrawl;
|
|
803
|
-
const crawlerOptions: CrawlerOptions = {
|
|
804
|
-
abortSignal: this._crawlerAbortController.signal,
|
|
805
|
-
computeSha1: options.computeSha1,
|
|
806
|
-
data: hasteMap,
|
|
807
|
-
enableSymlinks: options.enableSymlinks,
|
|
808
|
-
extensions: options.extensions,
|
|
809
|
-
forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,
|
|
810
|
-
ignore,
|
|
811
|
-
perfLogger: options.perfLogger,
|
|
812
|
-
rootDir: options.rootDir,
|
|
813
|
-
roots: options.roots,
|
|
814
|
-
};
|
|
815
|
-
|
|
816
|
-
const retry = (error: Error) => {
|
|
817
|
-
if (crawl === watchmanCrawl) {
|
|
818
|
-
this._console.warn(
|
|
819
|
-
'metro-file-map: Watchman crawl failed. Retrying once with node ' +
|
|
820
|
-
'crawler.\n' +
|
|
821
|
-
" Usually this happens when watchman isn't running. Create an " +
|
|
822
|
-
"empty `.watchmanconfig` file in your project's root folder or " +
|
|
823
|
-
'initialize a git or hg repository in your project.\n' +
|
|
824
|
-
' ' +
|
|
825
|
-
error.toString(),
|
|
826
|
-
);
|
|
827
|
-
return nodeCrawl(crawlerOptions).catch(e => {
|
|
828
|
-
throw new Error(
|
|
829
|
-
'Crawler retry failed:\n' +
|
|
830
|
-
` Original error: ${error.message}\n` +
|
|
831
|
-
` Retry error: ${e.message}\n`,
|
|
832
|
-
);
|
|
833
|
-
});
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
throw error;
|
|
837
|
-
};
|
|
838
|
-
|
|
839
|
-
const logEnd = <T>(result: T): T => {
|
|
840
|
-
this._options.perfLogger?.point('crawl_end');
|
|
841
|
-
return result;
|
|
842
|
-
};
|
|
843
|
-
|
|
844
|
-
try {
|
|
845
|
-
return crawl(crawlerOptions).catch(retry).then(logEnd);
|
|
846
|
-
} catch (error) {
|
|
847
|
-
return retry(error).then(logEnd);
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
|
|
851
823
|
/**
|
|
852
824
|
* Watch mode
|
|
853
825
|
*/
|
|
@@ -863,24 +835,7 @@ export default class HasteMap extends EventEmitter {
|
|
|
863
835
|
this._options.throwOnModuleCollision = false;
|
|
864
836
|
this._options.retainAllFiles = true;
|
|
865
837
|
|
|
866
|
-
// WatchmanWatcher > FSEventsWatcher > sane.NodeWatcher
|
|
867
|
-
const WatcherImpl = (await this._shouldUseWatchman())
|
|
868
|
-
? WatchmanWatcher
|
|
869
|
-
: FSEventsWatcher.isSupported()
|
|
870
|
-
? FSEventsWatcher
|
|
871
|
-
: NodeWatcher;
|
|
872
|
-
|
|
873
|
-
let watcher = 'node';
|
|
874
|
-
if (WatcherImpl === WatchmanWatcher) {
|
|
875
|
-
watcher = 'watchman';
|
|
876
|
-
} else if (WatcherImpl === FSEventsWatcher) {
|
|
877
|
-
watcher = 'fsevents';
|
|
878
|
-
}
|
|
879
|
-
debug(`Using watcher: ${watcher}`);
|
|
880
|
-
this._options.perfLogger?.annotate({string: {watcher}});
|
|
881
|
-
|
|
882
838
|
const extensions = this._options.extensions;
|
|
883
|
-
const ignorePattern = this._options.ignorePattern;
|
|
884
839
|
const rootDir = this._options.rootDir;
|
|
885
840
|
|
|
886
841
|
let changeQueue: Promise<null | void> = Promise.resolve();
|
|
@@ -888,34 +843,6 @@ export default class HasteMap extends EventEmitter {
|
|
|
888
843
|
// We only need to copy the entire haste map once on every "frame".
|
|
889
844
|
let mustCopy = true;
|
|
890
845
|
|
|
891
|
-
const createWatcher = (root: Path): Promise<Watcher> => {
|
|
892
|
-
const watcherOptions: WatcherOptions = {
|
|
893
|
-
dot: true,
|
|
894
|
-
glob: [
|
|
895
|
-
// Ensure we always include package.json files, which are crucial for
|
|
896
|
-
/// module resolution.
|
|
897
|
-
'**/package.json',
|
|
898
|
-
...extensions.map(extension => '**/*.' + extension),
|
|
899
|
-
],
|
|
900
|
-
ignored: ignorePattern,
|
|
901
|
-
watchmanDeferStates: this._options.watchmanDeferStates,
|
|
902
|
-
};
|
|
903
|
-
const watcher = new WatcherImpl(root, watcherOptions);
|
|
904
|
-
|
|
905
|
-
return new Promise((resolve, reject) => {
|
|
906
|
-
const rejectTimeout = setTimeout(
|
|
907
|
-
() => reject(new Error('Failed to start watch mode.')),
|
|
908
|
-
MAX_WAIT_TIME,
|
|
909
|
-
);
|
|
910
|
-
|
|
911
|
-
watcher.once('ready', () => {
|
|
912
|
-
clearTimeout(rejectTimeout);
|
|
913
|
-
watcher.on('all', onChange);
|
|
914
|
-
resolve(watcher);
|
|
915
|
-
});
|
|
916
|
-
});
|
|
917
|
-
};
|
|
918
|
-
|
|
919
846
|
const emitChange = () => {
|
|
920
847
|
if (eventsQueue.length) {
|
|
921
848
|
mustCopy = true;
|
|
@@ -1076,10 +1003,30 @@ export default class HasteMap extends EventEmitter {
|
|
|
1076
1003
|
|
|
1077
1004
|
this._changeInterval = setInterval(emitChange, CHANGE_INTERVAL);
|
|
1078
1005
|
|
|
1079
|
-
|
|
1080
|
-
this.
|
|
1081
|
-
|
|
1082
|
-
|
|
1006
|
+
invariant(
|
|
1007
|
+
this._watcher != null,
|
|
1008
|
+
'Expected _watcher to have been initialised by _buildFileMap',
|
|
1009
|
+
);
|
|
1010
|
+
await this._watcher.watch(onChange);
|
|
1011
|
+
|
|
1012
|
+
if (this._options.healthCheck.enabled) {
|
|
1013
|
+
const performHealthCheck = () => {
|
|
1014
|
+
if (!this._watcher) {
|
|
1015
|
+
return;
|
|
1016
|
+
}
|
|
1017
|
+
this._watcher
|
|
1018
|
+
.checkHealth(this._options.healthCheck.timeout)
|
|
1019
|
+
.then(result => {
|
|
1020
|
+
this.emit('healthCheck', result);
|
|
1021
|
+
});
|
|
1022
|
+
};
|
|
1023
|
+
performHealthCheck();
|
|
1024
|
+
this._healthCheckInterval = setInterval(
|
|
1025
|
+
performHealthCheck,
|
|
1026
|
+
this._options.healthCheck.interval,
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
this._options.perfLogger?.point('watch_end');
|
|
1083
1030
|
}
|
|
1084
1031
|
|
|
1085
1032
|
/**
|
|
@@ -1143,14 +1090,14 @@ export default class HasteMap extends EventEmitter {
|
|
|
1143
1090
|
if (this._changeInterval) {
|
|
1144
1091
|
clearInterval(this._changeInterval);
|
|
1145
1092
|
}
|
|
1093
|
+
if (this._healthCheckInterval) {
|
|
1094
|
+
clearInterval(this._healthCheckInterval);
|
|
1095
|
+
}
|
|
1146
1096
|
|
|
1147
|
-
if (!this.
|
|
1097
|
+
if (!this._watcher) {
|
|
1148
1098
|
return;
|
|
1149
1099
|
}
|
|
1150
|
-
|
|
1151
|
-
await Promise.all(this._watchers.map(watcher => watcher.close()));
|
|
1152
|
-
|
|
1153
|
-
this._watchers = [];
|
|
1100
|
+
await this._watcher.close();
|
|
1154
1101
|
this._crawlerAbortController.abort();
|
|
1155
1102
|
}
|
|
1156
1103
|
|