metro 0.81.0 → 0.81.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 +27 -21
- package/src/Assets.js +8 -24
- package/src/Assets.js.flow +9 -28
- package/src/Bundler.js +8 -2
- package/src/Bundler.js.flow +10 -2
- package/src/DeltaBundler/DeltaCalculator.js.flow +3 -14
- package/src/DeltaBundler/Serializers/hmrJSBundle.js +5 -2
- package/src/DeltaBundler/Serializers/hmrJSBundle.js.flow +8 -2
- package/src/DeltaBundler/Transformer.js +17 -4
- package/src/DeltaBundler/Transformer.js.flow +26 -5
- package/src/HmrServer.js.flow +3 -0
- package/src/commands/dependencies.js +13 -10
- package/src/commands/dependencies.js.flow +17 -14
- package/src/index.flow.js +6 -1
- package/src/index.flow.js.flow +9 -5
- package/src/integration_tests/metro.config.js +1 -1
- package/src/lib/TerminalReporter.js +3 -0
- package/src/lib/TerminalReporter.js.flow +3 -0
- package/src/lib/getMaxWorkers.js +1 -1
- package/src/lib/getMaxWorkers.js.flow +2 -1
- package/src/lib/getPreludeCode.js +2 -2
- package/src/lib/getPreludeCode.js.flow +2 -2
- package/src/lib/reporting.js +4 -2
- package/src/lib/reporting.js.flow +9 -2
- package/src/lib/transformHelpers.js +5 -0
- package/src/lib/transformHelpers.js.flow +5 -0
- package/src/node-haste/DependencyGraph/createFileMap.js +9 -5
- package/src/node-haste/DependencyGraph/createFileMap.js.flow +10 -5
- package/src/node-haste/DependencyGraph.js +16 -4
- package/src/node-haste/DependencyGraph.js.flow +26 -9
- package/src/shared/output/RamBundle/write-sourcemap.js +1 -1
- package/src/shared/output/RamBundle/write-sourcemap.js.flow +1 -1
- package/src/shared/output/bundle.flow.js +1 -1
- package/src/shared/output/bundle.flow.js.flow +2 -2
- package/src/shared/output/writeFile.js +1 -2
- package/src/shared/output/writeFile.js.flow +5 -8
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metro",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.2",
|
|
4
4
|
"description": "🚇 The JavaScript bundler for React Native.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": "src/cli.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./package.json": "./package.json",
|
|
10
|
+
"./private/*": "./src/*.js",
|
|
11
|
+
"./src": "./src/index.js",
|
|
12
|
+
"./src/*.js": "./src/*.js",
|
|
13
|
+
"./src/*": "./src/*.js"
|
|
14
|
+
},
|
|
7
15
|
"repository": {
|
|
8
16
|
"type": "git",
|
|
9
17
|
"url": "git@github.com:facebook/metro.git"
|
|
@@ -25,33 +33,31 @@
|
|
|
25
33
|
"ci-info": "^2.0.0",
|
|
26
34
|
"connect": "^3.6.5",
|
|
27
35
|
"debug": "^2.2.0",
|
|
28
|
-
"denodeify": "^1.2.1",
|
|
29
36
|
"error-stack-parser": "^2.0.6",
|
|
30
37
|
"flow-enums-runtime": "^0.0.6",
|
|
31
38
|
"graceful-fs": "^4.2.4",
|
|
32
|
-
"hermes-parser": "0.
|
|
39
|
+
"hermes-parser": "0.25.1",
|
|
33
40
|
"image-size": "^1.0.2",
|
|
34
41
|
"invariant": "^2.2.4",
|
|
35
|
-
"jest-worker": "^29.
|
|
42
|
+
"jest-worker": "^29.7.0",
|
|
36
43
|
"jsc-safe-url": "^0.2.2",
|
|
37
44
|
"lodash.throttle": "^4.1.1",
|
|
38
|
-
"metro-babel-transformer": "0.81.
|
|
39
|
-
"metro-cache": "0.81.
|
|
40
|
-
"metro-cache-key": "0.81.
|
|
41
|
-
"metro-config": "0.81.
|
|
42
|
-
"metro-core": "0.81.
|
|
43
|
-
"metro-file-map": "0.81.
|
|
44
|
-
"metro-resolver": "0.81.
|
|
45
|
-
"metro-runtime": "0.81.
|
|
46
|
-
"metro-source-map": "0.81.
|
|
47
|
-
"metro-symbolicate": "0.81.
|
|
48
|
-
"metro-transform-plugins": "0.81.
|
|
49
|
-
"metro-transform-worker": "0.81.
|
|
45
|
+
"metro-babel-transformer": "0.81.2",
|
|
46
|
+
"metro-cache": "0.81.2",
|
|
47
|
+
"metro-cache-key": "0.81.2",
|
|
48
|
+
"metro-config": "0.81.2",
|
|
49
|
+
"metro-core": "0.81.2",
|
|
50
|
+
"metro-file-map": "0.81.2",
|
|
51
|
+
"metro-resolver": "0.81.2",
|
|
52
|
+
"metro-runtime": "0.81.2",
|
|
53
|
+
"metro-source-map": "0.81.2",
|
|
54
|
+
"metro-symbolicate": "0.81.2",
|
|
55
|
+
"metro-transform-plugins": "0.81.2",
|
|
56
|
+
"metro-transform-worker": "0.81.2",
|
|
50
57
|
"mime-types": "^2.1.27",
|
|
51
58
|
"nullthrows": "^1.1.1",
|
|
52
59
|
"serialize-error": "^2.1.0",
|
|
53
60
|
"source-map": "^0.5.6",
|
|
54
|
-
"strip-ansi": "^6.0.0",
|
|
55
61
|
"throat": "^5.0.0",
|
|
56
62
|
"ws": "^7.5.10",
|
|
57
63
|
"yargs": "^17.6.2"
|
|
@@ -61,12 +67,12 @@
|
|
|
61
67
|
"@babel/plugin-transform-modules-commonjs": "^7.24.8",
|
|
62
68
|
"@react-native/babel-preset": "0.73.16",
|
|
63
69
|
"@react-native/metro-babel-transformer": "0.73.11",
|
|
64
|
-
"babel-jest": "^29.
|
|
70
|
+
"babel-jest": "^29.7.0",
|
|
65
71
|
"dedent": "^0.7.0",
|
|
66
|
-
"jest-snapshot": "^29.
|
|
72
|
+
"jest-snapshot": "^29.7.0",
|
|
67
73
|
"jest-snapshot-serializer-raw": "^1.2.0",
|
|
68
|
-
"metro-babel-register": "0.81.
|
|
69
|
-
"metro-memory-fs": "0.81.
|
|
74
|
+
"metro-babel-register": "0.81.2",
|
|
75
|
+
"metro-memory-fs": "0.81.2",
|
|
70
76
|
"mock-req": "^0.2.0",
|
|
71
77
|
"mock-res": "^0.6.0",
|
|
72
78
|
"stack-trace": "^0.0.10"
|
package/src/Assets.js
CHANGED
|
@@ -2,12 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const AssetPaths = require("./node-haste/lib/AssetPaths");
|
|
4
4
|
const crypto = require("crypto");
|
|
5
|
-
const denodeify = require("denodeify");
|
|
6
5
|
const fs = require("fs");
|
|
7
6
|
const getImageSize = require("image-size");
|
|
8
7
|
const path = require("path");
|
|
9
|
-
const readDir = denodeify(fs.readdir);
|
|
10
|
-
const readFile = denodeify(fs.readFile);
|
|
11
8
|
function isAssetTypeAnImage(type) {
|
|
12
9
|
return (
|
|
13
10
|
[
|
|
@@ -37,22 +34,6 @@ function getAssetSize(type, content, filePath) {
|
|
|
37
34
|
height,
|
|
38
35
|
};
|
|
39
36
|
}
|
|
40
|
-
const hashFiles = denodeify(function hashFilesCb(files, hash, callback) {
|
|
41
|
-
if (!files.length) {
|
|
42
|
-
callback(null);
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const file = files.shift();
|
|
46
|
-
fs.readFile(file, (err, data) => {
|
|
47
|
-
if (err) {
|
|
48
|
-
callback(err);
|
|
49
|
-
return;
|
|
50
|
-
} else {
|
|
51
|
-
hash.update(data);
|
|
52
|
-
hashFilesCb(files, hash, callback);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
37
|
function buildAssetMap(dir, files, platform) {
|
|
57
38
|
const platforms = new Set(platform != null ? [platform] : []);
|
|
58
39
|
const assets = files.map((file) => AssetPaths.tryParse(file, platforms));
|
|
@@ -93,7 +74,7 @@ function getAssetKey(assetName, platform) {
|
|
|
93
74
|
async function getAbsoluteAssetRecord(assetPath, platform = null) {
|
|
94
75
|
const filename = path.basename(assetPath);
|
|
95
76
|
const dir = path.dirname(assetPath);
|
|
96
|
-
const files = await
|
|
77
|
+
const files = await fs.promises.readdir(dir);
|
|
97
78
|
const assetData = AssetPaths.parse(
|
|
98
79
|
filename,
|
|
99
80
|
new Set(platform != null ? [platform] : [])
|
|
@@ -124,8 +105,11 @@ async function getAbsoluteAssetInfo(assetPath, platform = null) {
|
|
|
124
105
|
const { name, type } = nameData;
|
|
125
106
|
const { scales, files } = await getAbsoluteAssetRecord(assetPath, platform);
|
|
126
107
|
const hasher = crypto.createHash("md5");
|
|
127
|
-
|
|
128
|
-
|
|
108
|
+
const fileData = await Promise.all(
|
|
109
|
+
files.map((file) => fs.promises.readFile(file))
|
|
110
|
+
);
|
|
111
|
+
for (const data of fileData) {
|
|
112
|
+
hasher.update(data);
|
|
129
113
|
}
|
|
130
114
|
return {
|
|
131
115
|
files,
|
|
@@ -207,10 +191,10 @@ async function getAsset(
|
|
|
207
191
|
const record = await getAbsoluteAssetRecord(absolutePath, platform);
|
|
208
192
|
for (let i = 0; i < record.scales.length; i++) {
|
|
209
193
|
if (record.scales[i] >= assetData.resolution) {
|
|
210
|
-
return readFile(record.files[i]);
|
|
194
|
+
return fs.promises.readFile(record.files[i]);
|
|
211
195
|
}
|
|
212
196
|
}
|
|
213
|
-
return readFile(record.files[record.files.length - 1]);
|
|
197
|
+
return fs.promises.readFile(record.files[record.files.length - 1]);
|
|
214
198
|
}
|
|
215
199
|
function pathBelongsToRoots(pathToCheck, roots) {
|
|
216
200
|
for (const rootFolder of roots) {
|
package/src/Assets.js.flow
CHANGED
|
@@ -15,14 +15,10 @@ import type {AssetPath} from './node-haste/lib/AssetPaths';
|
|
|
15
15
|
|
|
16
16
|
const AssetPaths = require('./node-haste/lib/AssetPaths');
|
|
17
17
|
const crypto = require('crypto');
|
|
18
|
-
const denodeify = require('denodeify');
|
|
19
18
|
const fs = require('fs');
|
|
20
19
|
const getImageSize = require('image-size');
|
|
21
20
|
const path = require('path');
|
|
22
21
|
|
|
23
|
-
const readDir = denodeify(fs.readdir);
|
|
24
|
-
const readFile = denodeify(fs.readFile);
|
|
25
|
-
|
|
26
22
|
export type AssetInfo = {
|
|
27
23
|
+files: Array<string>,
|
|
28
24
|
+hash: string,
|
|
@@ -95,25 +91,6 @@ export type AssetDataPlugin = (
|
|
|
95
91
|
assetData: AssetData,
|
|
96
92
|
) => AssetData | Promise<AssetData>;
|
|
97
93
|
|
|
98
|
-
const hashFiles = denodeify(function hashFilesCb(files, hash, callback): void {
|
|
99
|
-
if (!files.length) {
|
|
100
|
-
callback(null);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const file = files.shift();
|
|
105
|
-
|
|
106
|
-
fs.readFile(file, (err, data: Buffer) => {
|
|
107
|
-
if (err) {
|
|
108
|
-
callback(err);
|
|
109
|
-
return;
|
|
110
|
-
} else {
|
|
111
|
-
hash.update(data);
|
|
112
|
-
hashFilesCb(files, hash, callback);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
94
|
function buildAssetMap(
|
|
118
95
|
dir: string,
|
|
119
96
|
files: $ReadOnlyArray<string>,
|
|
@@ -168,7 +145,7 @@ async function getAbsoluteAssetRecord(
|
|
|
168
145
|
): Promise<{files: Array<string>, scales: Array<number>}> {
|
|
169
146
|
const filename = path.basename(assetPath);
|
|
170
147
|
const dir = path.dirname(assetPath);
|
|
171
|
-
const files = await
|
|
148
|
+
const files = await fs.promises.readdir(dir);
|
|
172
149
|
|
|
173
150
|
const assetData = AssetPaths.parse(
|
|
174
151
|
filename,
|
|
@@ -210,8 +187,12 @@ async function getAbsoluteAssetInfo(
|
|
|
210
187
|
const {scales, files} = await getAbsoluteAssetRecord(assetPath, platform);
|
|
211
188
|
const hasher = crypto.createHash('md5');
|
|
212
189
|
|
|
213
|
-
|
|
214
|
-
|
|
190
|
+
const fileData = await Promise.all(
|
|
191
|
+
files.map(file => fs.promises.readFile(file)),
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
for (const data of fileData) {
|
|
195
|
+
hasher.update(data);
|
|
215
196
|
}
|
|
216
197
|
|
|
217
198
|
return {files, hash: hasher.digest('hex'), name, scales, type};
|
|
@@ -328,11 +309,11 @@ async function getAsset(
|
|
|
328
309
|
|
|
329
310
|
for (let i = 0; i < record.scales.length; i++) {
|
|
330
311
|
if (record.scales[i] >= assetData.resolution) {
|
|
331
|
-
return readFile(record.files[i]);
|
|
312
|
+
return fs.promises.readFile(record.files[i]);
|
|
332
313
|
}
|
|
333
314
|
}
|
|
334
315
|
|
|
335
|
-
return readFile(record.files[record.files.length - 1]);
|
|
316
|
+
return fs.promises.readFile(record.files[record.files.length - 1]);
|
|
336
317
|
}
|
|
337
318
|
|
|
338
319
|
function pathBelongsToRoots(
|
package/src/Bundler.js
CHANGED
|
@@ -11,8 +11,14 @@ class Bundler {
|
|
|
11
11
|
config.reporter.update({
|
|
12
12
|
type: "transformer_load_started",
|
|
13
13
|
});
|
|
14
|
-
this._transformer = new Transformer(
|
|
15
|
-
|
|
14
|
+
this._transformer = new Transformer(
|
|
15
|
+
config,
|
|
16
|
+
config.watcher.unstable_lazySha1
|
|
17
|
+
? {
|
|
18
|
+
unstable_getOrComputeSha1: (filePath) =>
|
|
19
|
+
this._depGraph.unstable_getOrComputeSha1(filePath),
|
|
20
|
+
}
|
|
21
|
+
: (...args) => this._depGraph.getSha1(...args)
|
|
16
22
|
);
|
|
17
23
|
config.reporter.update({
|
|
18
24
|
type: "transformer_load_done",
|
package/src/Bundler.js.flow
CHANGED
|
@@ -36,8 +36,16 @@ class Bundler {
|
|
|
36
36
|
.ready()
|
|
37
37
|
.then(() => {
|
|
38
38
|
config.reporter.update({type: 'transformer_load_started'});
|
|
39
|
-
this._transformer = new Transformer(
|
|
40
|
-
|
|
39
|
+
this._transformer = new Transformer(
|
|
40
|
+
config,
|
|
41
|
+
config.watcher.unstable_lazySha1
|
|
42
|
+
? // This object-form API is expected to replace passing a function
|
|
43
|
+
// once lazy SHA1 is stable. This will be a breaking change.
|
|
44
|
+
{
|
|
45
|
+
unstable_getOrComputeSha1: filePath =>
|
|
46
|
+
this._depGraph.unstable_getOrComputeSha1(filePath),
|
|
47
|
+
}
|
|
48
|
+
: (...args) => this._depGraph.getSha1(...args),
|
|
41
49
|
);
|
|
42
50
|
config.reporter.update({type: 'transformer_load_done'});
|
|
43
51
|
})
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import type {DeltaResult, Options} from './types.flow';
|
|
15
15
|
import type {RootPerfLogger} from 'metro-config';
|
|
16
|
-
import type {
|
|
16
|
+
import type {ChangeEvent} from 'metro-file-map';
|
|
17
17
|
|
|
18
18
|
import {Graph} from './Graph';
|
|
19
19
|
import path from 'path';
|
|
@@ -173,9 +173,7 @@ class DeltaCalculator<T> extends EventEmitter {
|
|
|
173
173
|
return this._graph;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
* LTI update could not be added via codemod */
|
|
178
|
-
_handleMultipleFileChanges = changeEvent => {
|
|
176
|
+
_handleMultipleFileChanges = (changeEvent: ChangeEvent) => {
|
|
179
177
|
changeEvent.eventsQueue.forEach(eventInfo => {
|
|
180
178
|
this._handleFileChange(eventInfo, changeEvent.logger);
|
|
181
179
|
});
|
|
@@ -187,16 +185,7 @@ class DeltaCalculator<T> extends EventEmitter {
|
|
|
187
185
|
* when the delta needs to be calculated.
|
|
188
186
|
*/
|
|
189
187
|
_handleFileChange = (
|
|
190
|
-
{
|
|
191
|
-
type,
|
|
192
|
-
filePath,
|
|
193
|
-
metadata,
|
|
194
|
-
}: {
|
|
195
|
-
type: string,
|
|
196
|
-
filePath: string,
|
|
197
|
-
metadata: ChangeEventMetadata,
|
|
198
|
-
...
|
|
199
|
-
},
|
|
188
|
+
{type, filePath, metadata}: ChangeEvent['eventsQueue'][number],
|
|
200
189
|
logger: ?RootPerfLogger,
|
|
201
190
|
): mixed => {
|
|
202
191
|
debug('Handling %s: %s (type: %s)', type, filePath, metadata.type);
|
|
@@ -10,7 +10,9 @@ function generateModules(sourceModules, graph, options) {
|
|
|
10
10
|
for (const module of sourceModules) {
|
|
11
11
|
if (isJsModule(module)) {
|
|
12
12
|
const getURL = (extension) => {
|
|
13
|
-
|
|
13
|
+
const moduleUrl = url.parse(url.format(options.clientUrl), true);
|
|
14
|
+
moduleUrl.search = "";
|
|
15
|
+
moduleUrl.pathname = path.relative(
|
|
14
16
|
options.serverRoot ?? options.projectRoot,
|
|
15
17
|
path.join(
|
|
16
18
|
path.dirname(module.path),
|
|
@@ -19,7 +21,8 @@ function generateModules(sourceModules, graph, options) {
|
|
|
19
21
|
extension
|
|
20
22
|
)
|
|
21
23
|
);
|
|
22
|
-
|
|
24
|
+
delete moduleUrl.query.excludeSource;
|
|
25
|
+
return url.format(moduleUrl);
|
|
23
26
|
};
|
|
24
27
|
const sourceMappingURL = getURL("map");
|
|
25
28
|
const sourceURL = jscSafeUrl.toJscSafeUrl(getURL("bundle"));
|
|
@@ -41,7 +41,12 @@ function generateModules(
|
|
|
41
41
|
if (isJsModule(module)) {
|
|
42
42
|
// Construct a bundle URL for this specific module only
|
|
43
43
|
const getURL = (extension: 'bundle' | 'map') => {
|
|
44
|
-
|
|
44
|
+
const moduleUrl = url.parse(url.format(options.clientUrl), true);
|
|
45
|
+
// the legacy url object is parsed with both "search" and "query" fields.
|
|
46
|
+
// for the "query" field to be used when formatting the object bach to string, the "search" field must be empty.
|
|
47
|
+
// https://nodejs.org/api/url.html#urlformaturlobject:~:text=If%20the%20urlObject.search%20property%20is%20undefined
|
|
48
|
+
moduleUrl.search = '';
|
|
49
|
+
moduleUrl.pathname = path.relative(
|
|
45
50
|
options.serverRoot ?? options.projectRoot,
|
|
46
51
|
path.join(
|
|
47
52
|
path.dirname(module.path),
|
|
@@ -50,7 +55,8 @@ function generateModules(
|
|
|
50
55
|
extension,
|
|
51
56
|
),
|
|
52
57
|
);
|
|
53
|
-
|
|
58
|
+
delete moduleUrl.query.excludeSource;
|
|
59
|
+
return url.format(moduleUrl);
|
|
54
60
|
};
|
|
55
61
|
|
|
56
62
|
const sourceMappingURL = getURL('map');
|
|
@@ -11,11 +11,14 @@ const fs = require("fs");
|
|
|
11
11
|
const { Cache, stableHash } = require("metro-cache");
|
|
12
12
|
const path = require("path");
|
|
13
13
|
class Transformer {
|
|
14
|
-
constructor(config,
|
|
14
|
+
constructor(config, getSha1FnOrOpts) {
|
|
15
15
|
this._config = config;
|
|
16
16
|
this._config.watchFolders.forEach(verifyRootExists);
|
|
17
17
|
this._cache = new Cache(config.cacheStores);
|
|
18
|
-
this._getSha1 =
|
|
18
|
+
this._getSha1 =
|
|
19
|
+
typeof getSha1FnOrOpts === "function"
|
|
20
|
+
? getSha1FnOrOpts
|
|
21
|
+
: getSha1FnOrOpts.unstable_getOrComputeSha1;
|
|
19
22
|
const {
|
|
20
23
|
getTransformOptions: _getTransformOptions,
|
|
21
24
|
transformVariants: _transformVariants,
|
|
@@ -83,13 +86,23 @@ class Transformer {
|
|
|
83
86
|
unstable_transformProfile,
|
|
84
87
|
]);
|
|
85
88
|
let sha1;
|
|
89
|
+
let content;
|
|
86
90
|
if (fileBuffer) {
|
|
87
91
|
sha1 = _crypto.default
|
|
88
92
|
.createHash("sha1")
|
|
89
93
|
.update(fileBuffer)
|
|
90
94
|
.digest("hex");
|
|
95
|
+
content = fileBuffer;
|
|
91
96
|
} else {
|
|
92
|
-
|
|
97
|
+
const result = await this._getSha1(filePath);
|
|
98
|
+
if (typeof result === "string") {
|
|
99
|
+
sha1 = result;
|
|
100
|
+
} else {
|
|
101
|
+
sha1 = result.sha1;
|
|
102
|
+
if (result.content) {
|
|
103
|
+
content = result.content;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
93
106
|
}
|
|
94
107
|
let fullKey = Buffer.concat([partialKey, Buffer.from(sha1, "hex")]);
|
|
95
108
|
let result;
|
|
@@ -110,7 +123,7 @@ class Transformer {
|
|
|
110
123
|
: await this._workerFarm.transform(
|
|
111
124
|
localPath,
|
|
112
125
|
transformerOptions,
|
|
113
|
-
|
|
126
|
+
content
|
|
114
127
|
);
|
|
115
128
|
if (sha1 !== data.sha1) {
|
|
116
129
|
fullKey = Buffer.concat([partialKey, Buffer.from(data.sha1, "hex")]);
|
|
@@ -24,19 +24,30 @@ const fs = require('fs');
|
|
|
24
24
|
const {Cache, stableHash} = require('metro-cache');
|
|
25
25
|
const path = require('path');
|
|
26
26
|
|
|
27
|
+
type LazySha1Fn = string => Promise<{content?: Buffer, sha1: string}>;
|
|
28
|
+
type EagerSha1Fn = string => string;
|
|
29
|
+
|
|
27
30
|
class Transformer {
|
|
28
31
|
_config: ConfigT;
|
|
29
32
|
_cache: Cache<TransformResult<>>;
|
|
30
33
|
_baseHash: string;
|
|
31
|
-
_getSha1:
|
|
34
|
+
_getSha1: EagerSha1Fn | LazySha1Fn;
|
|
32
35
|
_workerFarm: WorkerFarm;
|
|
33
36
|
|
|
34
|
-
constructor(
|
|
37
|
+
constructor(
|
|
38
|
+
config: ConfigT,
|
|
39
|
+
getSha1FnOrOpts:
|
|
40
|
+
| $ReadOnly<{unstable_getOrComputeSha1: LazySha1Fn}>
|
|
41
|
+
| EagerSha1Fn,
|
|
42
|
+
) {
|
|
35
43
|
this._config = config;
|
|
36
44
|
|
|
37
45
|
this._config.watchFolders.forEach(verifyRootExists);
|
|
38
46
|
this._cache = new Cache(config.cacheStores);
|
|
39
|
-
this._getSha1 =
|
|
47
|
+
this._getSha1 =
|
|
48
|
+
typeof getSha1FnOrOpts === 'function'
|
|
49
|
+
? getSha1FnOrOpts
|
|
50
|
+
: getSha1FnOrOpts.unstable_getOrComputeSha1;
|
|
40
51
|
|
|
41
52
|
// Remove the transformer config params that we don't want to pass to the
|
|
42
53
|
// transformer. We should change the config object and move them away so we
|
|
@@ -129,11 +140,21 @@ class Transformer {
|
|
|
129
140
|
]);
|
|
130
141
|
|
|
131
142
|
let sha1: string;
|
|
143
|
+
let content: ?Buffer;
|
|
132
144
|
if (fileBuffer) {
|
|
133
145
|
// Shortcut for virtual modules which provide the contents with the filename.
|
|
134
146
|
sha1 = crypto.createHash('sha1').update(fileBuffer).digest('hex');
|
|
147
|
+
content = fileBuffer;
|
|
135
148
|
} else {
|
|
136
|
-
|
|
149
|
+
const result = await this._getSha1(filePath);
|
|
150
|
+
if (typeof result === 'string') {
|
|
151
|
+
sha1 = result;
|
|
152
|
+
} else {
|
|
153
|
+
sha1 = result.sha1;
|
|
154
|
+
if (result.content) {
|
|
155
|
+
content = result.content;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
137
158
|
}
|
|
138
159
|
|
|
139
160
|
let fullKey = Buffer.concat([partialKey, Buffer.from(sha1, 'hex')]);
|
|
@@ -158,7 +179,7 @@ class Transformer {
|
|
|
158
179
|
: await this._workerFarm.transform(
|
|
159
180
|
localPath,
|
|
160
181
|
transformerOptions,
|
|
161
|
-
|
|
182
|
+
content,
|
|
162
183
|
);
|
|
163
184
|
|
|
164
185
|
// Only re-compute the full key if the SHA-1 changed. This is because
|
package/src/HmrServer.js.flow
CHANGED
|
@@ -169,6 +169,9 @@ class HmrServer<TClient: Client> {
|
|
|
169
169
|
runModule: runModule || 'false',
|
|
170
170
|
shallow: 'true',
|
|
171
171
|
};
|
|
172
|
+
// the legacy url object is parsed with both "search" and "query" fields.
|
|
173
|
+
// for the "query" field to be used when formatting the object bach to string, the "search" field must be empty.
|
|
174
|
+
// https://nodejs.org/api/url.html#urlformaturlobject:~:text=If%20the%20urlObject.search%20property%20is%20undefined
|
|
172
175
|
clientUrl.search = '';
|
|
173
176
|
|
|
174
177
|
clientGroup = {
|
|
@@ -28,16 +28,19 @@ async function dependencies(args, config) {
|
|
|
28
28
|
const outStream =
|
|
29
29
|
args.output != null ? fs.createWriteStream(args.output) : process.stdout;
|
|
30
30
|
const server = new Server(config);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
try {
|
|
32
|
+
const deps = await server.getOrderedDependencyPaths(options);
|
|
33
|
+
deps.forEach((modulePath) => {
|
|
34
|
+
const isInsideProjectRoots =
|
|
35
|
+
config.watchFolders.filter((root) => modulePath.startsWith(root))
|
|
36
|
+
.length > 0;
|
|
37
|
+
if (isInsideProjectRoots) {
|
|
38
|
+
outStream.write(modulePath + "\n");
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
} finally {
|
|
42
|
+
await server.end();
|
|
43
|
+
}
|
|
41
44
|
return args.output != null
|
|
42
45
|
? promisify(outStream.end).bind(outStream)()
|
|
43
46
|
: Promise.resolve();
|
|
@@ -60,21 +60,24 @@ async function dependencies(args: Args, config: ConfigT) {
|
|
|
60
60
|
args.output != null ? fs.createWriteStream(args.output) : process.stdout;
|
|
61
61
|
|
|
62
62
|
const server = new Server(config);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
63
|
+
try {
|
|
64
|
+
const deps = await server.getOrderedDependencyPaths(options);
|
|
65
|
+
deps.forEach(modulePath => {
|
|
66
|
+
// Temporary hack to disable listing dependencies not under this directory.
|
|
67
|
+
// Long term, we need either
|
|
68
|
+
// (a) JS code to not depend on anything outside this directory, or
|
|
69
|
+
// (b) Come up with a way to declare this dependency in Buck.
|
|
70
|
+
const isInsideProjectRoots =
|
|
71
|
+
config.watchFolders.filter(root => modulePath.startsWith(root)).length >
|
|
72
|
+
0;
|
|
73
|
+
if (isInsideProjectRoots) {
|
|
74
|
+
outStream.write(modulePath + '\n');
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
} finally {
|
|
78
|
+
await server.end();
|
|
79
|
+
}
|
|
76
80
|
|
|
77
|
-
await server.end();
|
|
78
81
|
return args.output != null
|
|
79
82
|
? // $FlowFixMe[method-unbinding]
|
|
80
83
|
promisify(outStream.end).bind(outStream)()
|
package/src/index.flow.js
CHANGED
|
@@ -264,7 +264,12 @@ exports.runBuild = async (
|
|
|
264
264
|
dev,
|
|
265
265
|
platform,
|
|
266
266
|
};
|
|
267
|
-
await output.save(metroBundle, outputOptions,
|
|
267
|
+
await output.save(metroBundle, outputOptions, (message) =>
|
|
268
|
+
config.reporter.update({
|
|
269
|
+
type: "bundle_save_log",
|
|
270
|
+
message,
|
|
271
|
+
})
|
|
272
|
+
);
|
|
268
273
|
}
|
|
269
274
|
return metroBundle;
|
|
270
275
|
} finally {
|
package/src/index.flow.js.flow
CHANGED
|
@@ -98,7 +98,7 @@ export type RunBuildOptions = {
|
|
|
98
98
|
onComplete?: () => void,
|
|
99
99
|
onProgress?: (transformedFileCount: number, totalFileCount: number) => void,
|
|
100
100
|
minify?: boolean,
|
|
101
|
-
output?: {
|
|
101
|
+
output?: $ReadOnly<{
|
|
102
102
|
build: (
|
|
103
103
|
MetroServer,
|
|
104
104
|
RequestOptions,
|
|
@@ -114,10 +114,10 @@ export type RunBuildOptions = {
|
|
|
114
114
|
...
|
|
115
115
|
},
|
|
116
116
|
OutputOptions,
|
|
117
|
-
(
|
|
117
|
+
(logMessage: string) => void,
|
|
118
118
|
) => Promise<mixed>,
|
|
119
119
|
...
|
|
120
|
-
}
|
|
120
|
+
}>,
|
|
121
121
|
platform?: string,
|
|
122
122
|
sourceMap?: boolean,
|
|
123
123
|
sourceMapUrl?: string,
|
|
@@ -428,8 +428,12 @@ exports.runBuild = async (
|
|
|
428
428
|
platform,
|
|
429
429
|
};
|
|
430
430
|
|
|
431
|
-
|
|
432
|
-
|
|
431
|
+
await output.save(metroBundle, outputOptions, message =>
|
|
432
|
+
config.reporter.update({
|
|
433
|
+
type: 'bundle_save_log',
|
|
434
|
+
message,
|
|
435
|
+
}),
|
|
436
|
+
);
|
|
433
437
|
}
|
|
434
438
|
|
|
435
439
|
return metroBundle;
|
|
@@ -136,6 +136,9 @@ class TerminalReporter {
|
|
|
136
136
|
case "bundle_build_done":
|
|
137
137
|
this._logBundleBuildDone(event.buildID);
|
|
138
138
|
break;
|
|
139
|
+
case "bundle_save_log":
|
|
140
|
+
this.terminal.log("LOG:" + event.message);
|
|
141
|
+
break;
|
|
139
142
|
case "bundle_build_failed":
|
|
140
143
|
this._logBundleBuildFailed(event.buildID);
|
|
141
144
|
break;
|
|
@@ -237,6 +237,9 @@ class TerminalReporter {
|
|
|
237
237
|
case 'bundle_build_done':
|
|
238
238
|
this._logBundleBuildDone(event.buildID);
|
|
239
239
|
break;
|
|
240
|
+
case 'bundle_save_log':
|
|
241
|
+
this.terminal.log('LOG:' + event.message);
|
|
242
|
+
break;
|
|
240
243
|
case 'bundle_build_failed':
|
|
241
244
|
this._logBundleBuildFailed(event.buildID);
|
|
242
245
|
break;
|
package/src/lib/getMaxWorkers.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const os = require("os");
|
|
4
4
|
module.exports = (workers) => {
|
|
5
|
-
const cores = os.
|
|
5
|
+
const cores = os.availableParallelism();
|
|
6
6
|
return typeof workers === "number" && Number.isInteger(workers)
|
|
7
7
|
? Math.min(cores, workers > 0 ? workers : 1)
|
|
8
8
|
: Math.max(1, Math.ceil(cores * (0.5 + 0.5 * Math.exp(-cores * 0.07)) - 1));
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
const os = require('os');
|
|
15
15
|
|
|
16
16
|
module.exports = (workers: ?number): number => {
|
|
17
|
-
|
|
17
|
+
// $FlowFixMe[prop-missing] Missing Flow lib def for availableParallelism
|
|
18
|
+
const cores = os.availableParallelism();
|
|
18
19
|
return typeof workers === 'number' && Number.isInteger(workers)
|
|
19
20
|
? Math.min(cores, workers > 0 ? workers : 1)
|
|
20
21
|
: Math.max(1, Math.ceil(cores * (0.5 + 0.5 * Math.exp(-cores * 0.07)) - 1));
|
|
@@ -7,10 +7,10 @@ function getPreludeCode({
|
|
|
7
7
|
requireCycleIgnorePatterns,
|
|
8
8
|
}) {
|
|
9
9
|
const vars = [
|
|
10
|
-
"__BUNDLE_START_TIME__=
|
|
10
|
+
"__BUNDLE_START_TIME__=globalThis.nativePerformanceNow?nativePerformanceNow():Date.now()",
|
|
11
11
|
`__DEV__=${String(isDev)}`,
|
|
12
12
|
...formatExtraVars(extraVars),
|
|
13
|
-
"process=
|
|
13
|
+
"process=globalThis.process||{}",
|
|
14
14
|
`__METRO_GLOBAL_PREFIX__='${globalPrefix}'`,
|
|
15
15
|
];
|
|
16
16
|
if (isDev) {
|
|
@@ -25,10 +25,10 @@ function getPreludeCode({
|
|
|
25
25
|
const vars = [
|
|
26
26
|
// Ensure these variable names match the ones referenced in metro-runtime
|
|
27
27
|
// require.js
|
|
28
|
-
'__BUNDLE_START_TIME__=
|
|
28
|
+
'__BUNDLE_START_TIME__=globalThis.nativePerformanceNow?nativePerformanceNow():Date.now()',
|
|
29
29
|
`__DEV__=${String(isDev)}`,
|
|
30
30
|
...formatExtraVars(extraVars),
|
|
31
|
-
'process=
|
|
31
|
+
'process=globalThis.process||{}',
|
|
32
32
|
`__METRO_GLOBAL_PREFIX__='${globalPrefix}'`,
|
|
33
33
|
];
|
|
34
34
|
|
package/src/lib/reporting.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const chalk = require("chalk");
|
|
4
|
-
const stripAnsi = require("strip-ansi");
|
|
5
4
|
const util = require("util");
|
|
6
5
|
function logWarning(terminal, format, ...args) {
|
|
7
6
|
const str = util.format(format, ...args);
|
|
@@ -11,7 +10,10 @@ function logError(terminal, format, ...args) {
|
|
|
11
10
|
terminal.log(
|
|
12
11
|
"%s %s",
|
|
13
12
|
chalk.red.inverse.bold(" ERROR "),
|
|
14
|
-
util.format(
|
|
13
|
+
util.format(
|
|
14
|
+
chalk.supportsColor ? format : util.stripVTControlCharacters(format),
|
|
15
|
+
...args
|
|
16
|
+
)
|
|
15
17
|
);
|
|
16
18
|
}
|
|
17
19
|
function logInfo(terminal, format, ...args) {
|
|
@@ -17,7 +17,6 @@ import type {CustomResolverOptions} from 'metro-resolver';
|
|
|
17
17
|
import type {CustomTransformOptions} from 'metro-transform-worker';
|
|
18
18
|
|
|
19
19
|
const chalk = require('chalk');
|
|
20
|
-
const stripAnsi = require('strip-ansi');
|
|
21
20
|
const util = require('util');
|
|
22
21
|
|
|
23
22
|
export type BundleDetails = {
|
|
@@ -62,6 +61,11 @@ export type ReportableEvent =
|
|
|
62
61
|
type: 'bundle_build_failed',
|
|
63
62
|
...
|
|
64
63
|
}
|
|
64
|
+
| {
|
|
65
|
+
type: 'bundle_save_log',
|
|
66
|
+
message: string,
|
|
67
|
+
...
|
|
68
|
+
}
|
|
65
69
|
| {
|
|
66
70
|
buildID: string,
|
|
67
71
|
bundleDetails: BundleDetails,
|
|
@@ -207,7 +211,10 @@ function logError(
|
|
|
207
211
|
// in various places outside of where Metro is currently running.
|
|
208
212
|
// If the current terminal does not support color, we'll strip the colors
|
|
209
213
|
// here.
|
|
210
|
-
util.format(
|
|
214
|
+
util.format(
|
|
215
|
+
chalk.supportsColor ? format : util.stripVTControlCharacters(format),
|
|
216
|
+
...args,
|
|
217
|
+
),
|
|
211
218
|
);
|
|
212
219
|
}
|
|
213
220
|
|
|
@@ -12,6 +12,7 @@ const baseIgnoredInlineRequires = [
|
|
|
12
12
|
"react",
|
|
13
13
|
"react/jsx-dev-runtime",
|
|
14
14
|
"react/jsx-runtime",
|
|
15
|
+
"react-compiler-runtime",
|
|
15
16
|
"react-native",
|
|
16
17
|
];
|
|
17
18
|
async function calcTransformerOptions(
|
|
@@ -78,6 +79,10 @@ async function calcTransformerOptions(
|
|
|
78
79
|
);
|
|
79
80
|
return {
|
|
80
81
|
...baseOptions,
|
|
82
|
+
inlinePlatform:
|
|
83
|
+
transform?.unstable_inlinePlatform != null
|
|
84
|
+
? transform.unstable_inlinePlatform
|
|
85
|
+
: true,
|
|
81
86
|
inlineRequires: transform?.inlineRequires || false,
|
|
82
87
|
experimentalImportSupport: transform?.experimentalImportSupport || false,
|
|
83
88
|
unstable_disableES6Transforms:
|
|
@@ -41,6 +41,7 @@ const baseIgnoredInlineRequires = [
|
|
|
41
41
|
'react',
|
|
42
42
|
'react/jsx-dev-runtime',
|
|
43
43
|
'react/jsx-runtime',
|
|
44
|
+
'react-compiler-runtime',
|
|
44
45
|
'react-native',
|
|
45
46
|
];
|
|
46
47
|
|
|
@@ -112,6 +113,10 @@ async function calcTransformerOptions(
|
|
|
112
113
|
|
|
113
114
|
return {
|
|
114
115
|
...baseOptions,
|
|
116
|
+
inlinePlatform:
|
|
117
|
+
transform?.unstable_inlinePlatform != null
|
|
118
|
+
? transform.unstable_inlinePlatform
|
|
119
|
+
: true,
|
|
115
120
|
inlineRequires: transform?.inlineRequires || false,
|
|
116
121
|
experimentalImportSupport: transform?.experimentalImportSupport || false,
|
|
117
122
|
unstable_disableES6Transforms:
|
|
@@ -61,19 +61,23 @@ function createFileMap(config, options) {
|
|
|
61
61
|
? null
|
|
62
62
|
: config.resolver.dependencyExtractor;
|
|
63
63
|
const computeDependencies = dependencyExtractor != null;
|
|
64
|
+
const watch = options?.watch == null ? !ci.isCI : options.watch;
|
|
65
|
+
const { enabled: autoSaveEnabled, ...autoSaveOpts } =
|
|
66
|
+
config.watcher.unstable_autoSaveCache ?? {};
|
|
67
|
+
const autoSave = watch && autoSaveEnabled ? autoSaveOpts : false;
|
|
64
68
|
return _metroFileMap.default.create({
|
|
65
69
|
cacheManagerFactory:
|
|
66
70
|
config?.unstable_fileMapCacheManagerFactory ??
|
|
67
|
-
((
|
|
68
|
-
new _metroFileMap.DiskCacheManager({
|
|
69
|
-
buildParameters,
|
|
71
|
+
((factoryParams) =>
|
|
72
|
+
new _metroFileMap.DiskCacheManager(factoryParams, {
|
|
70
73
|
cacheDirectory:
|
|
71
74
|
config.fileMapCacheDirectory ?? config.hasteMapCacheDirectory,
|
|
72
75
|
cacheFilePrefix: options?.cacheFilePrefix,
|
|
76
|
+
autoSave,
|
|
73
77
|
})),
|
|
74
78
|
perfLoggerFactory: config.unstable_perfLoggerFactory,
|
|
75
79
|
computeDependencies,
|
|
76
|
-
computeSha1:
|
|
80
|
+
computeSha1: !config.watcher.unstable_lazySha1,
|
|
77
81
|
dependencyExtractor: config.resolver.dependencyExtractor,
|
|
78
82
|
enableHastePackages: config?.resolver.enableGlobalPackages,
|
|
79
83
|
enableSymlinks: true,
|
|
@@ -101,7 +105,7 @@ function createFileMap(config, options) {
|
|
|
101
105
|
roots: config.watchFolders,
|
|
102
106
|
throwOnModuleCollision: options?.throwOnModuleCollision ?? true,
|
|
103
107
|
useWatchman: config.resolver.useWatchman,
|
|
104
|
-
watch
|
|
108
|
+
watch,
|
|
105
109
|
watchmanDeferStates: config.watcher.watchman.deferStates,
|
|
106
110
|
});
|
|
107
111
|
}
|
|
@@ -68,19 +68,24 @@ function createFileMap(
|
|
|
68
68
|
: config.resolver.dependencyExtractor;
|
|
69
69
|
const computeDependencies = dependencyExtractor != null;
|
|
70
70
|
|
|
71
|
+
const watch = options?.watch == null ? !ci.isCI : options.watch;
|
|
72
|
+
const {enabled: autoSaveEnabled, ...autoSaveOpts} =
|
|
73
|
+
config.watcher.unstable_autoSaveCache ?? {};
|
|
74
|
+
const autoSave = watch && autoSaveEnabled ? autoSaveOpts : false;
|
|
75
|
+
|
|
71
76
|
return MetroFileMap.create({
|
|
72
77
|
cacheManagerFactory:
|
|
73
78
|
config?.unstable_fileMapCacheManagerFactory ??
|
|
74
|
-
(
|
|
75
|
-
new DiskCacheManager({
|
|
76
|
-
buildParameters,
|
|
79
|
+
(factoryParams =>
|
|
80
|
+
new DiskCacheManager(factoryParams, {
|
|
77
81
|
cacheDirectory:
|
|
78
82
|
config.fileMapCacheDirectory ?? config.hasteMapCacheDirectory,
|
|
79
83
|
cacheFilePrefix: options?.cacheFilePrefix,
|
|
84
|
+
autoSave,
|
|
80
85
|
})),
|
|
81
86
|
perfLoggerFactory: config.unstable_perfLoggerFactory,
|
|
82
87
|
computeDependencies,
|
|
83
|
-
computeSha1:
|
|
88
|
+
computeSha1: !config.watcher.unstable_lazySha1,
|
|
84
89
|
dependencyExtractor: config.resolver.dependencyExtractor,
|
|
85
90
|
enableHastePackages: config?.resolver.enableGlobalPackages,
|
|
86
91
|
enableSymlinks: true,
|
|
@@ -105,7 +110,7 @@ function createFileMap(
|
|
|
105
110
|
roots: config.watchFolders,
|
|
106
111
|
throwOnModuleCollision: options?.throwOnModuleCollision ?? true,
|
|
107
112
|
useWatchman: config.resolver.useWatchman,
|
|
108
|
-
watch
|
|
113
|
+
watch,
|
|
109
114
|
watchmanDeferStates: config.watcher.watchman.deferStates,
|
|
110
115
|
});
|
|
111
116
|
}
|
|
@@ -24,6 +24,13 @@ function getOrCreateMap(map, field) {
|
|
|
24
24
|
}
|
|
25
25
|
return subMap;
|
|
26
26
|
}
|
|
27
|
+
const missingSha1Error = (mixedPath) =>
|
|
28
|
+
new Error(`Failed to get the SHA-1 for: ${mixedPath}.
|
|
29
|
+
Potential causes:
|
|
30
|
+
1) The file is not watched. Ensure it is under the configured \`projectRoot\` or \`watchFolders\`.
|
|
31
|
+
2) Check \`blockList\` in your metro.config.js and make sure it isn't excluding the file path.
|
|
32
|
+
3) The file may have been deleted since it was resolved - try refreshing your app.
|
|
33
|
+
4) Otherwise, this is a bug in Metro or the configured resolver - please report it.`);
|
|
27
34
|
class DependencyGraph extends EventEmitter {
|
|
28
35
|
constructor(config, options) {
|
|
29
36
|
super();
|
|
@@ -37,6 +44,7 @@ class DependencyGraph extends EventEmitter {
|
|
|
37
44
|
hasReducedPerformance: !!hasReducedPerformance,
|
|
38
45
|
});
|
|
39
46
|
const fileMap = createFileMap(config, {
|
|
47
|
+
throwOnModuleCollision: false,
|
|
40
48
|
watch,
|
|
41
49
|
});
|
|
42
50
|
fileMap.setMaxListeners(1000);
|
|
@@ -178,13 +186,17 @@ class DependencyGraph extends EventEmitter {
|
|
|
178
186
|
getSha1(filename) {
|
|
179
187
|
const sha1 = this._fileSystem.getSha1(filename);
|
|
180
188
|
if (!sha1) {
|
|
181
|
-
throw
|
|
182
|
-
Potential causes:
|
|
183
|
-
1) You have symlinks in your project - watchman does not follow symlinks.
|
|
184
|
-
2) Check \`blockList\` in your metro.config.js and make sure it isn't excluding the file path.`);
|
|
189
|
+
throw missingSha1Error(filename);
|
|
185
190
|
}
|
|
186
191
|
return sha1;
|
|
187
192
|
}
|
|
193
|
+
async unstable_getOrComputeSha1(mixedPath) {
|
|
194
|
+
const result = await this._fileSystem.getOrComputeSha1(mixedPath);
|
|
195
|
+
if (!result || !result.sha1) {
|
|
196
|
+
throw missingSha1Error(mixedPath);
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
188
200
|
getWatcher() {
|
|
189
201
|
return this._haste;
|
|
190
202
|
}
|
|
@@ -55,6 +55,14 @@ function getOrCreateMap<T>(
|
|
|
55
55
|
return subMap;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
const missingSha1Error = (mixedPath: string) =>
|
|
59
|
+
new Error(`Failed to get the SHA-1 for: ${mixedPath}.
|
|
60
|
+
Potential causes:
|
|
61
|
+
1) The file is not watched. Ensure it is under the configured \`projectRoot\` or \`watchFolders\`.
|
|
62
|
+
2) Check \`blockList\` in your metro.config.js and make sure it isn't excluding the file path.
|
|
63
|
+
3) The file may have been deleted since it was resolved - try refreshing your app.
|
|
64
|
+
4) Otherwise, this is a bug in Metro or the configured resolver - please report it.`);
|
|
65
|
+
|
|
58
66
|
class DependencyGraph extends EventEmitter {
|
|
59
67
|
_config: ConfigT;
|
|
60
68
|
_haste: MetroFileMap;
|
|
@@ -101,7 +109,10 @@ class DependencyGraph extends EventEmitter {
|
|
|
101
109
|
type: 'dep_graph_loading',
|
|
102
110
|
hasReducedPerformance: !!hasReducedPerformance,
|
|
103
111
|
});
|
|
104
|
-
const fileMap = createFileMap(config, {
|
|
112
|
+
const fileMap = createFileMap(config, {
|
|
113
|
+
throwOnModuleCollision: false,
|
|
114
|
+
watch,
|
|
115
|
+
});
|
|
105
116
|
|
|
106
117
|
// We can have a lot of graphs listening to Haste for changes.
|
|
107
118
|
// Bump this up to silence the max listeners EventEmitter warning.
|
|
@@ -255,19 +266,25 @@ class DependencyGraph extends EventEmitter {
|
|
|
255
266
|
|
|
256
267
|
getSha1(filename: string): string {
|
|
257
268
|
const sha1 = this._fileSystem.getSha1(filename);
|
|
258
|
-
|
|
259
269
|
if (!sha1) {
|
|
260
|
-
throw
|
|
261
|
-
`SHA-1 for file ${filename} is not computed.
|
|
262
|
-
Potential causes:
|
|
263
|
-
1) You have symlinks in your project - watchman does not follow symlinks.
|
|
264
|
-
2) Check \`blockList\` in your metro.config.js and make sure it isn't excluding the file path.`,
|
|
265
|
-
);
|
|
270
|
+
throw missingSha1Error(filename);
|
|
266
271
|
}
|
|
267
|
-
|
|
268
272
|
return sha1;
|
|
269
273
|
}
|
|
270
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Used when watcher.unstable_lazySha1 is true
|
|
277
|
+
*/
|
|
278
|
+
async unstable_getOrComputeSha1(
|
|
279
|
+
mixedPath: string,
|
|
280
|
+
): Promise<{content?: Buffer, sha1: string}> {
|
|
281
|
+
const result = await this._fileSystem.getOrComputeSha1(mixedPath);
|
|
282
|
+
if (!result || !result.sha1) {
|
|
283
|
+
throw missingSha1Error(mixedPath);
|
|
284
|
+
}
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
287
|
+
|
|
271
288
|
getWatcher(): EventEmitter {
|
|
272
289
|
return this._haste;
|
|
273
290
|
}
|
|
@@ -6,7 +6,7 @@ function writeSourcemap(fileName, contents, log) {
|
|
|
6
6
|
return Promise.resolve();
|
|
7
7
|
}
|
|
8
8
|
log("Writing sourcemap output to:", fileName);
|
|
9
|
-
const writeMap = writeFile(fileName, contents
|
|
9
|
+
const writeMap = writeFile(fileName, contents);
|
|
10
10
|
writeMap.then(() => log("Done writing sourcemap output"));
|
|
11
11
|
return writeMap;
|
|
12
12
|
}
|
|
@@ -22,7 +22,7 @@ function writeSourcemap(
|
|
|
22
22
|
return Promise.resolve();
|
|
23
23
|
}
|
|
24
24
|
log('Writing sourcemap output to:', fileName);
|
|
25
|
-
const writeMap = writeFile(fileName, contents
|
|
25
|
+
const writeMap = writeFile(fileName, contents);
|
|
26
26
|
// $FlowFixMe[unused-promise]
|
|
27
27
|
writeMap.then(() => log('Done writing sourcemap output'));
|
|
28
28
|
return writeMap;
|
|
@@ -37,7 +37,7 @@ async function saveBundleAndMap(bundle, options, log) {
|
|
|
37
37
|
}
|
|
38
38
|
writeFns.push(async () => {
|
|
39
39
|
log(`Writing sourcemap output to: ${sourcemapOutput}`);
|
|
40
|
-
await writeFile(sourcemapOutput, map
|
|
40
|
+
await writeFile(sourcemapOutput, map);
|
|
41
41
|
log("Done writing sourcemap output");
|
|
42
42
|
});
|
|
43
43
|
}
|
|
@@ -49,7 +49,7 @@ async function saveBundleAndMap(
|
|
|
49
49
|
...
|
|
50
50
|
},
|
|
51
51
|
options: OutputOptions,
|
|
52
|
-
log:
|
|
52
|
+
log: string => void,
|
|
53
53
|
): Promise<mixed> {
|
|
54
54
|
const {
|
|
55
55
|
bundleOutput,
|
|
@@ -76,7 +76,7 @@ async function saveBundleAndMap(
|
|
|
76
76
|
|
|
77
77
|
writeFns.push(async () => {
|
|
78
78
|
log(`Writing sourcemap output to: ${sourcemapOutput}`);
|
|
79
|
-
await writeFile(sourcemapOutput, map
|
|
79
|
+
await writeFile(sourcemapOutput, map);
|
|
80
80
|
log('Done writing sourcemap output');
|
|
81
81
|
});
|
|
82
82
|
}
|
|
@@ -4,22 +4,19 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @flow
|
|
7
|
+
* @flow strict-local
|
|
8
8
|
* @format
|
|
9
9
|
* @oncall react_native
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
-
const denodeify = require('denodeify');
|
|
15
14
|
const fs = require('fs');
|
|
16
15
|
const throat = require('throat');
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
) => Promise<mixed>;
|
|
23
|
-
const writeFile: WriteFn = throat(128, denodeify(fs.writeFile));
|
|
17
|
+
const writeFile: typeof fs.promises.writeFile = throat(
|
|
18
|
+
128,
|
|
19
|
+
fs.promises.writeFile,
|
|
20
|
+
);
|
|
24
21
|
|
|
25
22
|
module.exports = writeFile;
|