metro 0.76.4 → 0.76.6
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 +24 -23
- package/src/Assets.js +35 -3
- package/src/Assets.js.flow +38 -3
- package/src/Bundler/util.js +0 -96
- package/src/Bundler/util.js.flow +0 -124
- package/src/DeltaBundler/DeltaCalculator.js +7 -0
- package/src/DeltaBundler/DeltaCalculator.js.flow +7 -0
- package/src/DeltaBundler/Graph.js +86 -31
- package/src/DeltaBundler/Graph.js.flow +98 -31
- package/src/DeltaBundler/Serializers/helpers/js.js +4 -1
- package/src/DeltaBundler/Serializers/helpers/js.js.flow +4 -1
- package/src/DeltaBundler/Serializers/hmrJSBundle.js +2 -1
- package/src/DeltaBundler/Serializers/hmrJSBundle.js.flow +2 -1
- package/src/DeltaBundler/Transformer.js +1 -0
- package/src/DeltaBundler/Transformer.js.flow +1 -0
- package/src/DeltaBundler/types.flow.js.flow +9 -7
- package/src/Server.js +32 -14
- package/src/Server.js.flow +45 -20
- package/src/index.d.ts +3 -1
- package/src/index.flow.js +5 -0
- package/src/index.flow.js.flow +8 -0
- package/src/lib/parseOptionsFromUrl.js +4 -3
- package/src/lib/parseOptionsFromUrl.js.flow +4 -3
package/src/Server.js.flow
CHANGED
|
@@ -31,7 +31,8 @@ import type {
|
|
|
31
31
|
ResolverInputOptions,
|
|
32
32
|
SplitBundleOptions,
|
|
33
33
|
} from './shared/types.flow';
|
|
34
|
-
import type {IncomingMessage
|
|
34
|
+
import type {IncomingMessage} from 'connect';
|
|
35
|
+
import type {ServerResponse} from 'http';
|
|
35
36
|
import type {CacheStore} from 'metro-cache';
|
|
36
37
|
import type {ConfigT, RootPerfLogger} from 'metro-config/src/configTypes.flow';
|
|
37
38
|
import type {
|
|
@@ -65,6 +66,8 @@ const {codeFrameColumns} = require('@babel/code-frame');
|
|
|
65
66
|
const MultipartResponse = require('./Server/MultipartResponse');
|
|
66
67
|
const debug = require('debug')('Metro:Server');
|
|
67
68
|
const fs = require('graceful-fs');
|
|
69
|
+
const invariant = require('invariant');
|
|
70
|
+
const jscSafeUrl = require('jsc-safe-url');
|
|
68
71
|
const {
|
|
69
72
|
Logger,
|
|
70
73
|
Logger: {createActionStartEntry, createActionEndEntry, log},
|
|
@@ -476,11 +479,11 @@ class Server {
|
|
|
476
479
|
processRequest: (
|
|
477
480
|
IncomingMessage,
|
|
478
481
|
ServerResponse,
|
|
479
|
-
((e: ?Error) =>
|
|
482
|
+
((e: ?Error) => void),
|
|
480
483
|
) => void = (
|
|
481
484
|
req: IncomingMessage,
|
|
482
485
|
res: ServerResponse,
|
|
483
|
-
next: (?Error) =>
|
|
486
|
+
next: (?Error) => void,
|
|
484
487
|
) => {
|
|
485
488
|
this._processRequest(req, res, next).catch(next);
|
|
486
489
|
};
|
|
@@ -489,14 +492,19 @@ class Server {
|
|
|
489
492
|
return parseOptionsFromUrl(url, new Set(this._config.resolver.platforms));
|
|
490
493
|
}
|
|
491
494
|
|
|
495
|
+
_rewriteAndNormalizeUrl(requestUrl: string): string {
|
|
496
|
+
return jscSafeUrl.toNormalUrl(
|
|
497
|
+
this._config.server.rewriteRequestUrl(jscSafeUrl.toNormalUrl(requestUrl)),
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
|
|
492
501
|
async _processRequest(
|
|
493
502
|
req: IncomingMessage,
|
|
494
503
|
res: ServerResponse,
|
|
495
|
-
next: (?Error) =>
|
|
504
|
+
next: (?Error) => void,
|
|
496
505
|
) {
|
|
497
506
|
const originalUrl = req.url;
|
|
498
|
-
req.url = this.
|
|
499
|
-
|
|
507
|
+
req.url = this._rewriteAndNormalizeUrl(req.url);
|
|
500
508
|
const urlObj = url.parse(req.url, true);
|
|
501
509
|
const {host} = req.headers;
|
|
502
510
|
debug(
|
|
@@ -899,7 +907,7 @@ class Server {
|
|
|
899
907
|
bundle: bundleCode,
|
|
900
908
|
};
|
|
901
909
|
},
|
|
902
|
-
finish({req, mres, result}) {
|
|
910
|
+
finish({req, mres, serializerOptions, result}) {
|
|
903
911
|
if (
|
|
904
912
|
// We avoid parsing the dates since the client should never send a more
|
|
905
913
|
// recent date than the one returned by the Delta Bundler (if that's the
|
|
@@ -916,6 +924,9 @@ class Server {
|
|
|
916
924
|
String(result.numModifiedFiles),
|
|
917
925
|
);
|
|
918
926
|
mres.setHeader(DELTA_ID_HEADER, String(result.nextRevId));
|
|
927
|
+
if (serializerOptions?.sourceUrl != null) {
|
|
928
|
+
mres.setHeader('Content-Location', serializerOptions.sourceUrl);
|
|
929
|
+
}
|
|
919
930
|
mres.setHeader('Content-Type', 'application/javascript; charset=UTF-8');
|
|
920
931
|
mres.setHeader('Last-Modified', result.lastModifiedDate.toUTCString());
|
|
921
932
|
mres.setHeader(
|
|
@@ -1112,19 +1123,33 @@ class Server {
|
|
|
1112
1123
|
/* $FlowFixMe: where is `rawBody` defined? Is it added by the `connect` framework? */
|
|
1113
1124
|
const body = await req.rawBody;
|
|
1114
1125
|
const parsedBody = JSON.parse(body);
|
|
1115
|
-
|
|
1116
|
-
|
|
1126
|
+
|
|
1127
|
+
const rewriteAndNormalizeStackFrame = <T>(
|
|
1128
|
+
frame: T,
|
|
1129
|
+
lineNumber: number,
|
|
1130
|
+
): T => {
|
|
1131
|
+
invariant(
|
|
1132
|
+
frame != null && typeof frame === 'object',
|
|
1133
|
+
'Bad stack frame at line %d, expected object, received: %s',
|
|
1134
|
+
lineNumber,
|
|
1135
|
+
typeof frame,
|
|
1136
|
+
);
|
|
1137
|
+
const frameFile = frame.file;
|
|
1138
|
+
if (typeof frameFile === 'string' && frameFile.includes('://')) {
|
|
1117
1139
|
return {
|
|
1118
1140
|
...frame,
|
|
1119
|
-
file: this.
|
|
1141
|
+
file: this._rewriteAndNormalizeUrl(frameFile),
|
|
1120
1142
|
};
|
|
1121
1143
|
}
|
|
1122
1144
|
return frame;
|
|
1123
|
-
}
|
|
1145
|
+
};
|
|
1146
|
+
|
|
1147
|
+
const stack = parsedBody.stack.map(rewriteAndNormalizeStackFrame);
|
|
1124
1148
|
// In case of multiple bundles / HMR, some stack frames can have different URLs from others
|
|
1125
1149
|
const urls = new Set<string>();
|
|
1126
1150
|
|
|
1127
1151
|
stack.forEach(frame => {
|
|
1152
|
+
// These urls have been rewritten and normalized above.
|
|
1128
1153
|
const sourceUrl = frame.file;
|
|
1129
1154
|
// Skip `/debuggerWorker.js` which does not need symbolication.
|
|
1130
1155
|
if (
|
|
@@ -1139,8 +1164,11 @@ class Server {
|
|
|
1139
1164
|
|
|
1140
1165
|
debug('Getting source maps for symbolication');
|
|
1141
1166
|
const sourceMaps = await Promise.all(
|
|
1142
|
-
|
|
1143
|
-
|
|
1167
|
+
Array.from(urls.values()).map(normalizedUrl =>
|
|
1168
|
+
this._explodedSourceMapForBundleOptions(
|
|
1169
|
+
this._parseOptions(normalizedUrl),
|
|
1170
|
+
),
|
|
1171
|
+
),
|
|
1144
1172
|
);
|
|
1145
1173
|
|
|
1146
1174
|
debug('Performing fast symbolication');
|
|
@@ -1168,12 +1196,9 @@ class Server {
|
|
|
1168
1196
|
}
|
|
1169
1197
|
}
|
|
1170
1198
|
|
|
1171
|
-
async
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
new Set(this._config.resolver.platforms),
|
|
1175
|
-
);
|
|
1176
|
-
|
|
1199
|
+
async _explodedSourceMapForBundleOptions(
|
|
1200
|
+
bundleOptions: BundleOptions,
|
|
1201
|
+
): Promise<ExplodedSourceMap> {
|
|
1177
1202
|
const {
|
|
1178
1203
|
entryFile,
|
|
1179
1204
|
graphOptions,
|
|
@@ -1181,7 +1206,7 @@ class Server {
|
|
|
1181
1206
|
resolverOptions,
|
|
1182
1207
|
serializerOptions,
|
|
1183
1208
|
transformOptions,
|
|
1184
|
-
} = splitBundleOptions(
|
|
1209
|
+
} = splitBundleOptions(bundleOptions);
|
|
1185
1210
|
|
|
1186
1211
|
/**
|
|
1187
1212
|
* `entryFile` is relative to projectRoot, we need to use resolution function
|
package/src/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from './ModuleGraph/worker/collectDependencies';
|
|
|
14
14
|
export * from './Server';
|
|
15
15
|
export * from './lib/reporting';
|
|
16
16
|
|
|
17
|
+
import type {HandleFunction} from 'connect';
|
|
17
18
|
import type {EventEmitter} from 'events';
|
|
18
19
|
import type {IncomingMessage, Server as HttpServer} from 'http';
|
|
19
20
|
import type {Server as HttpsServer} from 'https';
|
|
@@ -72,6 +73,7 @@ export interface RunServerOptions {
|
|
|
72
73
|
/** @deprecated since version 0.61 */
|
|
73
74
|
secureKey?: string;
|
|
74
75
|
|
|
76
|
+
unstable_extraMiddleware?: ReadonlyArray<HandleFunction>;
|
|
75
77
|
waitForBundler?: boolean;
|
|
76
78
|
watch?: boolean;
|
|
77
79
|
websocketEndpoints?: {
|
|
@@ -126,7 +128,7 @@ export function runMetro(
|
|
|
126
128
|
options?: RunMetroOptions,
|
|
127
129
|
): Promise<MetroServer>;
|
|
128
130
|
|
|
129
|
-
export function
|
|
131
|
+
export function createConnectMiddleware(
|
|
130
132
|
config: ConfigT,
|
|
131
133
|
options?: RunMetroOptions,
|
|
132
134
|
): Promise<MetroMiddleWare>;
|
package/src/index.flow.js
CHANGED
|
@@ -134,6 +134,7 @@ exports.runServer = async (
|
|
|
134
134
|
// deprecated
|
|
135
135
|
secureKey,
|
|
136
136
|
// deprecated
|
|
137
|
+
unstable_extraMiddleware,
|
|
137
138
|
waitForBundler = false,
|
|
138
139
|
websocketEndpoints = {},
|
|
139
140
|
watch,
|
|
@@ -161,6 +162,9 @@ exports.runServer = async (
|
|
|
161
162
|
}
|
|
162
163
|
);
|
|
163
164
|
serverApp.use(middleware);
|
|
165
|
+
for (const handler of unstable_extraMiddleware ?? []) {
|
|
166
|
+
serverApp.use(handler);
|
|
167
|
+
}
|
|
164
168
|
let inspectorProxy = null;
|
|
165
169
|
if (config.server.runInspectorProxy) {
|
|
166
170
|
inspectorProxy = new InspectorProxy(config.projectRoot);
|
|
@@ -175,6 +179,7 @@ exports.runServer = async (
|
|
|
175
179
|
...secureServerOptions,
|
|
176
180
|
};
|
|
177
181
|
}
|
|
182
|
+
// $FlowFixMe[incompatible-call] 'http' and 'https' Flow types do not match
|
|
178
183
|
httpServer = https.createServer(options, serverApp);
|
|
179
184
|
} else {
|
|
180
185
|
httpServer = http.createServer(serverApp);
|
package/src/index.flow.js.flow
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
+
import type {HandleFunction} from 'connect';
|
|
14
15
|
import type {CustomResolverOptions} from 'metro-resolver';
|
|
15
16
|
import type {ReadOnlyGraph} from './DeltaBundler';
|
|
16
17
|
import type {ServerOptions} from './Server';
|
|
@@ -82,6 +83,7 @@ export type RunServerOptions = $ReadOnly<{
|
|
|
82
83
|
secure?: boolean, // deprecated
|
|
83
84
|
secureCert?: string, // deprecated
|
|
84
85
|
secureKey?: string, // deprecated
|
|
86
|
+
unstable_extraMiddleware?: $ReadOnlyArray<HandleFunction>,
|
|
85
87
|
waitForBundler?: boolean,
|
|
86
88
|
watch?: boolean,
|
|
87
89
|
websocketEndpoints?: $ReadOnly<{
|
|
@@ -254,6 +256,7 @@ exports.runServer = async (
|
|
|
254
256
|
secure, //deprecated
|
|
255
257
|
secureCert, // deprecated
|
|
256
258
|
secureKey, // deprecated
|
|
259
|
+
unstable_extraMiddleware,
|
|
257
260
|
waitForBundler = false,
|
|
258
261
|
websocketEndpoints = {},
|
|
259
262
|
watch,
|
|
@@ -283,6 +286,10 @@ exports.runServer = async (
|
|
|
283
286
|
|
|
284
287
|
serverApp.use(middleware);
|
|
285
288
|
|
|
289
|
+
for (const handler of unstable_extraMiddleware ?? []) {
|
|
290
|
+
serverApp.use(handler);
|
|
291
|
+
}
|
|
292
|
+
|
|
286
293
|
let inspectorProxy: ?InspectorProxy = null;
|
|
287
294
|
if (config.server.runInspectorProxy) {
|
|
288
295
|
inspectorProxy = new InspectorProxy(config.projectRoot);
|
|
@@ -299,6 +306,7 @@ exports.runServer = async (
|
|
|
299
306
|
...secureServerOptions,
|
|
300
307
|
};
|
|
301
308
|
}
|
|
309
|
+
// $FlowFixMe[incompatible-call] 'http' and 'https' Flow types do not match
|
|
302
310
|
httpServer = https.createServer(options, serverApp);
|
|
303
311
|
} else {
|
|
304
312
|
httpServer = http.createServer(serverApp);
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
const parsePlatformFilePath = require("../node-haste/lib/parsePlatformFilePath");
|
|
15
15
|
const parseCustomResolverOptions = require("./parseCustomResolverOptions");
|
|
16
16
|
const parseCustomTransformOptions = require("./parseCustomTransformOptions");
|
|
17
|
+
const jscSafeUrl = require("jsc-safe-url");
|
|
17
18
|
const nullthrows = require("nullthrows");
|
|
18
19
|
const path = require("path");
|
|
19
20
|
const url = require("url");
|
|
@@ -27,8 +28,8 @@ const getTransformProfile = (transformProfile) =>
|
|
|
27
28
|
transformProfile === "hermes-stable" || transformProfile === "hermes-canary"
|
|
28
29
|
? transformProfile
|
|
29
30
|
: "default";
|
|
30
|
-
module.exports = function parseOptionsFromUrl(
|
|
31
|
-
const parsedURL = nullthrows(url.parse(
|
|
31
|
+
module.exports = function parseOptionsFromUrl(normalizedRequestUrl, platforms) {
|
|
32
|
+
const parsedURL = nullthrows(url.parse(normalizedRequestUrl, true)); // `true` to parse the query param as an object.
|
|
32
33
|
const query = nullthrows(parsedURL.query);
|
|
33
34
|
const pathname =
|
|
34
35
|
query.bundleEntry ||
|
|
@@ -62,7 +63,7 @@ module.exports = function parseOptionsFromUrl(requestUrl, platforms) {
|
|
|
62
63
|
platform != null && platform.match(/^(android|ios)$/) ? "http" : "",
|
|
63
64
|
pathname: pathname.replace(/\.(bundle|delta)$/, ".map"),
|
|
64
65
|
}),
|
|
65
|
-
sourceUrl:
|
|
66
|
+
sourceUrl: jscSafeUrl.toJscSafeUrl(normalizedRequestUrl),
|
|
66
67
|
unstable_transformProfile: getTransformProfile(
|
|
67
68
|
query.unstable_transformProfile
|
|
68
69
|
),
|
|
@@ -17,6 +17,7 @@ import type {TransformProfile} from 'metro-babel-transformer';
|
|
|
17
17
|
const parsePlatformFilePath = require('../node-haste/lib/parsePlatformFilePath');
|
|
18
18
|
const parseCustomResolverOptions = require('./parseCustomResolverOptions');
|
|
19
19
|
const parseCustomTransformOptions = require('./parseCustomTransformOptions');
|
|
20
|
+
const jscSafeUrl = require('jsc-safe-url');
|
|
20
21
|
const nullthrows = require('nullthrows');
|
|
21
22
|
const path = require('path');
|
|
22
23
|
const url = require('url');
|
|
@@ -39,10 +40,10 @@ const getTransformProfile = (transformProfile: string): TransformProfile =>
|
|
|
39
40
|
: 'default';
|
|
40
41
|
|
|
41
42
|
module.exports = function parseOptionsFromUrl(
|
|
42
|
-
|
|
43
|
+
normalizedRequestUrl: string,
|
|
43
44
|
platforms: Set<string>,
|
|
44
45
|
): BundleOptions {
|
|
45
|
-
const parsedURL = nullthrows(url.parse(
|
|
46
|
+
const parsedURL = nullthrows(url.parse(normalizedRequestUrl, true)); // `true` to parse the query param as an object.
|
|
46
47
|
const query = nullthrows(parsedURL.query);
|
|
47
48
|
const pathname =
|
|
48
49
|
query.bundleEntry ||
|
|
@@ -77,7 +78,7 @@ module.exports = function parseOptionsFromUrl(
|
|
|
77
78
|
platform != null && platform.match(/^(android|ios)$/) ? 'http' : '',
|
|
78
79
|
pathname: pathname.replace(/\.(bundle|delta)$/, '.map'),
|
|
79
80
|
}),
|
|
80
|
-
sourceUrl:
|
|
81
|
+
sourceUrl: jscSafeUrl.toJscSafeUrl(normalizedRequestUrl),
|
|
81
82
|
unstable_transformProfile: getTransformProfile(
|
|
82
83
|
query.unstable_transformProfile,
|
|
83
84
|
),
|