metro-file-map 0.73.1 → 0.73.2
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/Watcher.js +176 -0
- package/src/Watcher.js.flow +186 -0
- package/src/index.js +54 -161
- package/src/index.js.flow +44 -132
package/package.json
CHANGED
package/src/Watcher.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true,
|
|
5
|
+
});
|
|
6
|
+
exports.Watcher = void 0;
|
|
7
|
+
|
|
8
|
+
var _watchman = _interopRequireDefault(require("./crawlers/watchman"));
|
|
9
|
+
|
|
10
|
+
var _node = _interopRequireDefault(require("./crawlers/node"));
|
|
11
|
+
|
|
12
|
+
var _WatchmanWatcher = _interopRequireDefault(
|
|
13
|
+
require("./watchers/WatchmanWatcher")
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
var _FSEventsWatcher = _interopRequireDefault(
|
|
17
|
+
require("./watchers/FSEventsWatcher")
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
var _NodeWatcher = _interopRequireDefault(require("./watchers/NodeWatcher"));
|
|
21
|
+
|
|
22
|
+
function _interopRequireDefault(obj) {
|
|
23
|
+
return obj && obj.__esModule ? obj : { default: obj };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
28
|
+
*
|
|
29
|
+
* This source code is licensed under the MIT license found in the
|
|
30
|
+
* LICENSE file in the root directory of this source tree.
|
|
31
|
+
*
|
|
32
|
+
* @format
|
|
33
|
+
*
|
|
34
|
+
*/
|
|
35
|
+
// $FlowFixMe[untyped-import] - it's a fork: https://github.com/facebook/jest/pull/10919
|
|
36
|
+
const debug = require("debug")("Metro:Watcher");
|
|
37
|
+
|
|
38
|
+
const MAX_WAIT_TIME = 240000;
|
|
39
|
+
|
|
40
|
+
class Watcher {
|
|
41
|
+
_backends = [];
|
|
42
|
+
|
|
43
|
+
constructor(options) {
|
|
44
|
+
this._options = options;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async crawl() {
|
|
48
|
+
var _this$_options$perfLo;
|
|
49
|
+
|
|
50
|
+
(_this$_options$perfLo = this._options.perfLogger) === null ||
|
|
51
|
+
_this$_options$perfLo === void 0
|
|
52
|
+
? void 0
|
|
53
|
+
: _this$_options$perfLo.point("crawl_start");
|
|
54
|
+
const options = this._options;
|
|
55
|
+
|
|
56
|
+
const ignore = (filePath) => options.ignore(filePath);
|
|
57
|
+
|
|
58
|
+
const crawl = options.useWatchman ? _watchman.default : _node.default;
|
|
59
|
+
const crawlerOptions = {
|
|
60
|
+
abortSignal: options.abortSignal,
|
|
61
|
+
computeSha1: options.computeSha1,
|
|
62
|
+
data: options.initialData,
|
|
63
|
+
enableSymlinks: options.enableSymlinks,
|
|
64
|
+
extensions: options.extensions,
|
|
65
|
+
forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,
|
|
66
|
+
ignore,
|
|
67
|
+
perfLogger: options.perfLogger,
|
|
68
|
+
rootDir: options.rootDir,
|
|
69
|
+
roots: options.roots,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const retry = (error) => {
|
|
73
|
+
if (crawl === _watchman.default) {
|
|
74
|
+
options.console.warn(
|
|
75
|
+
"metro-file-map: Watchman crawl failed. Retrying once with node " +
|
|
76
|
+
"crawler.\n" +
|
|
77
|
+
" Usually this happens when watchman isn't running. Create an " +
|
|
78
|
+
"empty `.watchmanconfig` file in your project's root folder or " +
|
|
79
|
+
"initialize a git or hg repository in your project.\n" +
|
|
80
|
+
" " +
|
|
81
|
+
error.toString()
|
|
82
|
+
);
|
|
83
|
+
return (0, _node.default)(crawlerOptions).catch((e) => {
|
|
84
|
+
throw new Error(
|
|
85
|
+
"Crawler retry failed:\n" +
|
|
86
|
+
` Original error: ${error.message}\n` +
|
|
87
|
+
` Retry error: ${e.message}\n`
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
throw error;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const logEnd = (result) => {
|
|
96
|
+
var _this$_options$perfLo2;
|
|
97
|
+
|
|
98
|
+
(_this$_options$perfLo2 = this._options.perfLogger) === null ||
|
|
99
|
+
_this$_options$perfLo2 === void 0
|
|
100
|
+
? void 0
|
|
101
|
+
: _this$_options$perfLo2.point("crawl_end");
|
|
102
|
+
return result;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
return crawl(crawlerOptions).catch(retry).then(logEnd);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
return retry(error).then(logEnd);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async watch(onChange) {
|
|
113
|
+
var _this$_options$perfLo3;
|
|
114
|
+
|
|
115
|
+
const { extensions, ignorePattern, useWatchman } = this._options; // WatchmanWatcher > FSEventsWatcher > sane.NodeWatcher
|
|
116
|
+
|
|
117
|
+
const WatcherImpl = useWatchman
|
|
118
|
+
? _WatchmanWatcher.default
|
|
119
|
+
: _FSEventsWatcher.default.isSupported()
|
|
120
|
+
? _FSEventsWatcher.default
|
|
121
|
+
: _NodeWatcher.default;
|
|
122
|
+
let watcher = "node";
|
|
123
|
+
|
|
124
|
+
if (WatcherImpl === _WatchmanWatcher.default) {
|
|
125
|
+
watcher = "watchman";
|
|
126
|
+
} else if (WatcherImpl === _FSEventsWatcher.default) {
|
|
127
|
+
watcher = "fsevents";
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
debug(`Using watcher: ${watcher}`);
|
|
131
|
+
(_this$_options$perfLo3 = this._options.perfLogger) === null ||
|
|
132
|
+
_this$_options$perfLo3 === void 0
|
|
133
|
+
? void 0
|
|
134
|
+
: _this$_options$perfLo3.annotate({
|
|
135
|
+
string: {
|
|
136
|
+
watcher,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const createWatcherBackend = (root) => {
|
|
141
|
+
const watcherOptions = {
|
|
142
|
+
dot: true,
|
|
143
|
+
glob: [
|
|
144
|
+
// Ensure we always include package.json files, which are crucial for
|
|
145
|
+
/// module resolution.
|
|
146
|
+
"**/package.json",
|
|
147
|
+
...extensions.map((extension) => "**/*." + extension),
|
|
148
|
+
],
|
|
149
|
+
ignored: ignorePattern,
|
|
150
|
+
watchmanDeferStates: this._options.watchmanDeferStates,
|
|
151
|
+
};
|
|
152
|
+
const watcher = new WatcherImpl(root, watcherOptions);
|
|
153
|
+
return new Promise((resolve, reject) => {
|
|
154
|
+
const rejectTimeout = setTimeout(
|
|
155
|
+
() => reject(new Error("Failed to start watch mode.")),
|
|
156
|
+
MAX_WAIT_TIME
|
|
157
|
+
);
|
|
158
|
+
watcher.once("ready", () => {
|
|
159
|
+
clearTimeout(rejectTimeout);
|
|
160
|
+
watcher.on("all", onChange);
|
|
161
|
+
resolve(watcher);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
this._backends = await Promise.all(
|
|
167
|
+
this._options.roots.map(createWatcherBackend)
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async close() {
|
|
172
|
+
await Promise.all(this._backends.map((watcher) => watcher.close()));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
exports.Watcher = Watcher;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @flow strict-local
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
Console,
|
|
13
|
+
CrawlerOptions,
|
|
14
|
+
FileData,
|
|
15
|
+
InternalData,
|
|
16
|
+
Path,
|
|
17
|
+
PerfLogger,
|
|
18
|
+
} from './flow-types';
|
|
19
|
+
import type {WatcherOptions as WatcherBackendOptions} from './watchers/common';
|
|
20
|
+
import type {Stats} from 'fs';
|
|
21
|
+
|
|
22
|
+
import watchmanCrawl from './crawlers/watchman';
|
|
23
|
+
import nodeCrawl from './crawlers/node';
|
|
24
|
+
import WatchmanWatcher from './watchers/WatchmanWatcher';
|
|
25
|
+
import FSEventsWatcher from './watchers/FSEventsWatcher';
|
|
26
|
+
// $FlowFixMe[untyped-import] - it's a fork: https://github.com/facebook/jest/pull/10919
|
|
27
|
+
import NodeWatcher from './watchers/NodeWatcher';
|
|
28
|
+
|
|
29
|
+
const debug = require('debug')('Metro:Watcher');
|
|
30
|
+
|
|
31
|
+
const MAX_WAIT_TIME = 240000;
|
|
32
|
+
|
|
33
|
+
type WatcherOptions = {
|
|
34
|
+
abortSignal: AbortSignal,
|
|
35
|
+
computeSha1: boolean,
|
|
36
|
+
console: Console,
|
|
37
|
+
enableSymlinks: boolean,
|
|
38
|
+
extensions: $ReadOnlyArray<string>,
|
|
39
|
+
forceNodeFilesystemAPI: boolean,
|
|
40
|
+
ignore: string => boolean,
|
|
41
|
+
ignorePattern: RegExp,
|
|
42
|
+
initialData: InternalData,
|
|
43
|
+
perfLogger: ?PerfLogger,
|
|
44
|
+
roots: $ReadOnlyArray<string>,
|
|
45
|
+
rootDir: string,
|
|
46
|
+
useWatchman: boolean,
|
|
47
|
+
watch: boolean,
|
|
48
|
+
watchmanDeferStates: $ReadOnlyArray<string>,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
interface WatcherBackend {
|
|
52
|
+
close(): Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export class Watcher {
|
|
56
|
+
_options: WatcherOptions;
|
|
57
|
+
_backends: $ReadOnlyArray<WatcherBackend> = [];
|
|
58
|
+
|
|
59
|
+
constructor(options: WatcherOptions) {
|
|
60
|
+
this._options = options;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async crawl(): Promise<?(
|
|
64
|
+
| Promise<{
|
|
65
|
+
changedFiles?: FileData,
|
|
66
|
+
hasteMap: InternalData,
|
|
67
|
+
removedFiles: FileData,
|
|
68
|
+
}>
|
|
69
|
+
| {changedFiles?: FileData, hasteMap: InternalData, removedFiles: FileData}
|
|
70
|
+
)> {
|
|
71
|
+
this._options.perfLogger?.point('crawl_start');
|
|
72
|
+
|
|
73
|
+
const options = this._options;
|
|
74
|
+
const ignore = (filePath: string) => options.ignore(filePath);
|
|
75
|
+
const crawl = options.useWatchman ? watchmanCrawl : nodeCrawl;
|
|
76
|
+
const crawlerOptions: CrawlerOptions = {
|
|
77
|
+
abortSignal: options.abortSignal,
|
|
78
|
+
computeSha1: options.computeSha1,
|
|
79
|
+
data: options.initialData,
|
|
80
|
+
enableSymlinks: options.enableSymlinks,
|
|
81
|
+
extensions: options.extensions,
|
|
82
|
+
forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,
|
|
83
|
+
ignore,
|
|
84
|
+
perfLogger: options.perfLogger,
|
|
85
|
+
rootDir: options.rootDir,
|
|
86
|
+
roots: options.roots,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const retry = (error: Error) => {
|
|
90
|
+
if (crawl === watchmanCrawl) {
|
|
91
|
+
options.console.warn(
|
|
92
|
+
'metro-file-map: Watchman crawl failed. Retrying once with node ' +
|
|
93
|
+
'crawler.\n' +
|
|
94
|
+
" Usually this happens when watchman isn't running. Create an " +
|
|
95
|
+
"empty `.watchmanconfig` file in your project's root folder or " +
|
|
96
|
+
'initialize a git or hg repository in your project.\n' +
|
|
97
|
+
' ' +
|
|
98
|
+
error.toString(),
|
|
99
|
+
);
|
|
100
|
+
return nodeCrawl(crawlerOptions).catch(e => {
|
|
101
|
+
throw new Error(
|
|
102
|
+
'Crawler retry failed:\n' +
|
|
103
|
+
` Original error: ${error.message}\n` +
|
|
104
|
+
` Retry error: ${e.message}\n`,
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
throw error;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const logEnd = <T>(result: T): T => {
|
|
113
|
+
this._options.perfLogger?.point('crawl_end');
|
|
114
|
+
return result;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
return crawl(crawlerOptions).catch(retry).then(logEnd);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
return retry(error).then(logEnd);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async watch(
|
|
125
|
+
onChange: (
|
|
126
|
+
type: string,
|
|
127
|
+
filePath: string,
|
|
128
|
+
root: string,
|
|
129
|
+
stat?: Stats,
|
|
130
|
+
) => void,
|
|
131
|
+
) {
|
|
132
|
+
const {extensions, ignorePattern, useWatchman} = this._options;
|
|
133
|
+
|
|
134
|
+
// WatchmanWatcher > FSEventsWatcher > sane.NodeWatcher
|
|
135
|
+
const WatcherImpl = useWatchman
|
|
136
|
+
? WatchmanWatcher
|
|
137
|
+
: FSEventsWatcher.isSupported()
|
|
138
|
+
? FSEventsWatcher
|
|
139
|
+
: NodeWatcher;
|
|
140
|
+
|
|
141
|
+
let watcher = 'node';
|
|
142
|
+
if (WatcherImpl === WatchmanWatcher) {
|
|
143
|
+
watcher = 'watchman';
|
|
144
|
+
} else if (WatcherImpl === FSEventsWatcher) {
|
|
145
|
+
watcher = 'fsevents';
|
|
146
|
+
}
|
|
147
|
+
debug(`Using watcher: ${watcher}`);
|
|
148
|
+
this._options.perfLogger?.annotate({string: {watcher}});
|
|
149
|
+
|
|
150
|
+
const createWatcherBackend = (root: Path): Promise<WatcherBackend> => {
|
|
151
|
+
const watcherOptions: WatcherBackendOptions = {
|
|
152
|
+
dot: true,
|
|
153
|
+
glob: [
|
|
154
|
+
// Ensure we always include package.json files, which are crucial for
|
|
155
|
+
/// module resolution.
|
|
156
|
+
'**/package.json',
|
|
157
|
+
...extensions.map(extension => '**/*.' + extension),
|
|
158
|
+
],
|
|
159
|
+
ignored: ignorePattern,
|
|
160
|
+
watchmanDeferStates: this._options.watchmanDeferStates,
|
|
161
|
+
};
|
|
162
|
+
const watcher = new WatcherImpl(root, watcherOptions);
|
|
163
|
+
|
|
164
|
+
return new Promise((resolve, reject) => {
|
|
165
|
+
const rejectTimeout = setTimeout(
|
|
166
|
+
() => reject(new Error('Failed to start watch mode.')),
|
|
167
|
+
MAX_WAIT_TIME,
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
watcher.once('ready', () => {
|
|
171
|
+
clearTimeout(rejectTimeout);
|
|
172
|
+
watcher.on('all', onChange);
|
|
173
|
+
resolve(watcher);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
this._backends = await Promise.all(
|
|
179
|
+
this._options.roots.map(createWatcherBackend),
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async close() {
|
|
184
|
+
await Promise.all(this._backends.map(watcher => watcher.close()));
|
|
185
|
+
}
|
|
186
|
+
}
|
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"]
|
|
@@ -337,7 +321,6 @@ class HasteMap extends _events.default {
|
|
|
337
321
|
}
|
|
338
322
|
|
|
339
323
|
this._buildPromise = null;
|
|
340
|
-
this._watchers = [];
|
|
341
324
|
this._worker = null;
|
|
342
325
|
(_this$_options$perfLo = this._options.perfLogger) === null ||
|
|
343
326
|
_this$_options$perfLo === void 0
|
|
@@ -511,7 +494,36 @@ class HasteMap extends _events.default {
|
|
|
511
494
|
hasteMap = this._createEmptyMap();
|
|
512
495
|
}
|
|
513
496
|
|
|
514
|
-
|
|
497
|
+
const {
|
|
498
|
+
computeSha1,
|
|
499
|
+
enableSymlinks,
|
|
500
|
+
extensions,
|
|
501
|
+
forceNodeFilesystemAPI,
|
|
502
|
+
ignorePattern,
|
|
503
|
+
perfLogger,
|
|
504
|
+
roots,
|
|
505
|
+
rootDir,
|
|
506
|
+
watch,
|
|
507
|
+
watchmanDeferStates,
|
|
508
|
+
} = this._options;
|
|
509
|
+
this._watcher = new _Watcher.Watcher({
|
|
510
|
+
abortSignal: this._crawlerAbortController.signal,
|
|
511
|
+
computeSha1,
|
|
512
|
+
console: this._console,
|
|
513
|
+
enableSymlinks,
|
|
514
|
+
extensions,
|
|
515
|
+
forceNodeFilesystemAPI,
|
|
516
|
+
ignore: (path) => this._ignore(path),
|
|
517
|
+
ignorePattern,
|
|
518
|
+
initialData: hasteMap,
|
|
519
|
+
perfLogger,
|
|
520
|
+
roots,
|
|
521
|
+
rootDir,
|
|
522
|
+
useWatchman: await this._shouldUseWatchman(),
|
|
523
|
+
watch,
|
|
524
|
+
watchmanDeferStates,
|
|
525
|
+
});
|
|
526
|
+
return this._watcher.crawl().then((result) => {
|
|
515
527
|
var _this$_options$perfLo8;
|
|
516
528
|
|
|
517
529
|
(_this$_options$perfLo8 = this._options.perfLogger) === null ||
|
|
@@ -893,154 +905,38 @@ class HasteMap extends _events.default {
|
|
|
893
905
|
|
|
894
906
|
return this._worker;
|
|
895
907
|
}
|
|
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
908
|
/**
|
|
963
909
|
* Watch mode
|
|
964
910
|
*/
|
|
965
911
|
|
|
966
912
|
async _watch(hasteMap) {
|
|
967
|
-
var _this$_options$
|
|
913
|
+
var _this$_options$perfLo13, _this$_options$perfLo15;
|
|
968
914
|
|
|
969
|
-
(_this$_options$
|
|
970
|
-
_this$_options$
|
|
915
|
+
(_this$_options$perfLo13 = this._options.perfLogger) === null ||
|
|
916
|
+
_this$_options$perfLo13 === void 0
|
|
971
917
|
? void 0
|
|
972
|
-
: _this$_options$
|
|
918
|
+
: _this$_options$perfLo13.point("watch_start");
|
|
973
919
|
|
|
974
920
|
if (!this._options.watch) {
|
|
975
|
-
var _this$_options$
|
|
921
|
+
var _this$_options$perfLo14;
|
|
976
922
|
|
|
977
|
-
(_this$_options$
|
|
978
|
-
_this$_options$
|
|
923
|
+
(_this$_options$perfLo14 = this._options.perfLogger) === null ||
|
|
924
|
+
_this$_options$perfLo14 === void 0
|
|
979
925
|
? void 0
|
|
980
|
-
: _this$_options$
|
|
926
|
+
: _this$_options$perfLo14.point("watch_end");
|
|
981
927
|
return;
|
|
982
928
|
} // In watch mode, we'll only warn about module collisions and we'll retain
|
|
983
929
|
// all files, even changes to node_modules.
|
|
984
930
|
|
|
985
931
|
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
|
-
});
|
|
932
|
+
this._options.retainAllFiles = true;
|
|
1010
933
|
const extensions = this._options.extensions;
|
|
1011
|
-
const ignorePattern = this._options.ignorePattern;
|
|
1012
934
|
const rootDir = this._options.rootDir;
|
|
1013
935
|
let changeQueue = Promise.resolve();
|
|
1014
936
|
let eventsQueue = []; // We only need to copy the entire haste map once on every "frame".
|
|
1015
937
|
|
|
1016
938
|
let mustCopy = true;
|
|
1017
939
|
|
|
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
940
|
const emitChange = () => {
|
|
1045
941
|
if (eventsQueue.length) {
|
|
1046
942
|
mustCopy = true;
|
|
@@ -1213,17 +1109,15 @@ class HasteMap extends _events.default {
|
|
|
1213
1109
|
};
|
|
1214
1110
|
|
|
1215
1111
|
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
|
-
}
|
|
1112
|
+
(0, _invariant.default)(
|
|
1113
|
+
this._watcher != null,
|
|
1114
|
+
"Expected _watcher to have been initialised by _buildFileMap"
|
|
1226
1115
|
);
|
|
1116
|
+
await this._watcher.watch(onChange);
|
|
1117
|
+
(_this$_options$perfLo15 = this._options.perfLogger) === null ||
|
|
1118
|
+
_this$_options$perfLo15 === void 0
|
|
1119
|
+
? void 0
|
|
1120
|
+
: _this$_options$perfLo15.point("watch_end");
|
|
1227
1121
|
}
|
|
1228
1122
|
/**
|
|
1229
1123
|
* This function should be called when the file under `filePath` is removed
|
|
@@ -1290,12 +1184,11 @@ class HasteMap extends _events.default {
|
|
|
1290
1184
|
clearInterval(this._changeInterval);
|
|
1291
1185
|
}
|
|
1292
1186
|
|
|
1293
|
-
if (!this.
|
|
1187
|
+
if (!this._watcher) {
|
|
1294
1188
|
return;
|
|
1295
1189
|
}
|
|
1296
1190
|
|
|
1297
|
-
await
|
|
1298
|
-
this._watchers = [];
|
|
1191
|
+
await this._watcher.close();
|
|
1299
1192
|
|
|
1300
1193
|
this._crawlerAbortController.abort();
|
|
1301
1194
|
}
|
|
@@ -1326,14 +1219,14 @@ class HasteMap extends _events.default {
|
|
|
1326
1219
|
)
|
|
1327
1220
|
.then(() => true)
|
|
1328
1221
|
.catch((e) => {
|
|
1329
|
-
var _this$_options$
|
|
1222
|
+
var _this$_options$perfLo16, _e$message;
|
|
1330
1223
|
|
|
1331
1224
|
// TODO: Advise people to either install Watchman or set
|
|
1332
1225
|
// `useWatchman: false` here?
|
|
1333
|
-
(_this$_options$
|
|
1334
|
-
_this$_options$
|
|
1226
|
+
(_this$_options$perfLo16 = this._options.perfLogger) === null ||
|
|
1227
|
+
_this$_options$perfLo16 === void 0
|
|
1335
1228
|
? void 0
|
|
1336
|
-
: _this$_options$
|
|
1229
|
+
: _this$_options$perfLo16.annotate({
|
|
1337
1230
|
string: {
|
|
1338
1231
|
watchmanFailedCapabilityCheck:
|
|
1339
1232
|
(_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,7 +30,6 @@ 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';
|
|
36
34
|
|
|
37
35
|
import {DiskCacheManager} from './cache/DiskCacheManager';
|
|
@@ -45,10 +43,7 @@ import getPlatformExtension from './lib/getPlatformExtension';
|
|
|
45
43
|
import normalizePathSep from './lib/normalizePathSep';
|
|
46
44
|
import rootRelativeCacheKeys from './lib/rootRelativeCacheKeys';
|
|
47
45
|
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';
|
|
46
|
+
import {Watcher} from './Watcher';
|
|
52
47
|
import {getSha1, worker} from './worker';
|
|
53
48
|
import EventEmitter from 'events';
|
|
54
49
|
import invariant from 'invariant';
|
|
@@ -60,10 +55,6 @@ import * as path from 'path';
|
|
|
60
55
|
// $FlowFixMe[untyped-import] - this is a polyfill
|
|
61
56
|
import AbortController from 'abort-controller';
|
|
62
57
|
|
|
63
|
-
const nodeCrawl = require('./crawlers/node');
|
|
64
|
-
const watchmanCrawl = require('./crawlers/watchman');
|
|
65
|
-
const debug = require('debug')('Metro:FileMap');
|
|
66
|
-
|
|
67
58
|
export type {
|
|
68
59
|
BuildParameters,
|
|
69
60
|
FileData,
|
|
@@ -114,10 +105,6 @@ type InternalOptions = {
|
|
|
114
105
|
watchmanDeferStates: $ReadOnlyArray<string>,
|
|
115
106
|
};
|
|
116
107
|
|
|
117
|
-
interface Watcher {
|
|
118
|
-
close(): Promise<void>;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
108
|
type WorkerInterface = {worker: typeof worker, getSha1: typeof getSha1};
|
|
122
109
|
|
|
123
110
|
export const DuplicateHasteCandidatesError =
|
|
@@ -140,7 +127,6 @@ export type {
|
|
|
140
127
|
const CACHE_BREAKER = '2';
|
|
141
128
|
|
|
142
129
|
const CHANGE_INTERVAL = 30;
|
|
143
|
-
const MAX_WAIT_TIME = 240000;
|
|
144
130
|
const NODE_MODULES = path.sep + 'node_modules' + path.sep;
|
|
145
131
|
const PACKAGE_JSON = path.sep + 'package.json';
|
|
146
132
|
const VCS_DIRECTORIES = ['.git', '.hg']
|
|
@@ -237,7 +223,7 @@ export default class HasteMap extends EventEmitter {
|
|
|
237
223
|
_changeInterval: ?IntervalID;
|
|
238
224
|
_console: Console;
|
|
239
225
|
_options: InternalOptions;
|
|
240
|
-
|
|
226
|
+
_watcher: ?Watcher;
|
|
241
227
|
_worker: ?WorkerInterface;
|
|
242
228
|
_cacheManager: CacheManager;
|
|
243
229
|
_crawlerAbortController: typeof AbortController;
|
|
@@ -322,7 +308,6 @@ export default class HasteMap extends EventEmitter {
|
|
|
322
308
|
}
|
|
323
309
|
|
|
324
310
|
this._buildPromise = null;
|
|
325
|
-
this._watchers = [];
|
|
326
311
|
this._worker = null;
|
|
327
312
|
this._options.perfLogger?.point('constructor_end');
|
|
328
313
|
this._crawlerAbortController = new AbortController();
|
|
@@ -455,7 +440,39 @@ export default class HasteMap extends EventEmitter {
|
|
|
455
440
|
} catch {
|
|
456
441
|
hasteMap = this._createEmptyMap();
|
|
457
442
|
}
|
|
458
|
-
|
|
443
|
+
|
|
444
|
+
const {
|
|
445
|
+
computeSha1,
|
|
446
|
+
enableSymlinks,
|
|
447
|
+
extensions,
|
|
448
|
+
forceNodeFilesystemAPI,
|
|
449
|
+
ignorePattern,
|
|
450
|
+
perfLogger,
|
|
451
|
+
roots,
|
|
452
|
+
rootDir,
|
|
453
|
+
watch,
|
|
454
|
+
watchmanDeferStates,
|
|
455
|
+
} = this._options;
|
|
456
|
+
|
|
457
|
+
this._watcher = new Watcher({
|
|
458
|
+
abortSignal: this._crawlerAbortController.signal,
|
|
459
|
+
computeSha1,
|
|
460
|
+
console: this._console,
|
|
461
|
+
enableSymlinks,
|
|
462
|
+
extensions,
|
|
463
|
+
forceNodeFilesystemAPI,
|
|
464
|
+
ignore: path => this._ignore(path),
|
|
465
|
+
ignorePattern,
|
|
466
|
+
initialData: hasteMap,
|
|
467
|
+
perfLogger,
|
|
468
|
+
roots,
|
|
469
|
+
rootDir,
|
|
470
|
+
useWatchman: await this._shouldUseWatchman(),
|
|
471
|
+
watch,
|
|
472
|
+
watchmanDeferStates,
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
return this._watcher.crawl().then(result => {
|
|
459
476
|
this._options.perfLogger?.point('buildFileMap_end');
|
|
460
477
|
return result;
|
|
461
478
|
});
|
|
@@ -788,66 +805,6 @@ export default class HasteMap extends EventEmitter {
|
|
|
788
805
|
return this._worker;
|
|
789
806
|
}
|
|
790
807
|
|
|
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
808
|
/**
|
|
852
809
|
* Watch mode
|
|
853
810
|
*/
|
|
@@ -863,24 +820,7 @@ export default class HasteMap extends EventEmitter {
|
|
|
863
820
|
this._options.throwOnModuleCollision = false;
|
|
864
821
|
this._options.retainAllFiles = true;
|
|
865
822
|
|
|
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
823
|
const extensions = this._options.extensions;
|
|
883
|
-
const ignorePattern = this._options.ignorePattern;
|
|
884
824
|
const rootDir = this._options.rootDir;
|
|
885
825
|
|
|
886
826
|
let changeQueue: Promise<null | void> = Promise.resolve();
|
|
@@ -888,34 +828,6 @@ export default class HasteMap extends EventEmitter {
|
|
|
888
828
|
// We only need to copy the entire haste map once on every "frame".
|
|
889
829
|
let mustCopy = true;
|
|
890
830
|
|
|
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
831
|
const emitChange = () => {
|
|
920
832
|
if (eventsQueue.length) {
|
|
921
833
|
mustCopy = true;
|
|
@@ -1076,10 +988,13 @@ export default class HasteMap extends EventEmitter {
|
|
|
1076
988
|
|
|
1077
989
|
this._changeInterval = setInterval(emitChange, CHANGE_INTERVAL);
|
|
1078
990
|
|
|
1079
|
-
|
|
1080
|
-
this.
|
|
1081
|
-
|
|
1082
|
-
|
|
991
|
+
invariant(
|
|
992
|
+
this._watcher != null,
|
|
993
|
+
'Expected _watcher to have been initialised by _buildFileMap',
|
|
994
|
+
);
|
|
995
|
+
await this._watcher.watch(onChange);
|
|
996
|
+
|
|
997
|
+
this._options.perfLogger?.point('watch_end');
|
|
1083
998
|
}
|
|
1084
999
|
|
|
1085
1000
|
/**
|
|
@@ -1144,13 +1059,10 @@ export default class HasteMap extends EventEmitter {
|
|
|
1144
1059
|
clearInterval(this._changeInterval);
|
|
1145
1060
|
}
|
|
1146
1061
|
|
|
1147
|
-
if (!this.
|
|
1062
|
+
if (!this._watcher) {
|
|
1148
1063
|
return;
|
|
1149
1064
|
}
|
|
1150
|
-
|
|
1151
|
-
await Promise.all(this._watchers.map(watcher => watcher.close()));
|
|
1152
|
-
|
|
1153
|
-
this._watchers = [];
|
|
1065
|
+
await this._watcher.close();
|
|
1154
1066
|
this._crawlerAbortController.abort();
|
|
1155
1067
|
}
|
|
1156
1068
|
|