metro-file-map 0.73.3 → 0.73.4
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 +1 -1
- package/src/HasteFS.js.flow +8 -2
- package/src/ModuleMap.js +5 -98
- package/src/ModuleMap.js.flow +4 -111
- package/src/Watcher.js +28 -6
- package/src/Watcher.js.flow +28 -14
- package/src/crawlers/node.js +14 -13
- package/src/crawlers/node.js.flow +12 -20
- package/src/crawlers/watchman/index.js +72 -51
- package/src/crawlers/watchman/index.js.flow +54 -40
- package/src/flow-types.js.flow +57 -20
- package/src/index.js +261 -252
- package/src/index.js.flow +203 -193
- package/src/lib/DuplicateHasteCandidatesError.js +68 -0
- package/src/lib/DuplicateHasteCandidatesError.js.flow +65 -0
package/package.json
CHANGED
package/src/HasteFS.js.flow
CHANGED
|
@@ -8,14 +8,20 @@
|
|
|
8
8
|
* @flow strict-local
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
FileData,
|
|
13
|
+
FileMetaData,
|
|
14
|
+
FileSystem,
|
|
15
|
+
Glob,
|
|
16
|
+
Path,
|
|
17
|
+
} from './flow-types';
|
|
12
18
|
|
|
13
19
|
import H from './constants';
|
|
14
20
|
import * as fastPath from './lib/fast_path';
|
|
15
21
|
import * as path from 'path';
|
|
16
22
|
import {globsToMatcher, replacePathSepForGlob} from 'jest-util';
|
|
17
23
|
|
|
18
|
-
export default class HasteFS {
|
|
24
|
+
export default class HasteFS implements FileSystem {
|
|
19
25
|
+_rootDir: Path;
|
|
20
26
|
+_files: FileData;
|
|
21
27
|
|
package/src/ModuleMap.js
CHANGED
|
@@ -7,6 +7,8 @@ exports.default = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _constants = _interopRequireDefault(require("./constants"));
|
|
9
9
|
|
|
10
|
+
var _DuplicateHasteCandidatesError = require("./lib/DuplicateHasteCandidatesError");
|
|
11
|
+
|
|
10
12
|
var fastPath = _interopRequireWildcard(require("./lib/fast_path"));
|
|
11
13
|
|
|
12
14
|
function _getRequireWildcardCache(nodeInterop) {
|
|
@@ -69,32 +71,6 @@ const EMPTY_OBJ = {};
|
|
|
69
71
|
const EMPTY_MAP = new Map();
|
|
70
72
|
|
|
71
73
|
class ModuleMap {
|
|
72
|
-
// $FlowFixMe[unclear-type] - Refactor away this function
|
|
73
|
-
static _mapToArrayRecursive(map) {
|
|
74
|
-
let arr = Array.from(map);
|
|
75
|
-
|
|
76
|
-
if (arr[0] && arr[0][1] instanceof Map) {
|
|
77
|
-
arr = arr.map(
|
|
78
|
-
// $FlowFixMe[unclear-type] - Refactor away this function
|
|
79
|
-
(el) => [el[0], this._mapToArrayRecursive(el[1])]
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return arr;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
static _mapFromArrayRecursive(arr) { // $FlowFixMe[unclear-type] - Refactor away this function
|
|
87
|
-
if (arr[0] && Array.isArray(arr[1])) {
|
|
88
|
-
// $FlowFixMe[reassign-const] - Refactor away this function
|
|
89
|
-
arr = arr.map((el) => [
|
|
90
|
-
el[0], // $FlowFixMe[unclear-type] - Refactor away this function
|
|
91
|
-
this._mapFromArrayRecursive(el[1]), // $FlowFixMe[unclear-type] - Refactor away this function
|
|
92
|
-
]);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return new Map(arr);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
74
|
constructor(raw) {
|
|
99
75
|
this._raw = raw;
|
|
100
76
|
}
|
|
@@ -129,7 +105,8 @@ class ModuleMap {
|
|
|
129
105
|
return mockPath != null
|
|
130
106
|
? fastPath.resolve(this._raw.rootDir, mockPath)
|
|
131
107
|
: null;
|
|
132
|
-
}
|
|
108
|
+
} // FIXME: This is only used by Meta-internal validation and should be
|
|
109
|
+
// removed or replaced with a less leaky API.
|
|
133
110
|
|
|
134
111
|
getRawModuleMap() {
|
|
135
112
|
return {
|
|
@@ -139,30 +116,6 @@ class ModuleMap {
|
|
|
139
116
|
rootDir: this._raw.rootDir,
|
|
140
117
|
};
|
|
141
118
|
}
|
|
142
|
-
|
|
143
|
-
toJSON() {
|
|
144
|
-
if (!this._json) {
|
|
145
|
-
this._json = {
|
|
146
|
-
duplicates: ModuleMap._mapToArrayRecursive(this._raw.duplicates),
|
|
147
|
-
map: Array.from(this._raw.map),
|
|
148
|
-
mocks: Array.from(this._raw.mocks),
|
|
149
|
-
rootDir: this._raw.rootDir,
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return this._json;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
static fromJSON(serializableModuleMap) {
|
|
157
|
-
return new ModuleMap({
|
|
158
|
-
duplicates: ModuleMap._mapFromArrayRecursive(
|
|
159
|
-
serializableModuleMap.duplicates
|
|
160
|
-
),
|
|
161
|
-
map: new Map(serializableModuleMap.map),
|
|
162
|
-
mocks: new Map(serializableModuleMap.mocks),
|
|
163
|
-
rootDir: serializableModuleMap.rootDir,
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
119
|
/**
|
|
167
120
|
* When looking up a module's data, we walk through each eligible platform for
|
|
168
121
|
* the query. For each platform, we want to check if there are known
|
|
@@ -229,7 +182,7 @@ class ModuleMap {
|
|
|
229
182
|
duplicates.set(duplicatePath, type);
|
|
230
183
|
}
|
|
231
184
|
|
|
232
|
-
throw new DuplicateHasteCandidatesError(
|
|
185
|
+
throw new _DuplicateHasteCandidatesError.DuplicateHasteCandidatesError(
|
|
233
186
|
name,
|
|
234
187
|
platform,
|
|
235
188
|
supportsNativePlatform,
|
|
@@ -248,49 +201,3 @@ class ModuleMap {
|
|
|
248
201
|
}
|
|
249
202
|
|
|
250
203
|
exports.default = ModuleMap;
|
|
251
|
-
|
|
252
|
-
class DuplicateHasteCandidatesError extends Error {
|
|
253
|
-
constructor(name, platform, supportsNativePlatform, duplicatesSet) {
|
|
254
|
-
const platformMessage = getPlatformMessage(platform);
|
|
255
|
-
super(
|
|
256
|
-
`The name \`${name}\` was looked up in the Haste module map. It ` +
|
|
257
|
-
"cannot be resolved, because there exists several different " +
|
|
258
|
-
"files, or packages, that provide a module for " +
|
|
259
|
-
`that particular name and platform. ${platformMessage} You must ` +
|
|
260
|
-
"delete or exclude files until there remains only one of these:\n\n" +
|
|
261
|
-
Array.from(duplicatesSet)
|
|
262
|
-
.map(
|
|
263
|
-
([dupFilePath, dupFileType]) =>
|
|
264
|
-
` * \`${dupFilePath}\` (${getTypeMessage(dupFileType)})\n`
|
|
265
|
-
)
|
|
266
|
-
.sort()
|
|
267
|
-
.join("")
|
|
268
|
-
);
|
|
269
|
-
this.hasteName = name;
|
|
270
|
-
this.platform = platform;
|
|
271
|
-
this.supportsNativePlatform = supportsNativePlatform;
|
|
272
|
-
this.duplicatesSet = duplicatesSet;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function getPlatformMessage(platform) {
|
|
277
|
-
if (platform === _constants.default.GENERIC_PLATFORM) {
|
|
278
|
-
return "The platform is generic (no extension).";
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
return `The platform extension is \`${platform}\`.`;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function getTypeMessage(type) {
|
|
285
|
-
switch (type) {
|
|
286
|
-
case _constants.default.MODULE:
|
|
287
|
-
return "module";
|
|
288
|
-
|
|
289
|
-
case _constants.default.PACKAGE:
|
|
290
|
-
return "package";
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return "unknown";
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
ModuleMap.DuplicateHasteCandidatesError = DuplicateHasteCandidatesError;
|
package/src/ModuleMap.js.flow
CHANGED
|
@@ -16,48 +16,17 @@ import type {
|
|
|
16
16
|
ModuleMetaData,
|
|
17
17
|
Path,
|
|
18
18
|
RawModuleMap,
|
|
19
|
-
SerializableModuleMap,
|
|
20
19
|
} from './flow-types';
|
|
21
20
|
|
|
22
21
|
import H from './constants';
|
|
22
|
+
import {DuplicateHasteCandidatesError} from './lib/DuplicateHasteCandidatesError';
|
|
23
23
|
import * as fastPath from './lib/fast_path';
|
|
24
24
|
|
|
25
25
|
const EMPTY_OBJ: {[string]: ModuleMetaData} = {};
|
|
26
26
|
const EMPTY_MAP = new Map<'g' | 'native' | string, ?DuplicatesSet>();
|
|
27
27
|
|
|
28
|
-
export default class ModuleMap implements IModuleMap
|
|
29
|
-
static DuplicateHasteCandidatesError: Class<DuplicateHasteCandidatesError>;
|
|
28
|
+
export default class ModuleMap implements IModuleMap {
|
|
30
29
|
+_raw: RawModuleMap;
|
|
31
|
-
_json: ?SerializableModuleMap;
|
|
32
|
-
|
|
33
|
-
// $FlowFixMe[unclear-type] - Refactor away this function
|
|
34
|
-
static _mapToArrayRecursive(map: Map<string, any>): Array<[string, any]> {
|
|
35
|
-
let arr = Array.from(map);
|
|
36
|
-
if (arr[0] && arr[0][1] instanceof Map) {
|
|
37
|
-
arr = arr.map(
|
|
38
|
-
// $FlowFixMe[unclear-type] - Refactor away this function
|
|
39
|
-
el => ([el[0], this._mapToArrayRecursive(el[1])]: [string, any]),
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
return arr;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static _mapFromArrayRecursive(
|
|
46
|
-
// $FlowFixMe[unclear-type] - Refactor away this function
|
|
47
|
-
arr: $ReadOnlyArray<[string, any]>,
|
|
48
|
-
// $FlowFixMe[unclear-type] - Refactor away this function
|
|
49
|
-
): Map<string, any> {
|
|
50
|
-
if (arr[0] && Array.isArray(arr[1])) {
|
|
51
|
-
// $FlowFixMe[reassign-const] - Refactor away this function
|
|
52
|
-
arr = (arr.map(el => [
|
|
53
|
-
el[0],
|
|
54
|
-
// $FlowFixMe[unclear-type] - Refactor away this function
|
|
55
|
-
this._mapFromArrayRecursive((el[1]: Array<[string, any]>)),
|
|
56
|
-
// $FlowFixMe[unclear-type] - Refactor away this function
|
|
57
|
-
]): Array<[string, any]>);
|
|
58
|
-
}
|
|
59
|
-
return new Map(arr);
|
|
60
|
-
}
|
|
61
30
|
|
|
62
31
|
constructor(raw: RawModuleMap) {
|
|
63
32
|
this._raw = raw;
|
|
@@ -97,6 +66,8 @@ export default class ModuleMap implements IModuleMap<SerializableModuleMap> {
|
|
|
97
66
|
: null;
|
|
98
67
|
}
|
|
99
68
|
|
|
69
|
+
// FIXME: This is only used by Meta-internal validation and should be
|
|
70
|
+
// removed or replaced with a less leaky API.
|
|
100
71
|
getRawModuleMap(): RawModuleMap {
|
|
101
72
|
return {
|
|
102
73
|
duplicates: this._raw.duplicates,
|
|
@@ -106,31 +77,6 @@ export default class ModuleMap implements IModuleMap<SerializableModuleMap> {
|
|
|
106
77
|
};
|
|
107
78
|
}
|
|
108
79
|
|
|
109
|
-
toJSON(): SerializableModuleMap {
|
|
110
|
-
if (!this._json) {
|
|
111
|
-
this._json = {
|
|
112
|
-
duplicates: (ModuleMap._mapToArrayRecursive(
|
|
113
|
-
this._raw.duplicates,
|
|
114
|
-
): SerializableModuleMap['duplicates']),
|
|
115
|
-
map: Array.from(this._raw.map),
|
|
116
|
-
mocks: Array.from(this._raw.mocks),
|
|
117
|
-
rootDir: this._raw.rootDir,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
return this._json;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
static fromJSON(serializableModuleMap: SerializableModuleMap): ModuleMap {
|
|
124
|
-
return new ModuleMap({
|
|
125
|
-
duplicates: (ModuleMap._mapFromArrayRecursive(
|
|
126
|
-
serializableModuleMap.duplicates,
|
|
127
|
-
): RawModuleMap['duplicates']),
|
|
128
|
-
map: new Map(serializableModuleMap.map),
|
|
129
|
-
mocks: new Map(serializableModuleMap.mocks),
|
|
130
|
-
rootDir: serializableModuleMap.rootDir,
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
80
|
/**
|
|
135
81
|
* When looking up a module's data, we walk through each eligible platform for
|
|
136
82
|
* the query. For each platform, we want to check if there are known
|
|
@@ -215,56 +161,3 @@ export default class ModuleMap implements IModuleMap<SerializableModuleMap> {
|
|
|
215
161
|
});
|
|
216
162
|
}
|
|
217
163
|
}
|
|
218
|
-
|
|
219
|
-
class DuplicateHasteCandidatesError extends Error {
|
|
220
|
-
hasteName: string;
|
|
221
|
-
platform: string | null;
|
|
222
|
-
supportsNativePlatform: boolean;
|
|
223
|
-
duplicatesSet: DuplicatesSet;
|
|
224
|
-
|
|
225
|
-
constructor(
|
|
226
|
-
name: string,
|
|
227
|
-
platform: string,
|
|
228
|
-
supportsNativePlatform: boolean,
|
|
229
|
-
duplicatesSet: DuplicatesSet,
|
|
230
|
-
) {
|
|
231
|
-
const platformMessage = getPlatformMessage(platform);
|
|
232
|
-
super(
|
|
233
|
-
`The name \`${name}\` was looked up in the Haste module map. It ` +
|
|
234
|
-
'cannot be resolved, because there exists several different ' +
|
|
235
|
-
'files, or packages, that provide a module for ' +
|
|
236
|
-
`that particular name and platform. ${platformMessage} You must ` +
|
|
237
|
-
'delete or exclude files until there remains only one of these:\n\n' +
|
|
238
|
-
Array.from(duplicatesSet)
|
|
239
|
-
.map(
|
|
240
|
-
([dupFilePath, dupFileType]) =>
|
|
241
|
-
` * \`${dupFilePath}\` (${getTypeMessage(dupFileType)})\n`,
|
|
242
|
-
)
|
|
243
|
-
.sort()
|
|
244
|
-
.join(''),
|
|
245
|
-
);
|
|
246
|
-
this.hasteName = name;
|
|
247
|
-
this.platform = platform;
|
|
248
|
-
this.supportsNativePlatform = supportsNativePlatform;
|
|
249
|
-
this.duplicatesSet = duplicatesSet;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function getPlatformMessage(platform: string) {
|
|
254
|
-
if (platform === H.GENERIC_PLATFORM) {
|
|
255
|
-
return 'The platform is generic (no extension).';
|
|
256
|
-
}
|
|
257
|
-
return `The platform extension is \`${platform}\`.`;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function getTypeMessage(type: number) {
|
|
261
|
-
switch (type) {
|
|
262
|
-
case H.MODULE:
|
|
263
|
-
return 'module';
|
|
264
|
-
case H.PACKAGE:
|
|
265
|
-
return 'package';
|
|
266
|
-
}
|
|
267
|
-
return 'unknown';
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
ModuleMap.DuplicateHasteCandidatesError = DuplicateHasteCandidatesError;
|
package/src/Watcher.js
CHANGED
|
@@ -25,6 +25,8 @@ var fs = _interopRequireWildcard(require("fs"));
|
|
|
25
25
|
|
|
26
26
|
var _common = require("./watchers/common");
|
|
27
27
|
|
|
28
|
+
var _events = _interopRequireDefault(require("events"));
|
|
29
|
+
|
|
28
30
|
var _perf_hooks = require("perf_hooks");
|
|
29
31
|
|
|
30
32
|
var _nullthrows = _interopRequireDefault(require("nullthrows"));
|
|
@@ -90,12 +92,13 @@ const debug = require("debug")("Metro:Watcher");
|
|
|
90
92
|
const MAX_WAIT_TIME = 240000;
|
|
91
93
|
let nextInstanceId = 0;
|
|
92
94
|
|
|
93
|
-
class Watcher {
|
|
95
|
+
class Watcher extends _events.default {
|
|
94
96
|
_backends = [];
|
|
95
97
|
_nextHealthCheckId = 0;
|
|
96
98
|
_pendingHealthChecks = new Map();
|
|
97
99
|
|
|
98
100
|
constructor(options) {
|
|
101
|
+
super();
|
|
99
102
|
this._options = options;
|
|
100
103
|
this._instanceId = nextInstanceId++;
|
|
101
104
|
}
|
|
@@ -114,21 +117,26 @@ class Watcher {
|
|
|
114
117
|
path.basename(filePath).startsWith(this._options.healthCheckFilePrefix);
|
|
115
118
|
|
|
116
119
|
const crawl = options.useWatchman ? _watchman.default : _node.default;
|
|
120
|
+
let crawler = crawl === _watchman.default ? "watchman" : "node";
|
|
117
121
|
const crawlerOptions = {
|
|
118
122
|
abortSignal: options.abortSignal,
|
|
119
123
|
computeSha1: options.computeSha1,
|
|
120
|
-
data: options.initialData,
|
|
121
124
|
enableSymlinks: options.enableSymlinks,
|
|
122
125
|
extensions: options.extensions,
|
|
123
126
|
forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,
|
|
124
127
|
ignore,
|
|
128
|
+
onStatus: (status) => {
|
|
129
|
+
this.emit("status", status);
|
|
130
|
+
},
|
|
125
131
|
perfLogger: options.perfLogger,
|
|
132
|
+
previousState: options.previousState,
|
|
126
133
|
rootDir: options.rootDir,
|
|
127
134
|
roots: options.roots,
|
|
128
135
|
};
|
|
129
136
|
|
|
130
137
|
const retry = (error) => {
|
|
131
138
|
if (crawl === _watchman.default) {
|
|
139
|
+
crawler = "node";
|
|
132
140
|
options.console.warn(
|
|
133
141
|
"metro-file-map: Watchman crawl failed. Retrying once with node " +
|
|
134
142
|
"crawler.\n" +
|
|
@@ -150,16 +158,30 @@ class Watcher {
|
|
|
150
158
|
throw error;
|
|
151
159
|
};
|
|
152
160
|
|
|
153
|
-
const logEnd = (
|
|
154
|
-
var _this$_options$perfLo2;
|
|
155
|
-
|
|
161
|
+
const logEnd = (delta) => {
|
|
162
|
+
var _delta$clocks$size, _delta$clocks, _this$_options$perfLo2;
|
|
163
|
+
|
|
164
|
+
debug(
|
|
165
|
+
'Crawler "%s" returned %d added/modified, %d removed, %d clock(s).',
|
|
166
|
+
crawler,
|
|
167
|
+
delta.changedFiles.size,
|
|
168
|
+
delta.removedFiles.size,
|
|
169
|
+
(_delta$clocks$size =
|
|
170
|
+
(_delta$clocks = delta.clocks) === null || _delta$clocks === void 0
|
|
171
|
+
? void 0
|
|
172
|
+
: _delta$clocks.size) !== null && _delta$clocks$size !== void 0
|
|
173
|
+
? _delta$clocks$size
|
|
174
|
+
: 0
|
|
175
|
+
);
|
|
156
176
|
(_this$_options$perfLo2 = this._options.perfLogger) === null ||
|
|
157
177
|
_this$_options$perfLo2 === void 0
|
|
158
178
|
? void 0
|
|
159
179
|
: _this$_options$perfLo2.point("crawl_end");
|
|
160
|
-
return
|
|
180
|
+
return delta;
|
|
161
181
|
};
|
|
162
182
|
|
|
183
|
+
debug('Beginning crawl with "%s".', crawler);
|
|
184
|
+
|
|
163
185
|
try {
|
|
164
186
|
return crawl(crawlerOptions).catch(retry).then(logEnd);
|
|
165
187
|
} catch (error) {
|
package/src/Watcher.js.flow
CHANGED
|
@@ -12,9 +12,9 @@ import type {
|
|
|
12
12
|
Console,
|
|
13
13
|
CrawlerOptions,
|
|
14
14
|
FileData,
|
|
15
|
-
InternalData,
|
|
16
15
|
Path,
|
|
17
16
|
PerfLogger,
|
|
17
|
+
WatchmanClocks,
|
|
18
18
|
} from './flow-types';
|
|
19
19
|
import type {WatcherOptions as WatcherBackendOptions} from './watchers/common';
|
|
20
20
|
import type {Stats} from 'fs';
|
|
@@ -28,6 +28,7 @@ import NodeWatcher from './watchers/NodeWatcher';
|
|
|
28
28
|
import * as path from 'path';
|
|
29
29
|
import * as fs from 'fs';
|
|
30
30
|
import {ADD_EVENT, CHANGE_EVENT} from './watchers/common';
|
|
31
|
+
import EventEmitter from 'events';
|
|
31
32
|
import {performance} from 'perf_hooks';
|
|
32
33
|
import nullthrows from 'nullthrows';
|
|
33
34
|
|
|
@@ -35,6 +36,12 @@ const debug = require('debug')('Metro:Watcher');
|
|
|
35
36
|
|
|
36
37
|
const MAX_WAIT_TIME = 240000;
|
|
37
38
|
|
|
39
|
+
type CrawlResult = {
|
|
40
|
+
changedFiles: FileData,
|
|
41
|
+
clocks?: WatchmanClocks,
|
|
42
|
+
removedFiles: FileData,
|
|
43
|
+
};
|
|
44
|
+
|
|
38
45
|
type WatcherOptions = {
|
|
39
46
|
abortSignal: AbortSignal,
|
|
40
47
|
computeSha1: boolean,
|
|
@@ -45,7 +52,7 @@ type WatcherOptions = {
|
|
|
45
52
|
healthCheckFilePrefix: string,
|
|
46
53
|
ignore: string => boolean,
|
|
47
54
|
ignorePattern: RegExp,
|
|
48
|
-
|
|
55
|
+
previousState: CrawlerOptions['previousState'],
|
|
49
56
|
perfLogger: ?PerfLogger,
|
|
50
57
|
roots: $ReadOnlyArray<string>,
|
|
51
58
|
rootDir: string,
|
|
@@ -66,7 +73,7 @@ export type HealthCheckResult =
|
|
|
66
73
|
| {type: 'success', timeout: number, timeElapsed: number, watcher: ?string}
|
|
67
74
|
| {type: 'timeout', timeout: number, watcher: ?string, pauseReason: ?string};
|
|
68
75
|
|
|
69
|
-
export class Watcher {
|
|
76
|
+
export class Watcher extends EventEmitter {
|
|
70
77
|
_options: WatcherOptions;
|
|
71
78
|
_backends: $ReadOnlyArray<WatcherBackend> = [];
|
|
72
79
|
_instanceId: number;
|
|
@@ -76,18 +83,12 @@ export class Watcher {
|
|
|
76
83
|
_activeWatcher: ?string;
|
|
77
84
|
|
|
78
85
|
constructor(options: WatcherOptions) {
|
|
86
|
+
super();
|
|
79
87
|
this._options = options;
|
|
80
88
|
this._instanceId = nextInstanceId++;
|
|
81
89
|
}
|
|
82
90
|
|
|
83
|
-
async crawl(): Promise
|
|
84
|
-
| Promise<{
|
|
85
|
-
changedFiles?: FileData,
|
|
86
|
-
hasteMap: InternalData,
|
|
87
|
-
removedFiles: FileData,
|
|
88
|
-
}>
|
|
89
|
-
| {changedFiles?: FileData, hasteMap: InternalData, removedFiles: FileData}
|
|
90
|
-
)> {
|
|
91
|
+
async crawl(): Promise<CrawlResult> {
|
|
91
92
|
this._options.perfLogger?.point('crawl_start');
|
|
92
93
|
|
|
93
94
|
const options = this._options;
|
|
@@ -95,21 +96,26 @@ export class Watcher {
|
|
|
95
96
|
options.ignore(filePath) ||
|
|
96
97
|
path.basename(filePath).startsWith(this._options.healthCheckFilePrefix);
|
|
97
98
|
const crawl = options.useWatchman ? watchmanCrawl : nodeCrawl;
|
|
99
|
+
let crawler = crawl === watchmanCrawl ? 'watchman' : 'node';
|
|
98
100
|
const crawlerOptions: CrawlerOptions = {
|
|
99
101
|
abortSignal: options.abortSignal,
|
|
100
102
|
computeSha1: options.computeSha1,
|
|
101
|
-
data: options.initialData,
|
|
102
103
|
enableSymlinks: options.enableSymlinks,
|
|
103
104
|
extensions: options.extensions,
|
|
104
105
|
forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,
|
|
105
106
|
ignore,
|
|
107
|
+
onStatus: status => {
|
|
108
|
+
this.emit('status', status);
|
|
109
|
+
},
|
|
106
110
|
perfLogger: options.perfLogger,
|
|
111
|
+
previousState: options.previousState,
|
|
107
112
|
rootDir: options.rootDir,
|
|
108
113
|
roots: options.roots,
|
|
109
114
|
};
|
|
110
115
|
|
|
111
116
|
const retry = (error: Error) => {
|
|
112
117
|
if (crawl === watchmanCrawl) {
|
|
118
|
+
crawler = 'node';
|
|
113
119
|
options.console.warn(
|
|
114
120
|
'metro-file-map: Watchman crawl failed. Retrying once with node ' +
|
|
115
121
|
'crawler.\n' +
|
|
@@ -131,11 +137,19 @@ export class Watcher {
|
|
|
131
137
|
throw error;
|
|
132
138
|
};
|
|
133
139
|
|
|
134
|
-
const logEnd =
|
|
140
|
+
const logEnd = (delta: CrawlResult): CrawlResult => {
|
|
141
|
+
debug(
|
|
142
|
+
'Crawler "%s" returned %d added/modified, %d removed, %d clock(s).',
|
|
143
|
+
crawler,
|
|
144
|
+
delta.changedFiles.size,
|
|
145
|
+
delta.removedFiles.size,
|
|
146
|
+
delta.clocks?.size ?? 0,
|
|
147
|
+
);
|
|
135
148
|
this._options.perfLogger?.point('crawl_end');
|
|
136
|
-
return
|
|
149
|
+
return delta;
|
|
137
150
|
};
|
|
138
151
|
|
|
152
|
+
debug('Beginning crawl with "%s".', crawler);
|
|
139
153
|
try {
|
|
140
154
|
return crawl(crawlerOptions).catch(retry).then(logEnd);
|
|
141
155
|
} catch (error) {
|
package/src/crawlers/node.js
CHANGED
|
@@ -246,7 +246,7 @@ function findNative(roots, extensions, ignore, enableSymlinks, callback) {
|
|
|
246
246
|
|
|
247
247
|
module.exports = async function nodeCrawl(options) {
|
|
248
248
|
const {
|
|
249
|
-
|
|
249
|
+
previousState,
|
|
250
250
|
extensions,
|
|
251
251
|
forceNodeFilesystemAPI,
|
|
252
252
|
ignore,
|
|
@@ -261,28 +261,29 @@ module.exports = async function nodeCrawl(options) {
|
|
|
261
261
|
const useNativeFind = await hasNativeFindSupport(forceNodeFilesystemAPI);
|
|
262
262
|
return new Promise((resolve) => {
|
|
263
263
|
const callback = (list) => {
|
|
264
|
-
const
|
|
265
|
-
const removedFiles = new Map(
|
|
266
|
-
|
|
264
|
+
const changedFiles = new Map();
|
|
265
|
+
const removedFiles = new Map(previousState.files);
|
|
266
|
+
|
|
267
|
+
for (const fileData of list) {
|
|
267
268
|
const [filePath, mtime, size] = fileData;
|
|
268
269
|
const relativeFilePath = fastPath.relative(rootDir, filePath);
|
|
269
|
-
const existingFile =
|
|
270
|
+
const existingFile = previousState.files.get(relativeFilePath);
|
|
271
|
+
removedFiles.delete(relativeFilePath);
|
|
270
272
|
|
|
271
|
-
if (
|
|
272
|
-
|
|
273
|
-
|
|
273
|
+
if (
|
|
274
|
+
existingFile == null ||
|
|
275
|
+
existingFile[_constants.default.MTIME] !== mtime
|
|
276
|
+
) {
|
|
274
277
|
// See ../constants.js; SHA-1 will always be null and fulfilled later.
|
|
275
|
-
|
|
278
|
+
changedFiles.set(relativeFilePath, ["", mtime, size, 0, "", null]);
|
|
276
279
|
}
|
|
280
|
+
}
|
|
277
281
|
|
|
278
|
-
removedFiles.delete(relativeFilePath);
|
|
279
|
-
});
|
|
280
|
-
data.files = files;
|
|
281
282
|
perfLogger === null || perfLogger === void 0
|
|
282
283
|
? void 0
|
|
283
284
|
: perfLogger.point("nodeCrawl_end");
|
|
284
285
|
resolve({
|
|
285
|
-
|
|
286
|
+
changedFiles,
|
|
286
287
|
removedFiles,
|
|
287
288
|
});
|
|
288
289
|
};
|
|
@@ -10,12 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type {Path, FileMetaData} from '../flow-types';
|
|
13
|
-
import type {
|
|
14
|
-
CrawlerOptions,
|
|
15
|
-
FileData,
|
|
16
|
-
IgnoreMatcher,
|
|
17
|
-
InternalData,
|
|
18
|
-
} from '../flow-types';
|
|
13
|
+
import type {CrawlerOptions, FileData, IgnoreMatcher} from '../flow-types';
|
|
19
14
|
|
|
20
15
|
import H from '../constants';
|
|
21
16
|
import * as fastPath from '../lib/fast_path';
|
|
@@ -208,10 +203,10 @@ function findNative(
|
|
|
208
203
|
|
|
209
204
|
module.exports = async function nodeCrawl(options: CrawlerOptions): Promise<{
|
|
210
205
|
removedFiles: FileData,
|
|
211
|
-
|
|
206
|
+
changedFiles: FileData,
|
|
212
207
|
}> {
|
|
213
208
|
const {
|
|
214
|
-
|
|
209
|
+
previousState,
|
|
215
210
|
extensions,
|
|
216
211
|
forceNodeFilesystemAPI,
|
|
217
212
|
ignore,
|
|
@@ -225,25 +220,22 @@ module.exports = async function nodeCrawl(options: CrawlerOptions): Promise<{
|
|
|
225
220
|
|
|
226
221
|
return new Promise(resolve => {
|
|
227
222
|
const callback = (list: Result) => {
|
|
228
|
-
const
|
|
229
|
-
const removedFiles = new Map(
|
|
230
|
-
|
|
223
|
+
const changedFiles = new Map<Path, FileMetaData>();
|
|
224
|
+
const removedFiles = new Map(previousState.files);
|
|
225
|
+
for (const fileData of list) {
|
|
231
226
|
const [filePath, mtime, size] = fileData;
|
|
232
227
|
const relativeFilePath = fastPath.relative(rootDir, filePath);
|
|
233
|
-
const existingFile =
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
} else {
|
|
228
|
+
const existingFile = previousState.files.get(relativeFilePath);
|
|
229
|
+
removedFiles.delete(relativeFilePath);
|
|
230
|
+
if (existingFile == null || existingFile[H.MTIME] !== mtime) {
|
|
237
231
|
// See ../constants.js; SHA-1 will always be null and fulfilled later.
|
|
238
|
-
|
|
232
|
+
changedFiles.set(relativeFilePath, ['', mtime, size, 0, '', null]);
|
|
239
233
|
}
|
|
240
|
-
|
|
241
|
-
});
|
|
242
|
-
data.files = files;
|
|
234
|
+
}
|
|
243
235
|
|
|
244
236
|
perfLogger?.point('nodeCrawl_end');
|
|
245
237
|
resolve({
|
|
246
|
-
|
|
238
|
+
changedFiles,
|
|
247
239
|
removedFiles,
|
|
248
240
|
});
|
|
249
241
|
};
|