metro-file-map 0.83.3 → 0.84.0
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 +4 -3
- package/src/Watcher.js +59 -52
- package/src/Watcher.js.flow +39 -39
- package/src/cache/DiskCacheManager.js.flow +3 -3
- package/src/constants.js +9 -8
- package/src/constants.js.flow +6 -18
- package/src/crawlers/node/index.js +27 -25
- package/src/crawlers/node/index.js.flow +6 -8
- package/src/crawlers/watchman/index.js +26 -22
- package/src/crawlers/watchman/index.js.flow +3 -4
- package/src/crawlers/watchman/planQuery.d.ts +24 -0
- package/src/crawlers/watchman/planQuery.js.flow +4 -4
- package/src/flow-types.js.flow +125 -87
- package/src/index.js +267 -235
- package/src/index.js.flow +269 -275
- package/src/lib/FileProcessor.js +76 -54
- package/src/lib/FileProcessor.js.flow +93 -72
- package/src/lib/RootPathUtils.js +25 -21
- package/src/lib/RootPathUtils.js.flow +4 -4
- package/src/lib/TreeFS.js +72 -77
- package/src/lib/TreeFS.js.flow +104 -124
- package/src/lib/checkWatchmanCapabilities.js.flow +4 -4
- package/src/lib/dependencyExtractor.d.ts +14 -0
- package/src/lib/normalizePathSeparatorsToPosix.js +25 -21
- package/src/lib/normalizePathSeparatorsToPosix.js.flow +3 -3
- package/src/lib/normalizePathSeparatorsToSystem.js +25 -21
- package/src/lib/normalizePathSeparatorsToSystem.js.flow +3 -3
- package/src/lib/rootRelativeCacheKeys.js +0 -20
- package/src/lib/rootRelativeCacheKeys.js.flow +1 -23
- package/src/plugins/DependencyPlugin.js +75 -0
- package/src/plugins/DependencyPlugin.js.flow +144 -0
- package/src/plugins/HastePlugin.js +83 -38
- package/src/plugins/HastePlugin.js.flow +105 -51
- package/src/plugins/MockPlugin.js +7 -4
- package/src/plugins/MockPlugin.js.flow +24 -15
- package/src/plugins/dependencies/dependencyExtractor.d.ts +14 -0
- package/src/{lib → plugins/dependencies}/dependencyExtractor.js.flow +3 -6
- package/src/plugins/dependencies/worker.d.ts +24 -0
- package/src/plugins/dependencies/worker.js +24 -0
- package/src/plugins/dependencies/worker.js.flow +53 -0
- package/src/plugins/haste/HasteConflictsError.js.flow +2 -2
- package/src/plugins/haste/computeConflicts.js +2 -1
- package/src/plugins/haste/computeConflicts.js.flow +11 -12
- package/src/plugins/haste/getPlatformExtension.js.flow +2 -2
- package/src/plugins/haste/worker.d.ts +24 -0
- package/src/plugins/haste/worker.js +35 -0
- package/src/plugins/haste/worker.js.flow +64 -0
- package/src/plugins/mocks/getMockName.js +27 -23
- package/src/plugins/mocks/getMockName.js.flow +2 -4
- package/src/watchers/AbstractWatcher.js +27 -22
- package/src/watchers/AbstractWatcher.js.flow +6 -5
- package/src/watchers/FallbackWatcher.js +88 -84
- package/src/watchers/FallbackWatcher.js.flow +65 -65
- package/src/watchers/NativeWatcher.js +25 -21
- package/src/watchers/NativeWatcher.js.flow +3 -3
- package/src/watchers/RecrawlWarning.js.flow +1 -1
- package/src/watchers/WatchmanWatcher.js +61 -53
- package/src/watchers/WatchmanWatcher.js.flow +39 -38
- package/src/watchers/common.js.flow +5 -5
- package/src/worker.d.ts +36 -0
- package/src/worker.js +16 -58
- package/src/worker.js.flow +19 -69
- package/src/workerExclusionList.d.ts +12 -0
- package/src/workerExclusionList.js.flow +1 -1
- package/src/Watcher.d.ts +0 -24
- package/src/cache/DiskCacheManager.d.ts +0 -38
- package/src/flow-types.d.ts +0 -353
- package/src/index.d.ts +0 -97
- package/src/lib/DuplicateHasteCandidatesError.d.ts +0 -24
- /package/src/{lib → plugins/dependencies}/dependencyExtractor.js +0 -0
package/src/index.js
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true,
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "DependencyPlugin", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _DependencyPlugin.default;
|
|
10
|
+
},
|
|
11
|
+
});
|
|
6
12
|
Object.defineProperty(exports, "DiskCacheManager", {
|
|
7
13
|
enumerable: true,
|
|
8
14
|
get: function () {
|
|
@@ -42,8 +48,6 @@ var _normalizePathSeparatorsToSystem = _interopRequireDefault(
|
|
|
42
48
|
);
|
|
43
49
|
var _RootPathUtils = require("./lib/RootPathUtils");
|
|
44
50
|
var _TreeFS = _interopRequireDefault(require("./lib/TreeFS"));
|
|
45
|
-
var _HastePlugin = _interopRequireDefault(require("./plugins/HastePlugin"));
|
|
46
|
-
var _MockPlugin = _interopRequireDefault(require("./plugins/MockPlugin"));
|
|
47
51
|
var _Watcher = require("./Watcher");
|
|
48
52
|
var _events = _interopRequireDefault(require("events"));
|
|
49
53
|
var _fs = require("fs");
|
|
@@ -51,39 +55,46 @@ var _invariant = _interopRequireDefault(require("invariant"));
|
|
|
51
55
|
var _nullthrows = _interopRequireDefault(require("nullthrows"));
|
|
52
56
|
var path = _interopRequireWildcard(require("path"));
|
|
53
57
|
var _perf_hooks = require("perf_hooks");
|
|
58
|
+
var _DependencyPlugin = _interopRequireDefault(
|
|
59
|
+
require("./plugins/DependencyPlugin"),
|
|
60
|
+
);
|
|
54
61
|
var _DuplicateHasteCandidatesError = require("./plugins/haste/DuplicateHasteCandidatesError");
|
|
55
62
|
var _HasteConflictsError = require("./plugins/haste/HasteConflictsError");
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
a = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
72
|
-
for (var u in e)
|
|
73
|
-
if ("default" !== u && {}.hasOwnProperty.call(e, u)) {
|
|
74
|
-
var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;
|
|
75
|
-
i && (i.get || i.set) ? Object.defineProperty(n, u, i) : (n[u] = e[u]);
|
|
63
|
+
var _HastePlugin = _interopRequireDefault(require("./plugins/HastePlugin"));
|
|
64
|
+
function _interopRequireWildcard(e, t) {
|
|
65
|
+
if ("function" == typeof WeakMap)
|
|
66
|
+
var r = new WeakMap(),
|
|
67
|
+
n = new WeakMap();
|
|
68
|
+
return (_interopRequireWildcard = function (e, t) {
|
|
69
|
+
if (!t && e && e.__esModule) return e;
|
|
70
|
+
var o,
|
|
71
|
+
i,
|
|
72
|
+
f = { __proto__: null, default: e };
|
|
73
|
+
if (null === e || ("object" != typeof e && "function" != typeof e))
|
|
74
|
+
return f;
|
|
75
|
+
if ((o = t ? n : r)) {
|
|
76
|
+
if (o.has(e)) return o.get(e);
|
|
77
|
+
o.set(e, f);
|
|
76
78
|
}
|
|
77
|
-
|
|
79
|
+
for (const t in e)
|
|
80
|
+
"default" !== t &&
|
|
81
|
+
{}.hasOwnProperty.call(e, t) &&
|
|
82
|
+
((i =
|
|
83
|
+
(o = Object.defineProperty) &&
|
|
84
|
+
Object.getOwnPropertyDescriptor(e, t)) &&
|
|
85
|
+
(i.get || i.set)
|
|
86
|
+
? o(f, t, i)
|
|
87
|
+
: (f[t] = e[t]));
|
|
88
|
+
return f;
|
|
89
|
+
})(e, t);
|
|
78
90
|
}
|
|
79
91
|
function _interopRequireDefault(e) {
|
|
80
92
|
return e && e.__esModule ? e : { default: e };
|
|
81
93
|
}
|
|
82
94
|
const debug = require("debug")("Metro:FileMap");
|
|
83
|
-
const CACHE_BREAKER = "
|
|
95
|
+
const CACHE_BREAKER = "11";
|
|
84
96
|
const CHANGE_INTERVAL = 30;
|
|
85
97
|
const NODE_MODULES = path.sep + "node_modules" + path.sep;
|
|
86
|
-
const PACKAGE_JSON = path.sep + "package.json";
|
|
87
98
|
const VCS_DIRECTORIES = /[/\\]\.(git|hg)[/\\]/.source;
|
|
88
99
|
const WATCHMAN_REQUIRED_CAPABILITIES = [
|
|
89
100
|
"field-content.sha1hex",
|
|
@@ -92,18 +103,29 @@ const WATCHMAN_REQUIRED_CAPABILITIES = [
|
|
|
92
103
|
"wildmatch",
|
|
93
104
|
];
|
|
94
105
|
class FileMap extends _events.default {
|
|
95
|
-
#
|
|
96
|
-
#
|
|
106
|
+
#buildPromise;
|
|
107
|
+
#cacheManager;
|
|
108
|
+
#canUseWatchmanPromise;
|
|
109
|
+
#changeID;
|
|
110
|
+
#changeInterval;
|
|
111
|
+
#console;
|
|
112
|
+
#crawlerAbortController;
|
|
113
|
+
#fileProcessor;
|
|
114
|
+
#healthCheckInterval;
|
|
115
|
+
#options;
|
|
116
|
+
#pathUtils;
|
|
97
117
|
#plugins;
|
|
118
|
+
#startupPerfLogger;
|
|
119
|
+
#watcher;
|
|
98
120
|
static create(options) {
|
|
99
121
|
return new FileMap(options);
|
|
100
122
|
}
|
|
101
123
|
constructor(options) {
|
|
102
124
|
super();
|
|
103
125
|
if (options.perfLoggerFactory) {
|
|
104
|
-
this
|
|
126
|
+
this.#startupPerfLogger =
|
|
105
127
|
options.perfLoggerFactory?.("START_UP").subSpan("fileMap") ?? null;
|
|
106
|
-
this
|
|
128
|
+
this.#startupPerfLogger?.point("constructor_start");
|
|
107
129
|
}
|
|
108
130
|
let ignorePattern;
|
|
109
131
|
if (options.ignorePattern) {
|
|
@@ -121,49 +143,35 @@ class FileMap extends _events.default {
|
|
|
121
143
|
} else {
|
|
122
144
|
ignorePattern = new RegExp(VCS_DIRECTORIES);
|
|
123
145
|
}
|
|
124
|
-
this
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
});
|
|
135
|
-
const plugins = [this.#hastePlugin];
|
|
136
|
-
if (options.mocksPattern != null && options.mocksPattern !== "") {
|
|
137
|
-
this.#mockPlugin = new _MockPlugin.default({
|
|
138
|
-
console: this._console,
|
|
139
|
-
mocksPattern: new RegExp(options.mocksPattern),
|
|
140
|
-
rootDir: options.rootDir,
|
|
141
|
-
throwOnModuleCollision,
|
|
146
|
+
this.#console = options.console || global.console;
|
|
147
|
+
let dataSlot = _constants.default.PLUGINDATA;
|
|
148
|
+
const indexedPlugins = [];
|
|
149
|
+
const pluginWorkers = [];
|
|
150
|
+
const plugins = options.plugins ?? [];
|
|
151
|
+
for (const plugin of plugins) {
|
|
152
|
+
const maybeWorker = plugin.getWorker();
|
|
153
|
+
indexedPlugins.push({
|
|
154
|
+
plugin,
|
|
155
|
+
dataIdx: maybeWorker != null ? dataSlot++ : null,
|
|
142
156
|
});
|
|
143
|
-
|
|
157
|
+
if (maybeWorker != null) {
|
|
158
|
+
pluginWorkers.push(maybeWorker);
|
|
159
|
+
}
|
|
144
160
|
}
|
|
145
|
-
this.#plugins =
|
|
161
|
+
this.#plugins = indexedPlugins;
|
|
146
162
|
const buildParameters = {
|
|
147
|
-
|
|
148
|
-
options.computeDependencies == null
|
|
149
|
-
? true
|
|
150
|
-
: options.computeDependencies,
|
|
163
|
+
cacheBreaker: CACHE_BREAKER,
|
|
151
164
|
computeSha1: options.computeSha1 || false,
|
|
152
|
-
dependencyExtractor: options.dependencyExtractor ?? null,
|
|
153
|
-
enableHastePackages,
|
|
154
165
|
enableSymlinks: options.enableSymlinks || false,
|
|
155
166
|
extensions: options.extensions,
|
|
156
167
|
forceNodeFilesystemAPI: !!options.forceNodeFilesystemAPI,
|
|
157
|
-
hasteImplModulePath: options.hasteImplModulePath,
|
|
158
168
|
ignorePattern,
|
|
159
|
-
plugins
|
|
169
|
+
plugins,
|
|
160
170
|
retainAllFiles: options.retainAllFiles,
|
|
161
171
|
rootDir: options.rootDir,
|
|
162
172
|
roots: Array.from(new Set(options.roots)),
|
|
163
|
-
skipPackageJson: !!options.skipPackageJson,
|
|
164
|
-
cacheBreaker: CACHE_BREAKER,
|
|
165
173
|
};
|
|
166
|
-
this
|
|
174
|
+
this.#options = {
|
|
167
175
|
...buildParameters,
|
|
168
176
|
healthCheck: options.healthCheck,
|
|
169
177
|
perfLoggerFactory: options.perfLoggerFactory,
|
|
@@ -175,30 +183,28 @@ class FileMap extends _events.default {
|
|
|
175
183
|
const cacheFactoryOptions = {
|
|
176
184
|
buildParameters,
|
|
177
185
|
};
|
|
178
|
-
this
|
|
186
|
+
this.#cacheManager = options.cacheManagerFactory
|
|
179
187
|
? options.cacheManagerFactory.call(null, cacheFactoryOptions)
|
|
180
188
|
: new _DiskCacheManager.DiskCacheManager(cacheFactoryOptions, {});
|
|
181
|
-
this
|
|
182
|
-
dependencyExtractor: buildParameters.dependencyExtractor,
|
|
183
|
-
enableHastePackages: buildParameters.enableHastePackages,
|
|
184
|
-
enableWorkerThreads: options.enableWorkerThreads ?? false,
|
|
185
|
-
hasteImplModulePath: buildParameters.hasteImplModulePath,
|
|
189
|
+
this.#fileProcessor = new _FileProcessor.FileProcessor({
|
|
186
190
|
maxFilesPerWorker: options.maxFilesPerWorker,
|
|
187
191
|
maxWorkers: options.maxWorkers,
|
|
188
|
-
perfLogger: this
|
|
192
|
+
perfLogger: this.#startupPerfLogger,
|
|
193
|
+
pluginWorkers,
|
|
194
|
+
rootDir: options.rootDir,
|
|
189
195
|
});
|
|
190
|
-
this
|
|
191
|
-
this
|
|
192
|
-
this
|
|
193
|
-
this
|
|
194
|
-
this
|
|
196
|
+
this.#buildPromise = null;
|
|
197
|
+
this.#pathUtils = new _RootPathUtils.RootPathUtils(options.rootDir);
|
|
198
|
+
this.#startupPerfLogger?.point("constructor_end");
|
|
199
|
+
this.#crawlerAbortController = new AbortController();
|
|
200
|
+
this.#changeID = 0;
|
|
195
201
|
}
|
|
196
202
|
build() {
|
|
197
|
-
this
|
|
198
|
-
if (!this
|
|
199
|
-
this
|
|
203
|
+
this.#startupPerfLogger?.point("build_start");
|
|
204
|
+
if (!this.#buildPromise) {
|
|
205
|
+
this.#buildPromise = (async () => {
|
|
200
206
|
let initialData;
|
|
201
|
-
if (this.
|
|
207
|
+
if (this.#options.resetCache !== true) {
|
|
202
208
|
initialData = await this.read();
|
|
203
209
|
}
|
|
204
210
|
if (!initialData) {
|
|
@@ -206,53 +212,82 @@ class FileMap extends _events.default {
|
|
|
206
212
|
} else {
|
|
207
213
|
debug("Cache loaded (%d clock(s))", initialData.clocks.size);
|
|
208
214
|
}
|
|
209
|
-
const rootDir = this.
|
|
210
|
-
this
|
|
211
|
-
const processFile = (
|
|
212
|
-
const result = this.
|
|
213
|
-
|
|
215
|
+
const rootDir = this.#options.rootDir;
|
|
216
|
+
this.#startupPerfLogger?.point("constructFileSystem_start");
|
|
217
|
+
const processFile = (normalPath, metadata, opts) => {
|
|
218
|
+
const result = this.#fileProcessor.processRegularFile(
|
|
219
|
+
normalPath,
|
|
214
220
|
metadata,
|
|
215
221
|
{
|
|
216
222
|
computeSha1: opts.computeSha1,
|
|
217
|
-
computeDependencies: false,
|
|
218
223
|
maybeReturnContent: true,
|
|
219
224
|
},
|
|
220
225
|
);
|
|
221
|
-
debug("Lazily processed file: %s",
|
|
226
|
+
debug("Lazily processed file: %s", normalPath);
|
|
222
227
|
this.emit("metadata");
|
|
223
228
|
return result?.content;
|
|
224
229
|
};
|
|
225
230
|
const fileSystem =
|
|
226
231
|
initialData != null
|
|
227
232
|
? _TreeFS.default.fromDeserializedSnapshot({
|
|
228
|
-
rootDir,
|
|
229
233
|
fileSystemData: initialData.fileSystemData,
|
|
230
234
|
processFile,
|
|
235
|
+
rootDir,
|
|
231
236
|
})
|
|
232
237
|
: new _TreeFS.default({
|
|
233
|
-
rootDir,
|
|
234
238
|
processFile,
|
|
239
|
+
rootDir,
|
|
235
240
|
});
|
|
236
|
-
this
|
|
241
|
+
this.#startupPerfLogger?.point("constructFileSystem_end");
|
|
237
242
|
const plugins = this.#plugins;
|
|
238
243
|
const [fileDelta] = await Promise.all([
|
|
239
|
-
this
|
|
240
|
-
fileSystem,
|
|
244
|
+
this.#buildFileDelta({
|
|
241
245
|
clocks: initialData?.clocks ?? new Map(),
|
|
246
|
+
fileSystem,
|
|
242
247
|
}),
|
|
243
248
|
Promise.all(
|
|
244
|
-
plugins.map((plugin) =>
|
|
249
|
+
plugins.map(({ plugin, dataIdx }) =>
|
|
245
250
|
plugin.initialize({
|
|
246
|
-
files:
|
|
251
|
+
files: {
|
|
252
|
+
lookup: (mixedPath) => {
|
|
253
|
+
const result = fileSystem.lookup(mixedPath);
|
|
254
|
+
if (!result.exists) {
|
|
255
|
+
return {
|
|
256
|
+
exists: false,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
if (result.type === "d") {
|
|
260
|
+
return {
|
|
261
|
+
exists: true,
|
|
262
|
+
type: "d",
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
exists: true,
|
|
267
|
+
type: "f",
|
|
268
|
+
pluginData:
|
|
269
|
+
dataIdx != null ? result.metadata[dataIdx] : null,
|
|
270
|
+
};
|
|
271
|
+
},
|
|
272
|
+
fileIterator: (opts) =>
|
|
273
|
+
mapIterator(
|
|
274
|
+
fileSystem.metadataIterator(opts),
|
|
275
|
+
({ baseName, canonicalPath, metadata }) => ({
|
|
276
|
+
baseName,
|
|
277
|
+
canonicalPath,
|
|
278
|
+
pluginData: dataIdx != null ? metadata[dataIdx] : null,
|
|
279
|
+
}),
|
|
280
|
+
),
|
|
281
|
+
},
|
|
247
282
|
pluginState: initialData?.plugins.get(plugin.name),
|
|
248
283
|
}),
|
|
249
284
|
),
|
|
250
285
|
),
|
|
251
286
|
]);
|
|
252
|
-
await this
|
|
253
|
-
plugins.forEach((plugin) => plugin.assertValid());
|
|
287
|
+
await this.#applyFileDelta(fileSystem, plugins, fileDelta);
|
|
288
|
+
plugins.forEach(({ plugin }) => plugin.assertValid());
|
|
254
289
|
const watchmanClocks = new Map(fileDelta.clocks ?? []);
|
|
255
|
-
await this
|
|
290
|
+
await this.#takeSnapshotAndPersist(
|
|
256
291
|
fileSystem,
|
|
257
292
|
watchmanClocks,
|
|
258
293
|
plugins,
|
|
@@ -264,40 +299,38 @@ class FileMap extends _events.default {
|
|
|
264
299
|
fileDelta.changedFiles.size,
|
|
265
300
|
fileDelta.removedFiles.size,
|
|
266
301
|
);
|
|
267
|
-
await this
|
|
302
|
+
await this.#watch(fileSystem, watchmanClocks, plugins);
|
|
268
303
|
return {
|
|
269
304
|
fileSystem,
|
|
270
|
-
hasteMap: this.#hastePlugin,
|
|
271
|
-
mockMap: this.#mockPlugin,
|
|
272
305
|
};
|
|
273
306
|
})();
|
|
274
307
|
}
|
|
275
|
-
return this.
|
|
276
|
-
this
|
|
308
|
+
return this.#buildPromise.then((result) => {
|
|
309
|
+
this.#startupPerfLogger?.point("build_end");
|
|
277
310
|
return result;
|
|
278
311
|
});
|
|
279
312
|
}
|
|
280
313
|
async read() {
|
|
281
314
|
let data;
|
|
282
|
-
this
|
|
315
|
+
this.#startupPerfLogger?.point("read_start");
|
|
283
316
|
try {
|
|
284
|
-
data = await this.
|
|
317
|
+
data = await this.#cacheManager.read();
|
|
285
318
|
} catch (e) {
|
|
286
|
-
this.
|
|
319
|
+
this.#console.warn(
|
|
287
320
|
"Error while reading cache, falling back to a full crawl:\n",
|
|
288
321
|
e,
|
|
289
322
|
);
|
|
290
|
-
this
|
|
323
|
+
this.#startupPerfLogger?.annotate({
|
|
291
324
|
string: {
|
|
292
325
|
cacheReadError: e.toString(),
|
|
293
326
|
},
|
|
294
327
|
});
|
|
295
328
|
}
|
|
296
|
-
this
|
|
329
|
+
this.#startupPerfLogger?.point("read_end");
|
|
297
330
|
return data;
|
|
298
331
|
}
|
|
299
|
-
async
|
|
300
|
-
this
|
|
332
|
+
async #buildFileDelta(previousState) {
|
|
333
|
+
this.#startupPerfLogger?.point("buildFileDelta_start");
|
|
301
334
|
const {
|
|
302
335
|
computeSha1,
|
|
303
336
|
enableSymlinks,
|
|
@@ -309,15 +342,15 @@ class FileMap extends _events.default {
|
|
|
309
342
|
rootDir,
|
|
310
343
|
watch,
|
|
311
344
|
watchmanDeferStates,
|
|
312
|
-
} = this
|
|
313
|
-
this
|
|
314
|
-
abortSignal: this.
|
|
345
|
+
} = this.#options;
|
|
346
|
+
this.#watcher = new _Watcher.Watcher({
|
|
347
|
+
abortSignal: this.#crawlerAbortController.signal,
|
|
315
348
|
computeSha1,
|
|
316
|
-
console: this
|
|
349
|
+
console: this.#console,
|
|
317
350
|
enableSymlinks,
|
|
318
351
|
extensions,
|
|
319
352
|
forceNodeFilesystemAPI,
|
|
320
|
-
healthCheckFilePrefix: this.
|
|
353
|
+
healthCheckFilePrefix: this.#options.healthCheck.filePrefix,
|
|
321
354
|
ignoreForCrawl: (filePath) => {
|
|
322
355
|
const ignoreMatched = ignorePattern.test(filePath);
|
|
323
356
|
return (
|
|
@@ -325,36 +358,38 @@ class FileMap extends _events.default {
|
|
|
325
358
|
);
|
|
326
359
|
},
|
|
327
360
|
ignorePatternForWatch: ignorePattern,
|
|
328
|
-
perfLogger: this
|
|
361
|
+
perfLogger: this.#startupPerfLogger,
|
|
329
362
|
previousState,
|
|
330
|
-
roots,
|
|
331
363
|
rootDir,
|
|
332
|
-
|
|
364
|
+
roots,
|
|
365
|
+
useWatchman: await this.#shouldUseWatchman(),
|
|
333
366
|
watch,
|
|
334
367
|
watchmanDeferStates,
|
|
335
368
|
});
|
|
336
|
-
const watcher = this
|
|
369
|
+
const watcher = this.#watcher;
|
|
337
370
|
watcher.on("status", (status) => this.emit("status", status));
|
|
338
371
|
return watcher.crawl().then((result) => {
|
|
339
|
-
this
|
|
372
|
+
this.#startupPerfLogger?.point("buildFileDelta_end");
|
|
340
373
|
return result;
|
|
341
374
|
});
|
|
342
375
|
}
|
|
343
|
-
|
|
376
|
+
#maybeReadLink(normalPath, fileMetadata) {
|
|
344
377
|
if (fileMetadata[_constants.default.SYMLINK] === 1) {
|
|
345
|
-
return _fs.promises
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
378
|
+
return _fs.promises
|
|
379
|
+
.readlink(this.#pathUtils.normalToAbsolute(normalPath))
|
|
380
|
+
.then((symlinkTarget) => {
|
|
381
|
+
fileMetadata[_constants.default.VISITED] = 1;
|
|
382
|
+
fileMetadata[_constants.default.SYMLINK] = symlinkTarget;
|
|
383
|
+
});
|
|
349
384
|
}
|
|
350
385
|
return null;
|
|
351
386
|
}
|
|
352
|
-
async
|
|
353
|
-
this
|
|
387
|
+
async #applyFileDelta(fileSystem, plugins, delta) {
|
|
388
|
+
this.#startupPerfLogger?.point("applyFileDelta_start");
|
|
354
389
|
const { changedFiles, removedFiles } = delta;
|
|
355
|
-
this
|
|
390
|
+
this.#startupPerfLogger?.point("applyFileDelta_preprocess_start");
|
|
356
391
|
const missingFiles = new Set();
|
|
357
|
-
this
|
|
392
|
+
this.#startupPerfLogger?.point("applyFileDelta_remove_start");
|
|
358
393
|
const removed = [];
|
|
359
394
|
for (const relativeFilePath of removedFiles) {
|
|
360
395
|
const metadata = fileSystem.remove(relativeFilePath);
|
|
@@ -362,42 +397,23 @@ class FileMap extends _events.default {
|
|
|
362
397
|
removed.push([relativeFilePath, metadata]);
|
|
363
398
|
}
|
|
364
399
|
}
|
|
365
|
-
this
|
|
400
|
+
this.#startupPerfLogger?.point("applyFileDelta_remove_end");
|
|
366
401
|
const readLinkPromises = [];
|
|
367
402
|
const readLinkErrors = [];
|
|
368
403
|
const filesToProcess = [];
|
|
369
|
-
for (const [
|
|
404
|
+
for (const [normalFilePath, fileData] of changedFiles) {
|
|
370
405
|
if (fileData[_constants.default.VISITED] === 1) {
|
|
371
406
|
continue;
|
|
372
407
|
}
|
|
373
|
-
if (
|
|
374
|
-
this._options.skipPackageJson &&
|
|
375
|
-
relativeFilePath.endsWith(PACKAGE_JSON)
|
|
376
|
-
) {
|
|
377
|
-
continue;
|
|
378
|
-
}
|
|
379
|
-
if (
|
|
380
|
-
fileData[_constants.default.SYMLINK] === 0 &&
|
|
381
|
-
!this._options.computeDependencies &&
|
|
382
|
-
!this._options.computeSha1 &&
|
|
383
|
-
this._options.hasteImplModulePath == null &&
|
|
384
|
-
!(
|
|
385
|
-
this._options.enableHastePackages &&
|
|
386
|
-
relativeFilePath.endsWith(PACKAGE_JSON)
|
|
387
|
-
)
|
|
388
|
-
) {
|
|
389
|
-
continue;
|
|
390
|
-
}
|
|
391
|
-
const absolutePath = this._pathUtils.normalToAbsolute(relativeFilePath);
|
|
392
408
|
if (fileData[_constants.default.SYMLINK] === 0) {
|
|
393
|
-
filesToProcess.push([
|
|
409
|
+
filesToProcess.push([normalFilePath, fileData]);
|
|
394
410
|
} else {
|
|
395
|
-
const maybeReadLink = this
|
|
411
|
+
const maybeReadLink = this.#maybeReadLink(normalFilePath, fileData);
|
|
396
412
|
if (maybeReadLink) {
|
|
397
413
|
readLinkPromises.push(
|
|
398
414
|
maybeReadLink.catch((error) =>
|
|
399
415
|
readLinkErrors.push({
|
|
400
|
-
|
|
416
|
+
normalFilePath,
|
|
401
417
|
error,
|
|
402
418
|
}),
|
|
403
419
|
),
|
|
@@ -405,28 +421,27 @@ class FileMap extends _events.default {
|
|
|
405
421
|
}
|
|
406
422
|
}
|
|
407
423
|
}
|
|
408
|
-
this
|
|
424
|
+
this.#startupPerfLogger?.point("applyFileDelta_preprocess_end");
|
|
409
425
|
debug(
|
|
410
|
-
"
|
|
426
|
+
"Found %d added/modified files and %d symlinks.",
|
|
411
427
|
filesToProcess.length,
|
|
412
428
|
readLinkPromises.length,
|
|
413
429
|
);
|
|
414
|
-
this
|
|
430
|
+
this.#startupPerfLogger?.point("applyFileDelta_process_start");
|
|
415
431
|
const [batchResult] = await Promise.all([
|
|
416
|
-
this.
|
|
417
|
-
computeSha1: this.
|
|
418
|
-
computeDependencies: this._options.computeDependencies,
|
|
432
|
+
this.#fileProcessor.processBatch(filesToProcess, {
|
|
433
|
+
computeSha1: this.#options.computeSha1,
|
|
419
434
|
maybeReturnContent: false,
|
|
420
435
|
}),
|
|
421
436
|
Promise.all(readLinkPromises),
|
|
422
437
|
]);
|
|
423
|
-
this
|
|
424
|
-
this
|
|
425
|
-
for (const {
|
|
438
|
+
this.#startupPerfLogger?.point("applyFileDelta_process_end");
|
|
439
|
+
this.#startupPerfLogger?.point("applyFileDelta_missing_start");
|
|
440
|
+
for (const { normalFilePath, error } of batchResult.errors.concat(
|
|
426
441
|
readLinkErrors,
|
|
427
442
|
)) {
|
|
428
443
|
if (["ENOENT", "EACCESS"].includes(error.code)) {
|
|
429
|
-
missingFiles.add(
|
|
444
|
+
missingFiles.add(normalFilePath);
|
|
430
445
|
} else {
|
|
431
446
|
throw error;
|
|
432
447
|
}
|
|
@@ -438,30 +453,34 @@ class FileMap extends _events.default {
|
|
|
438
453
|
removed.push([relativeFilePath, metadata]);
|
|
439
454
|
}
|
|
440
455
|
}
|
|
441
|
-
this
|
|
442
|
-
this
|
|
456
|
+
this.#startupPerfLogger?.point("applyFileDelta_missing_end");
|
|
457
|
+
this.#startupPerfLogger?.point("applyFileDelta_add_start");
|
|
443
458
|
fileSystem.bulkAddOrModify(changedFiles);
|
|
444
|
-
this
|
|
445
|
-
this
|
|
459
|
+
this.#startupPerfLogger?.point("applyFileDelta_add_end");
|
|
460
|
+
this.#startupPerfLogger?.point("applyFileDelta_updatePlugins_start");
|
|
446
461
|
await Promise.all([
|
|
447
|
-
plugins.map((plugin) =>
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
462
|
+
plugins.map(({ plugin, dataIdx }) => {
|
|
463
|
+
const mapFn =
|
|
464
|
+
dataIdx != null
|
|
465
|
+
? ([relativePath, fileData]) => [relativePath, fileData[dataIdx]]
|
|
466
|
+
: ([relativePath, fileData]) => [relativePath, null];
|
|
467
|
+
return plugin.bulkUpdate({
|
|
468
|
+
addedOrModified: mapIterator(changedFiles.entries(), mapFn),
|
|
469
|
+
removed: mapIterator(removed.values(), mapFn),
|
|
470
|
+
});
|
|
471
|
+
}),
|
|
453
472
|
]);
|
|
454
|
-
this
|
|
455
|
-
this
|
|
473
|
+
this.#startupPerfLogger?.point("applyFileDelta_updatePlugins_end");
|
|
474
|
+
this.#startupPerfLogger?.point("applyFileDelta_end");
|
|
456
475
|
}
|
|
457
|
-
async
|
|
458
|
-
this
|
|
459
|
-
await this.
|
|
476
|
+
async #takeSnapshotAndPersist(fileSystem, clocks, plugins, changed, removed) {
|
|
477
|
+
this.#startupPerfLogger?.point("persist_start");
|
|
478
|
+
await this.#cacheManager.write(
|
|
460
479
|
() => ({
|
|
461
|
-
fileSystemData: fileSystem.getSerializableSnapshot(),
|
|
462
480
|
clocks: new Map(clocks),
|
|
481
|
+
fileSystemData: fileSystem.getSerializableSnapshot(),
|
|
463
482
|
plugins: new Map(
|
|
464
|
-
plugins.map((plugin) => [
|
|
483
|
+
plugins.map(({ plugin }) => [
|
|
465
484
|
plugin.name,
|
|
466
485
|
plugin.getSerializableSnapshot(),
|
|
467
486
|
]),
|
|
@@ -480,20 +499,20 @@ class FileMap extends _events.default {
|
|
|
480
499
|
},
|
|
481
500
|
},
|
|
482
501
|
onWriteError: (error) => {
|
|
483
|
-
this.
|
|
502
|
+
this.#console.warn("[metro-file-map] Cache write error\n:", error);
|
|
484
503
|
},
|
|
485
504
|
},
|
|
486
505
|
);
|
|
487
|
-
this
|
|
506
|
+
this.#startupPerfLogger?.point("persist_end");
|
|
488
507
|
}
|
|
489
|
-
async
|
|
490
|
-
this
|
|
491
|
-
if (!this.
|
|
492
|
-
this
|
|
508
|
+
async #watch(fileSystem, clocks, plugins) {
|
|
509
|
+
this.#startupPerfLogger?.point("watch_start");
|
|
510
|
+
if (!this.#options.watch) {
|
|
511
|
+
this.#startupPerfLogger?.point("watch_end");
|
|
493
512
|
return;
|
|
494
513
|
}
|
|
495
514
|
const hasWatchedExtension = (filePath) =>
|
|
496
|
-
this.
|
|
515
|
+
this.#options.extensions.some((ext) => filePath.endsWith(ext));
|
|
497
516
|
let changeQueue = Promise.resolve();
|
|
498
517
|
let nextEmit = null;
|
|
499
518
|
const emitChange = () => {
|
|
@@ -502,8 +521,8 @@ class FileMap extends _events.default {
|
|
|
502
521
|
}
|
|
503
522
|
const { eventsQueue, firstEventTimestamp, firstEnqueuedTimestamp } =
|
|
504
523
|
nextEmit;
|
|
505
|
-
const hmrPerfLogger = this.
|
|
506
|
-
key: this
|
|
524
|
+
const hmrPerfLogger = this.#options.perfLoggerFactory?.("HMR", {
|
|
525
|
+
key: this.#getNextChangeID(),
|
|
507
526
|
});
|
|
508
527
|
if (hmrPerfLogger != null) {
|
|
509
528
|
hmrPerfLogger.start({
|
|
@@ -521,8 +540,8 @@ class FileMap extends _events.default {
|
|
|
521
540
|
hmrPerfLogger.point("fileChange_start");
|
|
522
541
|
}
|
|
523
542
|
const changeEvent = {
|
|
524
|
-
logger: hmrPerfLogger,
|
|
525
543
|
eventsQueue,
|
|
544
|
+
logger: hmrPerfLogger,
|
|
526
545
|
};
|
|
527
546
|
this.emit("change", changeEvent);
|
|
528
547
|
nextEmit = null;
|
|
@@ -533,7 +552,7 @@ class FileMap extends _events.default {
|
|
|
533
552
|
(change.metadata.type === "d" ||
|
|
534
553
|
(change.metadata.type === "f" &&
|
|
535
554
|
!hasWatchedExtension(change.relativePath)) ||
|
|
536
|
-
(!this.
|
|
555
|
+
(!this.#options.enableSymlinks && change.metadata?.type === "l"))
|
|
537
556
|
) {
|
|
538
557
|
return;
|
|
539
558
|
}
|
|
@@ -541,11 +560,11 @@ class FileMap extends _events.default {
|
|
|
541
560
|
change.root,
|
|
542
561
|
(0, _normalizePathSeparatorsToSystem.default)(change.relativePath),
|
|
543
562
|
);
|
|
544
|
-
if (this.
|
|
563
|
+
if (this.#options.ignorePattern.test(absoluteFilePath)) {
|
|
545
564
|
return;
|
|
546
565
|
}
|
|
547
566
|
const relativeFilePath =
|
|
548
|
-
this.
|
|
567
|
+
this.#pathUtils.absoluteToNormal(absoluteFilePath);
|
|
549
568
|
const linkStats = fileSystem.linkStats(relativeFilePath);
|
|
550
569
|
if (
|
|
551
570
|
change.event === "touch" &&
|
|
@@ -592,10 +611,10 @@ class FileMap extends _events.default {
|
|
|
592
611
|
if (nextEmit == null) {
|
|
593
612
|
nextEmit = {
|
|
594
613
|
eventsQueue: [event],
|
|
595
|
-
firstEventTimestamp: onChangeStartTime,
|
|
596
614
|
firstEnqueuedTimestamp:
|
|
597
615
|
_perf_hooks.performance.timeOrigin +
|
|
598
616
|
_perf_hooks.performance.now(),
|
|
617
|
+
firstEventTimestamp: onChangeStartTime,
|
|
599
618
|
};
|
|
600
619
|
} else {
|
|
601
620
|
nextEmit.eventsQueue.push(event);
|
|
@@ -611,29 +630,32 @@ class FileMap extends _events.default {
|
|
|
611
630
|
change.metadata.modifiedTime,
|
|
612
631
|
change.metadata.size,
|
|
613
632
|
0,
|
|
614
|
-
"",
|
|
615
633
|
null,
|
|
616
634
|
change.metadata.type === "l" ? 1 : 0,
|
|
617
|
-
|
|
635
|
+
null,
|
|
618
636
|
];
|
|
619
637
|
try {
|
|
620
638
|
if (change.metadata.type === "l") {
|
|
621
|
-
await this
|
|
639
|
+
await this.#maybeReadLink(relativeFilePath, fileMetadata);
|
|
622
640
|
} else {
|
|
623
|
-
await this.
|
|
624
|
-
|
|
641
|
+
await this.#fileProcessor.processRegularFile(
|
|
642
|
+
relativeFilePath,
|
|
625
643
|
fileMetadata,
|
|
626
644
|
{
|
|
627
|
-
computeSha1: this.
|
|
628
|
-
computeDependencies: this._options.computeDependencies,
|
|
645
|
+
computeSha1: this.#options.computeSha1,
|
|
629
646
|
maybeReturnContent: false,
|
|
630
647
|
},
|
|
631
648
|
);
|
|
632
649
|
}
|
|
633
650
|
fileSystem.addOrModify(relativeFilePath, fileMetadata);
|
|
634
|
-
this
|
|
635
|
-
plugins.forEach((plugin) =>
|
|
636
|
-
|
|
651
|
+
this.#updateClock(clocks, change.clock);
|
|
652
|
+
plugins.forEach(({ plugin, dataIdx }) =>
|
|
653
|
+
dataIdx != null
|
|
654
|
+
? plugin.onNewOrModifiedFile(
|
|
655
|
+
relativeFilePath,
|
|
656
|
+
fileMetadata[dataIdx],
|
|
657
|
+
)
|
|
658
|
+
: plugin.onNewOrModifiedFile(relativeFilePath),
|
|
637
659
|
);
|
|
638
660
|
enqueueEvent(change.metadata);
|
|
639
661
|
} catch (e) {
|
|
@@ -648,9 +670,11 @@ class FileMap extends _events.default {
|
|
|
648
670
|
const metadata = (0, _nullthrows.default)(
|
|
649
671
|
fileSystem.remove(relativeFilePath),
|
|
650
672
|
);
|
|
651
|
-
this
|
|
652
|
-
plugins.forEach((plugin) =>
|
|
653
|
-
|
|
673
|
+
this.#updateClock(clocks, change.clock);
|
|
674
|
+
plugins.forEach(({ plugin, dataIdx }) =>
|
|
675
|
+
dataIdx != null
|
|
676
|
+
? plugin.onRemovedFile(relativeFilePath, metadata[dataIdx])
|
|
677
|
+
: plugin.onRemovedFile(relativeFilePath),
|
|
654
678
|
);
|
|
655
679
|
enqueueEvent({
|
|
656
680
|
modifiedTime: null,
|
|
@@ -665,60 +689,60 @@ class FileMap extends _events.default {
|
|
|
665
689
|
return null;
|
|
666
690
|
})
|
|
667
691
|
.catch((error) => {
|
|
668
|
-
this.
|
|
692
|
+
this.#console.error(
|
|
669
693
|
`metro-file-map: watch error:\n ${error.stack}\n`,
|
|
670
694
|
);
|
|
671
695
|
});
|
|
672
696
|
};
|
|
673
|
-
this
|
|
697
|
+
this.#changeInterval = setInterval(emitChange, CHANGE_INTERVAL);
|
|
674
698
|
(0, _invariant.default)(
|
|
675
|
-
this
|
|
676
|
-
"Expected
|
|
699
|
+
this.#watcher != null,
|
|
700
|
+
"Expected #watcher to have been initialised by build()",
|
|
677
701
|
);
|
|
678
|
-
await this.
|
|
679
|
-
if (this.
|
|
702
|
+
await this.#watcher.watch(onChange);
|
|
703
|
+
if (this.#options.healthCheck.enabled) {
|
|
680
704
|
const performHealthCheck = () => {
|
|
681
|
-
if (!this
|
|
705
|
+
if (!this.#watcher) {
|
|
682
706
|
return;
|
|
683
707
|
}
|
|
684
|
-
this
|
|
685
|
-
.checkHealth(this.
|
|
708
|
+
this.#watcher
|
|
709
|
+
.checkHealth(this.#options.healthCheck.timeout)
|
|
686
710
|
.then((result) => {
|
|
687
711
|
this.emit("healthCheck", result);
|
|
688
712
|
});
|
|
689
713
|
};
|
|
690
714
|
performHealthCheck();
|
|
691
|
-
this
|
|
715
|
+
this.#healthCheckInterval = setInterval(
|
|
692
716
|
performHealthCheck,
|
|
693
|
-
this.
|
|
717
|
+
this.#options.healthCheck.interval,
|
|
694
718
|
);
|
|
695
719
|
}
|
|
696
|
-
this
|
|
720
|
+
this.#startupPerfLogger?.point("watch_end");
|
|
697
721
|
}
|
|
698
722
|
async end() {
|
|
699
|
-
if (this
|
|
700
|
-
clearInterval(this
|
|
723
|
+
if (this.#changeInterval) {
|
|
724
|
+
clearInterval(this.#changeInterval);
|
|
701
725
|
}
|
|
702
|
-
if (this
|
|
703
|
-
clearInterval(this
|
|
726
|
+
if (this.#healthCheckInterval) {
|
|
727
|
+
clearInterval(this.#healthCheckInterval);
|
|
704
728
|
}
|
|
705
|
-
this.
|
|
729
|
+
this.#crawlerAbortController.abort();
|
|
706
730
|
await Promise.all([
|
|
707
|
-
this.
|
|
708
|
-
this
|
|
709
|
-
this.
|
|
731
|
+
this.#fileProcessor.end(),
|
|
732
|
+
this.#watcher?.close(),
|
|
733
|
+
this.#cacheManager.end(),
|
|
710
734
|
]);
|
|
711
735
|
}
|
|
712
|
-
async
|
|
713
|
-
if (!this.
|
|
736
|
+
async #shouldUseWatchman() {
|
|
737
|
+
if (!this.#options.useWatchman) {
|
|
714
738
|
return false;
|
|
715
739
|
}
|
|
716
|
-
if (!this
|
|
717
|
-
this
|
|
740
|
+
if (!this.#canUseWatchmanPromise) {
|
|
741
|
+
this.#canUseWatchmanPromise = (0, _checkWatchmanCapabilities.default)(
|
|
718
742
|
WATCHMAN_REQUIRED_CAPABILITIES,
|
|
719
743
|
)
|
|
720
744
|
.then(({ version }) => {
|
|
721
|
-
this
|
|
745
|
+
this.#startupPerfLogger?.annotate({
|
|
722
746
|
string: {
|
|
723
747
|
watchmanVersion: version,
|
|
724
748
|
},
|
|
@@ -726,7 +750,7 @@ class FileMap extends _events.default {
|
|
|
726
750
|
return true;
|
|
727
751
|
})
|
|
728
752
|
.catch((e) => {
|
|
729
|
-
this
|
|
753
|
+
this.#startupPerfLogger?.annotate({
|
|
730
754
|
string: {
|
|
731
755
|
watchmanFailedCapabilityCheck: e?.message ?? "[missing]",
|
|
732
756
|
},
|
|
@@ -734,20 +758,20 @@ class FileMap extends _events.default {
|
|
|
734
758
|
return false;
|
|
735
759
|
});
|
|
736
760
|
}
|
|
737
|
-
return this
|
|
761
|
+
return this.#canUseWatchmanPromise;
|
|
738
762
|
}
|
|
739
|
-
|
|
740
|
-
if (this
|
|
741
|
-
this
|
|
763
|
+
#getNextChangeID() {
|
|
764
|
+
if (this.#changeID >= Number.MAX_SAFE_INTEGER) {
|
|
765
|
+
this.#changeID = 0;
|
|
742
766
|
}
|
|
743
|
-
return ++this
|
|
767
|
+
return ++this.#changeID;
|
|
744
768
|
}
|
|
745
|
-
|
|
769
|
+
#updateClock(clocks, newClock) {
|
|
746
770
|
if (newClock == null) {
|
|
747
771
|
return;
|
|
748
772
|
}
|
|
749
773
|
const [absoluteWatchRoot, clockSpec] = newClock;
|
|
750
|
-
const relativeFsRoot = this.
|
|
774
|
+
const relativeFsRoot = this.#pathUtils.absoluteToNormal(absoluteWatchRoot);
|
|
751
775
|
clocks.set(
|
|
752
776
|
(0, _normalizePathSeparatorsToPosix.default)(relativeFsRoot),
|
|
753
777
|
clockSpec,
|
|
@@ -756,3 +780,11 @@ class FileMap extends _events.default {
|
|
|
756
780
|
static H = _constants.default;
|
|
757
781
|
}
|
|
758
782
|
exports.default = FileMap;
|
|
783
|
+
const mapIterator = (it, fn) =>
|
|
784
|
+
"map" in it
|
|
785
|
+
? it.map(fn)
|
|
786
|
+
: (function* mapped() {
|
|
787
|
+
for (const item of it) {
|
|
788
|
+
yield fn(item);
|
|
789
|
+
}
|
|
790
|
+
})();
|