metro 0.72.2 → 0.72.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +22 -21
- package/src/DeltaBundler/Serializers/hmrJSBundle.js +3 -1
- package/src/DeltaBundler/Serializers/hmrJSBundle.js.flow +2 -1
- package/src/DeltaBundler/Worker.js +0 -1
- package/src/DeltaBundler/Worker.js.flow +0 -1
- package/src/DeltaBundler/graphOperations.js +6 -6
- package/src/DeltaBundler/graphOperations.js.flow +5 -5
- package/src/ModuleGraph/node-haste/HasteFS.js +0 -1
- package/src/ModuleGraph/node-haste/HasteFS.js.flow +0 -1
- package/src/ModuleGraph/output/reverse-dependency-map-references.js +1 -2
- package/src/ModuleGraph/output/reverse-dependency-map-references.js.flow +0 -1
- package/src/ModuleGraph/types.flow.js.flow +0 -1
- package/src/Server/MultipartResponse.js +10 -12
- package/src/Server/MultipartResponse.js.flow +97 -0
- package/src/Server.js +59 -32
- package/src/Server.js.flow +53 -30
- package/src/index.js +0 -1
- package/src/index.js.flow +0 -1
- package/src/lib/CountingSet.js +0 -1
- package/src/lib/CountingSet.js.flow +0 -1
- package/src/lib/TerminalReporter.js +22 -24
- package/src/lib/TerminalReporter.js.flow +20 -24
- package/src/lib/parseOptionsFromUrl.js +5 -3
- package/src/lib/parseOptionsFromUrl.js.flow +4 -3
- package/src/node-haste/Package.js +0 -1
- package/src/node-haste/Package.js.flow +0 -1
- package/src/shared/output/bundle.js +0 -1
- package/src/shared/output/bundle.js.flow +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metro",
|
|
3
|
-
"version": "0.72.
|
|
3
|
+
"version": "0.72.4",
|
|
4
4
|
"description": "🚇 The JavaScript bundler for React Native.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": "src/cli.js",
|
|
@@ -35,23 +35,24 @@
|
|
|
35
35
|
"image-size": "^0.6.0",
|
|
36
36
|
"invariant": "^2.2.4",
|
|
37
37
|
"jest-worker": "^27.2.0",
|
|
38
|
+
"jsc-safe-url": "^0.2.2",
|
|
38
39
|
"lodash.throttle": "^4.1.1",
|
|
39
|
-
"metro-babel-transformer": "0.72.
|
|
40
|
-
"metro-cache": "0.72.
|
|
41
|
-
"metro-cache-key": "0.72.
|
|
42
|
-
"metro-config": "0.72.
|
|
43
|
-
"metro-core": "0.72.
|
|
44
|
-
"metro-file-map": "0.72.
|
|
45
|
-
"metro-hermes-compiler": "0.72.
|
|
46
|
-
"metro-inspector-proxy": "0.72.
|
|
47
|
-
"metro-minify-uglify": "0.72.
|
|
48
|
-
"metro-react-native-babel-preset": "0.72.
|
|
49
|
-
"metro-resolver": "0.72.
|
|
50
|
-
"metro-runtime": "0.72.
|
|
51
|
-
"metro-source-map": "0.72.
|
|
52
|
-
"metro-symbolicate": "0.72.
|
|
53
|
-
"metro-transform-plugins": "0.72.
|
|
54
|
-
"metro-transform-worker": "0.72.
|
|
40
|
+
"metro-babel-transformer": "0.72.4",
|
|
41
|
+
"metro-cache": "0.72.4",
|
|
42
|
+
"metro-cache-key": "0.72.4",
|
|
43
|
+
"metro-config": "0.72.4",
|
|
44
|
+
"metro-core": "0.72.4",
|
|
45
|
+
"metro-file-map": "0.72.4",
|
|
46
|
+
"metro-hermes-compiler": "0.72.4",
|
|
47
|
+
"metro-inspector-proxy": "0.72.4",
|
|
48
|
+
"metro-minify-uglify": "0.72.4",
|
|
49
|
+
"metro-react-native-babel-preset": "0.72.4",
|
|
50
|
+
"metro-resolver": "0.72.4",
|
|
51
|
+
"metro-runtime": "0.72.4",
|
|
52
|
+
"metro-source-map": "0.72.4",
|
|
53
|
+
"metro-symbolicate": "0.72.4",
|
|
54
|
+
"metro-transform-plugins": "0.72.4",
|
|
55
|
+
"metro-transform-worker": "0.72.4",
|
|
55
56
|
"mime-types": "^2.1.27",
|
|
56
57
|
"node-fetch": "^2.2.0",
|
|
57
58
|
"nullthrows": "^1.1.1",
|
|
@@ -70,10 +71,10 @@
|
|
|
70
71
|
"babel-jest": "^26.6.3",
|
|
71
72
|
"dedent": "^0.7.0",
|
|
72
73
|
"jest-snapshot": "^26.5.2",
|
|
73
|
-
"metro-babel-register": "0.72.
|
|
74
|
-
"metro-memory-fs": "0.72.
|
|
75
|
-
"metro-react-native-babel-preset": "0.72.
|
|
76
|
-
"metro-react-native-babel-transformer": "0.72.
|
|
74
|
+
"metro-babel-register": "0.72.4",
|
|
75
|
+
"metro-memory-fs": "0.72.4",
|
|
76
|
+
"metro-react-native-babel-preset": "0.72.4",
|
|
77
|
+
"metro-react-native-babel-transformer": "0.72.4",
|
|
77
78
|
"mock-req": "^0.2.0",
|
|
78
79
|
"mock-res": "^0.6.0",
|
|
79
80
|
"stack-trace": "^0.0.10"
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
const { isJsModule, wrapModule } = require("./helpers/js");
|
|
13
13
|
|
|
14
|
+
const jscSafeUrl = require("jsc-safe-url");
|
|
15
|
+
|
|
14
16
|
const { addParamsToDefineCall } = require("metro-transform-plugins");
|
|
15
17
|
|
|
16
18
|
const path = require("path");
|
|
@@ -37,7 +39,7 @@ function generateModules(sourceModules, graph, options) {
|
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
const sourceMappingURL = getURL("map");
|
|
40
|
-
const sourceURL = getURL("bundle");
|
|
42
|
+
const sourceURL = jscSafeUrl.toJscSafeUrl(getURL("bundle"));
|
|
41
43
|
const code =
|
|
42
44
|
prepareModule(module, graph, options) +
|
|
43
45
|
`\n//# sourceMappingURL=${sourceMappingURL}\n` +
|
|
@@ -15,6 +15,7 @@ import type {DeltaResult, Graph, Module} from '../types.flow';
|
|
|
15
15
|
import type {HmrModule} from 'metro-runtime/src/modules/types.flow';
|
|
16
16
|
|
|
17
17
|
const {isJsModule, wrapModule} = require('./helpers/js');
|
|
18
|
+
const jscSafeUrl = require('jsc-safe-url');
|
|
18
19
|
const {addParamsToDefineCall} = require('metro-transform-plugins');
|
|
19
20
|
const path = require('path');
|
|
20
21
|
const url = require('url');
|
|
@@ -50,7 +51,7 @@ function generateModules(
|
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
const sourceMappingURL = getURL('map');
|
|
53
|
-
const sourceURL = getURL('bundle');
|
|
54
|
+
const sourceURL = jscSafeUrl.toJscSafeUrl(getURL('bundle'));
|
|
54
55
|
const code =
|
|
55
56
|
prepareModule(module, graph, options) +
|
|
56
57
|
`\n//# sourceMappingURL=${sourceMappingURL}\n` +
|
|
@@ -286,8 +286,7 @@ async function processModule(path, graph, delta, options) {
|
|
|
286
286
|
invariant(
|
|
287
287
|
module.dependencies.size === currentDependencies.size,
|
|
288
288
|
"Failed to add the correct dependencies"
|
|
289
|
-
);
|
|
290
|
-
|
|
289
|
+
);
|
|
291
290
|
module.dependencies = currentDependencies;
|
|
292
291
|
return module;
|
|
293
292
|
}
|
|
@@ -728,10 +727,11 @@ function collectWhite(module, graph, delta) {
|
|
|
728
727
|
graph.privateState.gc.color.set(module.path, "black");
|
|
729
728
|
|
|
730
729
|
for (const dependency of module.dependencies.values()) {
|
|
731
|
-
const childModule =
|
|
732
|
-
|
|
733
|
-
)
|
|
734
|
-
|
|
730
|
+
const childModule = graph.dependencies.get(dependency.absolutePath); // The child may already have been collected.
|
|
731
|
+
|
|
732
|
+
if (childModule) {
|
|
733
|
+
collectWhite(childModule, graph, delta);
|
|
734
|
+
}
|
|
735
735
|
}
|
|
736
736
|
|
|
737
737
|
freeModule(module, graph, delta);
|
|
@@ -345,7 +345,6 @@ async function processModule<T>(
|
|
|
345
345
|
'Failed to add the correct dependencies',
|
|
346
346
|
);
|
|
347
347
|
|
|
348
|
-
// $FlowFixMe[cannot-write]
|
|
349
348
|
module.dependencies = currentDependencies;
|
|
350
349
|
|
|
351
350
|
return module;
|
|
@@ -812,10 +811,11 @@ function collectWhite<T>(module: Module<T>, graph: Graph<T>, delta: Delta) {
|
|
|
812
811
|
) {
|
|
813
812
|
graph.privateState.gc.color.set(module.path, 'black');
|
|
814
813
|
for (const dependency of module.dependencies.values()) {
|
|
815
|
-
const childModule =
|
|
816
|
-
|
|
817
|
-
)
|
|
818
|
-
|
|
814
|
+
const childModule = graph.dependencies.get(dependency.absolutePath);
|
|
815
|
+
// The child may already have been collected.
|
|
816
|
+
if (childModule) {
|
|
817
|
+
collectWhite(childModule, graph, delta);
|
|
818
|
+
}
|
|
819
819
|
}
|
|
820
820
|
freeModule(module, graph, delta);
|
|
821
821
|
}
|
|
@@ -54,7 +54,6 @@ module.exports = class HasteFS {
|
|
|
54
54
|
|
|
55
55
|
matches(directory, pattern) {
|
|
56
56
|
const entries = this.directoryEntries.get(directory); // $FlowFixMe[method-unbinding] added when improving typing for this parameters
|
|
57
|
-
// $FlowFixMe[incompatible-call]
|
|
58
57
|
|
|
59
58
|
return entries ? entries.filter(pattern.test, pattern) : [];
|
|
60
59
|
}
|
|
@@ -66,7 +66,6 @@ module.exports = class HasteFS {
|
|
|
66
66
|
const entries = this.directoryEntries.get(directory);
|
|
67
67
|
|
|
68
68
|
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
|
|
69
|
-
// $FlowFixMe[incompatible-call]
|
|
70
69
|
return entries ? entries.filter(pattern.test, pattern) : [];
|
|
71
70
|
}
|
|
72
71
|
};
|
|
@@ -25,8 +25,7 @@ function reverseDependencyMapReferences({ types: t }) {
|
|
|
25
25
|
|
|
26
26
|
if (node.callee.name === `${state.opts.globalPrefix}__d`) {
|
|
27
27
|
// $FlowFixMe Flow error uncovered by typing Babel more strictly
|
|
28
|
-
const lastArg = node.arguments[0].params.slice(-1)[0];
|
|
29
|
-
|
|
28
|
+
const lastArg = node.arguments[0].params.slice(-1)[0];
|
|
30
29
|
const depMapName = lastArg && lastArg.name;
|
|
31
30
|
|
|
32
31
|
if (depMapName == null) {
|
|
@@ -37,7 +37,6 @@ function reverseDependencyMapReferences({types: t}: {types: Types, ...}): {
|
|
|
37
37
|
if (node.callee.name === `${state.opts.globalPrefix}__d`) {
|
|
38
38
|
// $FlowFixMe Flow error uncovered by typing Babel more strictly
|
|
39
39
|
const lastArg = node.arguments[0].params.slice(-1)[0];
|
|
40
|
-
// $FlowFixMe Flow error uncovered by typing Babel more strictly
|
|
41
40
|
const depMapName: ?string = lastArg && lastArg.name;
|
|
42
41
|
|
|
43
42
|
if (depMapName == null) {
|
|
@@ -314,7 +314,6 @@ export type ResolvedLibrary = {
|
|
|
314
314
|
+files: $ReadOnlyArray<$DeepReadOnly<ResolvedCodeFile>>,
|
|
315
315
|
/* cannot be a Map because it's JSONified later on */
|
|
316
316
|
+assets: AssetContentsByPath,
|
|
317
|
-
+isPartiallyResolved?: boolean,
|
|
318
317
|
};
|
|
319
318
|
|
|
320
319
|
type DeepReadOnlyFn = (<T>(Array<T>) => $ReadOnlyArray<$DeepReadOnly<T>>) &
|
|
@@ -4,6 +4,7 @@
|
|
|
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
|
+
*
|
|
7
8
|
* @format
|
|
8
9
|
*/
|
|
9
10
|
"use strict";
|
|
@@ -14,17 +15,20 @@ const CRLF = "\r\n";
|
|
|
14
15
|
const BOUNDARY = "3beqjf3apnqeu3h5jqorms4i";
|
|
15
16
|
|
|
16
17
|
class MultipartResponse {
|
|
17
|
-
static
|
|
18
|
+
static wrapIfSupported(req, res) {
|
|
18
19
|
if (accepts(req).types().includes("multipart/mixed")) {
|
|
19
20
|
return new MultipartResponse(res);
|
|
20
|
-
}
|
|
21
|
-
// object with the same interface
|
|
22
|
-
|
|
23
|
-
res.writeChunk = () => {}; // noop
|
|
21
|
+
}
|
|
24
22
|
|
|
25
23
|
return res;
|
|
26
24
|
}
|
|
27
25
|
|
|
26
|
+
static serializeHeaders(headers) {
|
|
27
|
+
return Object.keys(headers)
|
|
28
|
+
.map((key) => `${key}: ${headers[key]}`)
|
|
29
|
+
.join(CRLF);
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
constructor(res) {
|
|
29
33
|
this.res = res;
|
|
30
34
|
this.headers = {};
|
|
@@ -47,7 +51,7 @@ class MultipartResponse {
|
|
|
47
51
|
this.res.write(MultipartResponse.serializeHeaders(headers) + CRLF + CRLF);
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
if (data) {
|
|
54
|
+
if (data != null) {
|
|
51
55
|
this.res.write(data);
|
|
52
56
|
}
|
|
53
57
|
|
|
@@ -78,12 +82,6 @@ class MultipartResponse {
|
|
|
78
82
|
this.writeChunk(this.headers, data, true);
|
|
79
83
|
this.res.end();
|
|
80
84
|
}
|
|
81
|
-
|
|
82
|
-
static serializeHeaders(headers) {
|
|
83
|
-
return Object.keys(headers)
|
|
84
|
-
.map((key) => `${key}: ${headers[key]}`)
|
|
85
|
-
.join(CRLF);
|
|
86
|
-
}
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
module.exports = MultipartResponse;
|
|
@@ -0,0 +1,97 @@
|
|
|
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
|
+
* @flow strict
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
import type {IncomingMessage, ServerResponse} from 'http';
|
|
13
|
+
const accepts = require('accepts');
|
|
14
|
+
|
|
15
|
+
const CRLF = '\r\n';
|
|
16
|
+
const BOUNDARY = '3beqjf3apnqeu3h5jqorms4i';
|
|
17
|
+
type Data = string | Buffer | Uint8Array;
|
|
18
|
+
type Headers = {[string]: string | number};
|
|
19
|
+
|
|
20
|
+
class MultipartResponse {
|
|
21
|
+
static wrapIfSupported(
|
|
22
|
+
req: IncomingMessage,
|
|
23
|
+
res: ServerResponse,
|
|
24
|
+
): MultipartResponse | ServerResponse {
|
|
25
|
+
if (accepts(req).types().includes('multipart/mixed')) {
|
|
26
|
+
return new MultipartResponse(res);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return res;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static serializeHeaders(headers: Headers): string {
|
|
33
|
+
return Object.keys(headers)
|
|
34
|
+
.map(key => `${key}: ${headers[key]}`)
|
|
35
|
+
.join(CRLF);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
res: ServerResponse;
|
|
39
|
+
headers: Headers;
|
|
40
|
+
|
|
41
|
+
constructor(res: ServerResponse) {
|
|
42
|
+
this.res = res;
|
|
43
|
+
this.headers = {};
|
|
44
|
+
res.writeHead(200, {
|
|
45
|
+
'Content-Type': `multipart/mixed; boundary="${BOUNDARY}"`,
|
|
46
|
+
});
|
|
47
|
+
res.write(
|
|
48
|
+
'If you are seeing this, your client does not support multipart response',
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
writeChunk(
|
|
53
|
+
headers: Headers | null,
|
|
54
|
+
data?: Data,
|
|
55
|
+
isLast?: boolean = false,
|
|
56
|
+
): void {
|
|
57
|
+
if (this.res.finished) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.res.write(`${CRLF}--${BOUNDARY}${CRLF}`);
|
|
62
|
+
if (headers) {
|
|
63
|
+
this.res.write(MultipartResponse.serializeHeaders(headers) + CRLF + CRLF);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (data != null) {
|
|
67
|
+
this.res.write(data);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (isLast) {
|
|
71
|
+
this.res.write(`${CRLF}--${BOUNDARY}--${CRLF}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
writeHead(status: number, headers?: Headers): void {
|
|
76
|
+
// We can't actually change the response HTTP status code
|
|
77
|
+
// because the headers have already been sent
|
|
78
|
+
this.setHeader('X-Http-Status', status);
|
|
79
|
+
if (!headers) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
for (const key in headers) {
|
|
83
|
+
this.setHeader(key, headers[key]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
setHeader(name: string, value: string | number): void {
|
|
88
|
+
this.headers[name] = value;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
end(data?: Data): void {
|
|
92
|
+
this.writeChunk(this.headers, data, true);
|
|
93
|
+
this.res.end();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = MultipartResponse;
|
package/src/Server.js
CHANGED
|
@@ -47,16 +47,20 @@ const transformHelpers = require("./lib/transformHelpers");
|
|
|
47
47
|
|
|
48
48
|
const parsePlatformFilePath = require("./node-haste/lib/parsePlatformFilePath");
|
|
49
49
|
|
|
50
|
-
const MultipartResponse = require("./Server/MultipartResponse");
|
|
51
|
-
|
|
52
50
|
const symbolicate = require("./Server/symbolicate");
|
|
53
51
|
|
|
54
52
|
const { codeFrameColumns } = require("@babel/code-frame");
|
|
55
53
|
|
|
54
|
+
const MultipartResponse = require("./Server/MultipartResponse");
|
|
55
|
+
|
|
56
56
|
const debug = require("debug")("Metro:Server");
|
|
57
57
|
|
|
58
58
|
const fs = require("graceful-fs");
|
|
59
59
|
|
|
60
|
+
const invariant = require("invariant");
|
|
61
|
+
|
|
62
|
+
const jscSafeUrl = require("jsc-safe-url");
|
|
63
|
+
|
|
60
64
|
const {
|
|
61
65
|
Logger,
|
|
62
66
|
Logger: { createActionStartEntry, createActionEndEntry, log },
|
|
@@ -414,9 +418,15 @@ class Server {
|
|
|
414
418
|
);
|
|
415
419
|
}
|
|
416
420
|
|
|
421
|
+
_rewriteAndNormalizeUrl(requestUrl) {
|
|
422
|
+
return jscSafeUrl.toNormalUrl(
|
|
423
|
+
this._config.server.rewriteRequestUrl(jscSafeUrl.toNormalUrl(requestUrl))
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
|
|
417
427
|
async _processRequest(req, res, next) {
|
|
418
428
|
const originalUrl = req.url;
|
|
419
|
-
req.url = this.
|
|
429
|
+
req.url = this._rewriteAndNormalizeUrl(req.url);
|
|
420
430
|
const urlObj = url.parse(req.url, true);
|
|
421
431
|
const { host } = req.headers;
|
|
422
432
|
debug(
|
|
@@ -516,7 +526,7 @@ class Server {
|
|
|
516
526
|
return;
|
|
517
527
|
}
|
|
518
528
|
|
|
519
|
-
const mres = MultipartResponse.
|
|
529
|
+
const mres = MultipartResponse.wrapIfSupported(req, res);
|
|
520
530
|
const buildID = this.getNewBuildID();
|
|
521
531
|
let onProgress = null;
|
|
522
532
|
let lastProgress = -1;
|
|
@@ -532,15 +542,17 @@ class Server {
|
|
|
532
542
|
// actually different and that have increased from the last one we sent.
|
|
533
543
|
|
|
534
544
|
if (currentProgress > lastProgress || totalFileCount < 10) {
|
|
535
|
-
mres
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
545
|
+
if (mres instanceof MultipartResponse) {
|
|
546
|
+
mres.writeChunk(
|
|
547
|
+
{
|
|
548
|
+
"Content-Type": "application/json",
|
|
549
|
+
},
|
|
550
|
+
JSON.stringify({
|
|
551
|
+
done: transformedFileCount,
|
|
552
|
+
total: totalFileCount,
|
|
553
|
+
})
|
|
554
|
+
);
|
|
555
|
+
} // The `uncork` called internally in Node via `promise.nextTick()` may not fire
|
|
544
556
|
// until all of the Promises are resolved because the microtask queue we're
|
|
545
557
|
// in could be starving the event loop. This can cause a bug where the progress
|
|
546
558
|
// is not actually sent in the response until after bundling is complete. This
|
|
@@ -691,8 +703,6 @@ class Server {
|
|
|
691
703
|
|
|
692
704
|
const serializer =
|
|
693
705
|
this._config.serializer.customSerializer ||
|
|
694
|
-
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by
|
|
695
|
-
* Flow's LTI update could not be added via codemod */
|
|
696
706
|
((...args) => bundleToString(baseJSBundle(...args)).code);
|
|
697
707
|
|
|
698
708
|
const bundle = await serializer(
|
|
@@ -741,7 +751,7 @@ class Server {
|
|
|
741
751
|
};
|
|
742
752
|
},
|
|
743
753
|
|
|
744
|
-
finish({ req, mres, result }) {
|
|
754
|
+
finish({ req, mres, serializerOptions, result }) {
|
|
745
755
|
if (
|
|
746
756
|
// We avoid parsing the dates since the client should never send a more
|
|
747
757
|
// recent date than the one returned by the Delta Bundler (if that's the
|
|
@@ -758,6 +768,15 @@ class Server {
|
|
|
758
768
|
String(result.numModifiedFiles)
|
|
759
769
|
);
|
|
760
770
|
mres.setHeader(DELTA_ID_HEADER, String(result.nextRevId));
|
|
771
|
+
|
|
772
|
+
if (
|
|
773
|
+
(serializerOptions === null || serializerOptions === void 0
|
|
774
|
+
? void 0
|
|
775
|
+
: serializerOptions.sourceUrl) != null
|
|
776
|
+
) {
|
|
777
|
+
mres.setHeader("Content-Location", serializerOptions.sourceUrl);
|
|
778
|
+
}
|
|
779
|
+
|
|
761
780
|
mres.setHeader("Content-Type", "application/javascript; charset=UTF-8");
|
|
762
781
|
mres.setHeader("Last-Modified", result.lastModifiedDate.toUTCString());
|
|
763
782
|
mres.setHeader(
|
|
@@ -1060,19 +1079,29 @@ class Server {
|
|
|
1060
1079
|
/* $FlowFixMe: where is `rawBody` defined? Is it added by the `connect` framework? */
|
|
1061
1080
|
|
|
1062
1081
|
const body = await req.rawBody;
|
|
1063
|
-
const
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1082
|
+
const parsedBody = JSON.parse(body);
|
|
1083
|
+
|
|
1084
|
+
const rewriteAndNormalizeStackFrame = (frame, lineNumber) => {
|
|
1085
|
+
invariant(
|
|
1086
|
+
frame != null && typeof frame === "object",
|
|
1087
|
+
"Bad stack frame at line %d, expected object, received: %s",
|
|
1088
|
+
lineNumber,
|
|
1089
|
+
typeof frame
|
|
1090
|
+
);
|
|
1091
|
+
const frameFile = frame.file;
|
|
1092
|
+
|
|
1093
|
+
if (typeof frameFile === "string" && frameFile.includes("://")) {
|
|
1094
|
+
return { ...frame, file: this._rewriteAndNormalizeUrl(frameFile) };
|
|
1069
1095
|
}
|
|
1070
1096
|
|
|
1071
1097
|
return frame;
|
|
1072
|
-
}
|
|
1098
|
+
};
|
|
1099
|
+
|
|
1100
|
+
const stack = parsedBody.stack.map(rewriteAndNormalizeStackFrame); // In case of multiple bundles / HMR, some stack frames can have different URLs from others
|
|
1073
1101
|
|
|
1074
1102
|
const urls = new Set();
|
|
1075
1103
|
stack.forEach((frame) => {
|
|
1104
|
+
// These urls have been rewritten and normalized above.
|
|
1076
1105
|
const sourceUrl = frame.file; // Skip `/debuggerWorker.js` which does not need symbolication.
|
|
1077
1106
|
|
|
1078
1107
|
if (
|
|
@@ -1086,8 +1115,11 @@ class Server {
|
|
|
1086
1115
|
});
|
|
1087
1116
|
debug("Getting source maps for symbolication");
|
|
1088
1117
|
const sourceMaps = await Promise.all(
|
|
1089
|
-
|
|
1090
|
-
|
|
1118
|
+
Array.from(urls.values()).map((normalizedUrl) =>
|
|
1119
|
+
this._explodedSourceMapForBundleOptions(
|
|
1120
|
+
this._parseOptions(normalizedUrl)
|
|
1121
|
+
)
|
|
1122
|
+
)
|
|
1091
1123
|
);
|
|
1092
1124
|
debug("Performing fast symbolication");
|
|
1093
1125
|
const symbolicatedStack = await await symbolicate(
|
|
@@ -1116,12 +1148,7 @@ class Server {
|
|
|
1116
1148
|
}
|
|
1117
1149
|
}
|
|
1118
1150
|
|
|
1119
|
-
async
|
|
1120
|
-
const options = parseOptionsFromUrl(
|
|
1121
|
-
reqUrl,
|
|
1122
|
-
new Set(this._config.resolver.platforms),
|
|
1123
|
-
getBytecodeVersion()
|
|
1124
|
-
);
|
|
1151
|
+
async _explodedSourceMapForBundleOptions(bundleOptions) {
|
|
1125
1152
|
const {
|
|
1126
1153
|
entryFile,
|
|
1127
1154
|
graphOptions,
|
|
@@ -1129,7 +1156,7 @@ class Server {
|
|
|
1129
1156
|
resolverOptions,
|
|
1130
1157
|
serializerOptions,
|
|
1131
1158
|
transformOptions,
|
|
1132
|
-
} = splitBundleOptions(
|
|
1159
|
+
} = splitBundleOptions(bundleOptions);
|
|
1133
1160
|
/**
|
|
1134
1161
|
* `entryFile` is relative to projectRoot, we need to use resolution function
|
|
1135
1162
|
* to find the appropriate file with supported extensions.
|
package/src/Server.js.flow
CHANGED
|
@@ -60,11 +60,13 @@ const parseOptionsFromUrl = require('./lib/parseOptionsFromUrl');
|
|
|
60
60
|
const splitBundleOptions = require('./lib/splitBundleOptions');
|
|
61
61
|
const transformHelpers = require('./lib/transformHelpers');
|
|
62
62
|
const parsePlatformFilePath = require('./node-haste/lib/parsePlatformFilePath');
|
|
63
|
-
const MultipartResponse = require('./Server/MultipartResponse');
|
|
64
63
|
const symbolicate = require('./Server/symbolicate');
|
|
65
64
|
const {codeFrameColumns} = require('@babel/code-frame');
|
|
65
|
+
const MultipartResponse = require('./Server/MultipartResponse');
|
|
66
66
|
const debug = require('debug')('Metro:Server');
|
|
67
67
|
const fs = require('graceful-fs');
|
|
68
|
+
const invariant = require('invariant');
|
|
69
|
+
const jscSafeUrl = require('jsc-safe-url');
|
|
68
70
|
const {
|
|
69
71
|
Logger,
|
|
70
72
|
Logger: {createActionStartEntry, createActionEndEntry, log},
|
|
@@ -91,8 +93,7 @@ type ProcessStartContext = {
|
|
|
91
93
|
+bundleOptions: BundleOptions,
|
|
92
94
|
+graphId: GraphId,
|
|
93
95
|
+graphOptions: GraphOptions,
|
|
94
|
-
|
|
95
|
-
+mres: MultipartResponse,
|
|
96
|
+
+mres: MultipartResponse | ServerResponse,
|
|
96
97
|
+req: IncomingMessage,
|
|
97
98
|
+revisionId?: ?RevisionId,
|
|
98
99
|
...SplitBundleOptions,
|
|
@@ -475,14 +476,19 @@ class Server {
|
|
|
475
476
|
);
|
|
476
477
|
}
|
|
477
478
|
|
|
479
|
+
_rewriteAndNormalizeUrl(requestUrl: string): string {
|
|
480
|
+
return jscSafeUrl.toNormalUrl(
|
|
481
|
+
this._config.server.rewriteRequestUrl(jscSafeUrl.toNormalUrl(requestUrl)),
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
|
|
478
485
|
async _processRequest(
|
|
479
486
|
req: IncomingMessage,
|
|
480
487
|
res: ServerResponse,
|
|
481
488
|
next: (?Error) => mixed,
|
|
482
489
|
) {
|
|
483
490
|
const originalUrl = req.url;
|
|
484
|
-
req.url = this.
|
|
485
|
-
|
|
491
|
+
req.url = this._rewriteAndNormalizeUrl(req.url);
|
|
486
492
|
const urlObj = url.parse(req.url, true);
|
|
487
493
|
const {host} = req.headers;
|
|
488
494
|
debug(
|
|
@@ -601,7 +607,7 @@ class Server {
|
|
|
601
607
|
return;
|
|
602
608
|
}
|
|
603
609
|
|
|
604
|
-
const mres = MultipartResponse.
|
|
610
|
+
const mres = MultipartResponse.wrapIfSupported(req, res);
|
|
605
611
|
const buildID = this.getNewBuildID();
|
|
606
612
|
|
|
607
613
|
let onProgress = null;
|
|
@@ -618,13 +624,15 @@ class Server {
|
|
|
618
624
|
// that, we check the percentage, and only send percentages that are
|
|
619
625
|
// actually different and that have increased from the last one we sent.
|
|
620
626
|
if (currentProgress > lastProgress || totalFileCount < 10) {
|
|
621
|
-
mres
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
627
|
+
if (mres instanceof MultipartResponse) {
|
|
628
|
+
mres.writeChunk(
|
|
629
|
+
{'Content-Type': 'application/json'},
|
|
630
|
+
JSON.stringify({
|
|
631
|
+
done: transformedFileCount,
|
|
632
|
+
total: totalFileCount,
|
|
633
|
+
}),
|
|
634
|
+
);
|
|
635
|
+
}
|
|
628
636
|
|
|
629
637
|
// The `uncork` called internally in Node via `promise.nextTick()` may not fire
|
|
630
638
|
// until all of the Promises are resolved because the microtask queue we're
|
|
@@ -789,8 +797,6 @@ class Server {
|
|
|
789
797
|
|
|
790
798
|
const serializer =
|
|
791
799
|
this._config.serializer.customSerializer ||
|
|
792
|
-
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by
|
|
793
|
-
* Flow's LTI update could not be added via codemod */
|
|
794
800
|
((...args) => bundleToString(baseJSBundle(...args)).code);
|
|
795
801
|
|
|
796
802
|
const bundle = await serializer(
|
|
@@ -836,7 +842,7 @@ class Server {
|
|
|
836
842
|
bundle: bundleCode,
|
|
837
843
|
};
|
|
838
844
|
},
|
|
839
|
-
finish({req, mres, result}) {
|
|
845
|
+
finish({req, mres, serializerOptions, result}) {
|
|
840
846
|
if (
|
|
841
847
|
// We avoid parsing the dates since the client should never send a more
|
|
842
848
|
// recent date than the one returned by the Delta Bundler (if that's the
|
|
@@ -853,6 +859,9 @@ class Server {
|
|
|
853
859
|
String(result.numModifiedFiles),
|
|
854
860
|
);
|
|
855
861
|
mres.setHeader(DELTA_ID_HEADER, String(result.nextRevId));
|
|
862
|
+
if (serializerOptions?.sourceUrl != null) {
|
|
863
|
+
mres.setHeader('Content-Location', serializerOptions.sourceUrl);
|
|
864
|
+
}
|
|
856
865
|
mres.setHeader('Content-Type', 'application/javascript; charset=UTF-8');
|
|
857
866
|
mres.setHeader('Last-Modified', result.lastModifiedDate.toUTCString());
|
|
858
867
|
mres.setHeader(
|
|
@@ -1146,19 +1155,34 @@ class Server {
|
|
|
1146
1155
|
debug('Start symbolication');
|
|
1147
1156
|
/* $FlowFixMe: where is `rawBody` defined? Is it added by the `connect` framework? */
|
|
1148
1157
|
const body = await req.rawBody;
|
|
1149
|
-
const
|
|
1150
|
-
|
|
1158
|
+
const parsedBody = JSON.parse(body);
|
|
1159
|
+
|
|
1160
|
+
const rewriteAndNormalizeStackFrame = <T>(
|
|
1161
|
+
frame: T,
|
|
1162
|
+
lineNumber: number,
|
|
1163
|
+
): T => {
|
|
1164
|
+
invariant(
|
|
1165
|
+
frame != null && typeof frame === 'object',
|
|
1166
|
+
'Bad stack frame at line %d, expected object, received: %s',
|
|
1167
|
+
lineNumber,
|
|
1168
|
+
typeof frame,
|
|
1169
|
+
);
|
|
1170
|
+
const frameFile = frame.file;
|
|
1171
|
+
if (typeof frameFile === 'string' && frameFile.includes('://')) {
|
|
1151
1172
|
return {
|
|
1152
1173
|
...frame,
|
|
1153
|
-
file: this.
|
|
1174
|
+
file: this._rewriteAndNormalizeUrl(frameFile),
|
|
1154
1175
|
};
|
|
1155
1176
|
}
|
|
1156
1177
|
return frame;
|
|
1157
|
-
}
|
|
1178
|
+
};
|
|
1179
|
+
|
|
1180
|
+
const stack = parsedBody.stack.map(rewriteAndNormalizeStackFrame);
|
|
1158
1181
|
// In case of multiple bundles / HMR, some stack frames can have different URLs from others
|
|
1159
1182
|
const urls = new Set();
|
|
1160
1183
|
|
|
1161
1184
|
stack.forEach(frame => {
|
|
1185
|
+
// These urls have been rewritten and normalized above.
|
|
1162
1186
|
const sourceUrl = frame.file;
|
|
1163
1187
|
// Skip `/debuggerWorker.js` which does not need symbolication.
|
|
1164
1188
|
if (
|
|
@@ -1173,8 +1197,11 @@ class Server {
|
|
|
1173
1197
|
|
|
1174
1198
|
debug('Getting source maps for symbolication');
|
|
1175
1199
|
const sourceMaps = await Promise.all(
|
|
1176
|
-
|
|
1177
|
-
|
|
1200
|
+
Array.from(urls.values()).map(normalizedUrl =>
|
|
1201
|
+
this._explodedSourceMapForBundleOptions(
|
|
1202
|
+
this._parseOptions(normalizedUrl),
|
|
1203
|
+
),
|
|
1204
|
+
),
|
|
1178
1205
|
);
|
|
1179
1206
|
|
|
1180
1207
|
debug('Performing fast symbolication');
|
|
@@ -1201,13 +1228,9 @@ class Server {
|
|
|
1201
1228
|
}
|
|
1202
1229
|
}
|
|
1203
1230
|
|
|
1204
|
-
async
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
new Set(this._config.resolver.platforms),
|
|
1208
|
-
getBytecodeVersion(),
|
|
1209
|
-
);
|
|
1210
|
-
|
|
1231
|
+
async _explodedSourceMapForBundleOptions(
|
|
1232
|
+
bundleOptions: BundleOptions,
|
|
1233
|
+
): Promise<ExplodedSourceMap> {
|
|
1211
1234
|
const {
|
|
1212
1235
|
entryFile,
|
|
1213
1236
|
graphOptions,
|
|
@@ -1215,7 +1238,7 @@ class Server {
|
|
|
1215
1238
|
resolverOptions,
|
|
1216
1239
|
serializerOptions,
|
|
1217
1240
|
transformOptions,
|
|
1218
|
-
} = splitBundleOptions(
|
|
1241
|
+
} = splitBundleOptions(bundleOptions);
|
|
1219
1242
|
|
|
1220
1243
|
/**
|
|
1221
1244
|
* `entryFile` is relative to projectRoot, we need to use resolution function
|
package/src/index.js
CHANGED
package/src/index.js.flow
CHANGED
package/src/lib/CountingSet.js
CHANGED
|
@@ -144,28 +144,21 @@ class TerminalReporter {
|
|
|
144
144
|
|
|
145
145
|
_logInitializing(port, hasReducedPerformance) {
|
|
146
146
|
const logo = [
|
|
147
|
-
"
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
"
|
|
156
|
-
"
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
"
|
|
160
|
-
"
|
|
161
|
-
"
|
|
162
|
-
" ###### ############# ####### ",
|
|
163
|
-
" ######### #### ######### ",
|
|
164
|
-
" ######### ######### ",
|
|
165
|
-
" ######### ######### ",
|
|
166
|
-
" ######### ",
|
|
167
|
-
" ",
|
|
168
|
-
" ",
|
|
147
|
+
"",
|
|
148
|
+
" ▒▒▓▓▓▓▒▒",
|
|
149
|
+
" ▒▓▓▓▒▒░░▒▒▓▓▓▒",
|
|
150
|
+
" ▒▓▓▓▓░░░▒▒▒▒░░░▓▓▓▓▒",
|
|
151
|
+
" ▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓",
|
|
152
|
+
" ▓▓░░░░░▒▓▓▓▓▓▓▒░░░░░▓▓",
|
|
153
|
+
" ▓▓░░▓▓▒░░░▒▒░░░▒▓▒░░▓▓",
|
|
154
|
+
" ▓▓░░▓▓▓▓▓▒▒▒▒▓▓▓▓▒░░▓▓",
|
|
155
|
+
" ▓▓░░▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░▓▓",
|
|
156
|
+
" ▓▓▒░░▒▒▓▓▓▓▓▓▓▓▒░░░▒▓▓",
|
|
157
|
+
" ▒▓▓▓▒░░░▒▓▓▒░░░▒▓▓▓▒",
|
|
158
|
+
" ▒▓▓▓▒░░░░▒▓▓▓▒",
|
|
159
|
+
" ▒▒▓▓▓▓▒▒",
|
|
160
|
+
"",
|
|
161
|
+
"",
|
|
169
162
|
];
|
|
170
163
|
const color = hasReducedPerformance ? chalk.red : chalk.blue;
|
|
171
164
|
this.terminal.log(color(logo.join("\n")));
|
|
@@ -258,9 +251,14 @@ class TerminalReporter {
|
|
|
258
251
|
|
|
259
252
|
case "dep_graph_loading":
|
|
260
253
|
const color = event.hasReducedPerformance ? chalk.red : chalk.blue;
|
|
254
|
+
|
|
255
|
+
const version = "v" + require("../../package.json").version;
|
|
256
|
+
|
|
261
257
|
this.terminal.log(
|
|
262
|
-
color.bold(
|
|
263
|
-
|
|
258
|
+
color.bold(
|
|
259
|
+
" ".repeat(19 - version.length / 2),
|
|
260
|
+
"Welcome to Metro " + chalk.white(version) + "\n"
|
|
261
|
+
) + chalk.dim(" Fast - Scalable - Integrated\n\n")
|
|
264
262
|
);
|
|
265
263
|
|
|
266
264
|
if (event.hasReducedPerformance) {
|
|
@@ -182,28 +182,21 @@ class TerminalReporter {
|
|
|
182
182
|
|
|
183
183
|
_logInitializing(port: number, hasReducedPerformance: boolean): void {
|
|
184
184
|
const logo = [
|
|
185
|
-
'
|
|
186
|
-
'
|
|
187
|
-
'
|
|
188
|
-
'
|
|
189
|
-
'
|
|
190
|
-
'
|
|
191
|
-
'
|
|
192
|
-
'
|
|
193
|
-
'
|
|
194
|
-
'
|
|
195
|
-
'
|
|
196
|
-
'
|
|
197
|
-
'
|
|
198
|
-
'
|
|
199
|
-
'
|
|
200
|
-
' ###### ############# ####### ',
|
|
201
|
-
' ######### #### ######### ',
|
|
202
|
-
' ######### ######### ',
|
|
203
|
-
' ######### ######### ',
|
|
204
|
-
' ######### ',
|
|
205
|
-
' ',
|
|
206
|
-
' ',
|
|
185
|
+
'',
|
|
186
|
+
' ▒▒▓▓▓▓▒▒',
|
|
187
|
+
' ▒▓▓▓▒▒░░▒▒▓▓▓▒',
|
|
188
|
+
' ▒▓▓▓▓░░░▒▒▒▒░░░▓▓▓▓▒',
|
|
189
|
+
' ▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓',
|
|
190
|
+
' ▓▓░░░░░▒▓▓▓▓▓▓▒░░░░░▓▓',
|
|
191
|
+
' ▓▓░░▓▓▒░░░▒▒░░░▒▓▒░░▓▓',
|
|
192
|
+
' ▓▓░░▓▓▓▓▓▒▒▒▒▓▓▓▓▒░░▓▓',
|
|
193
|
+
' ▓▓░░▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░▓▓',
|
|
194
|
+
' ▓▓▒░░▒▒▓▓▓▓▓▓▓▓▒░░░▒▓▓',
|
|
195
|
+
' ▒▓▓▓▒░░░▒▓▓▒░░░▒▓▓▓▒',
|
|
196
|
+
' ▒▓▓▓▒░░░░▒▓▓▓▒',
|
|
197
|
+
' ▒▒▓▓▓▓▒▒',
|
|
198
|
+
'',
|
|
199
|
+
'',
|
|
207
200
|
];
|
|
208
201
|
|
|
209
202
|
const color = hasReducedPerformance ? chalk.red : chalk.blue;
|
|
@@ -275,9 +268,12 @@ class TerminalReporter {
|
|
|
275
268
|
break;
|
|
276
269
|
case 'dep_graph_loading':
|
|
277
270
|
const color = event.hasReducedPerformance ? chalk.red : chalk.blue;
|
|
271
|
+
const version = 'v' + require('../../package.json').version;
|
|
278
272
|
this.terminal.log(
|
|
279
|
-
color.bold(
|
|
280
|
-
|
|
273
|
+
color.bold(
|
|
274
|
+
' '.repeat(19 - version.length / 2),
|
|
275
|
+
'Welcome to Metro ' + chalk.white(version) + '\n',
|
|
276
|
+
) + chalk.dim(' Fast - Scalable - Integrated\n\n'),
|
|
281
277
|
);
|
|
282
278
|
|
|
283
279
|
if (event.hasReducedPerformance) {
|
|
@@ -15,6 +15,8 @@ const parseCustomResolverOptions = require("./parseCustomResolverOptions");
|
|
|
15
15
|
|
|
16
16
|
const parseCustomTransformOptions = require("./parseCustomTransformOptions");
|
|
17
17
|
|
|
18
|
+
const jscSafeUrl = require("jsc-safe-url");
|
|
19
|
+
|
|
18
20
|
const nullthrows = require("nullthrows");
|
|
19
21
|
|
|
20
22
|
const path = require("path");
|
|
@@ -40,11 +42,11 @@ const getTransformProfile = (transformProfile) =>
|
|
|
40
42
|
: "default";
|
|
41
43
|
|
|
42
44
|
module.exports = function parseOptionsFromUrl(
|
|
43
|
-
|
|
45
|
+
normalizedRequestUrl,
|
|
44
46
|
platforms,
|
|
45
47
|
bytecodeVersion
|
|
46
48
|
) {
|
|
47
|
-
const parsedURL = nullthrows(url.parse(
|
|
49
|
+
const parsedURL = nullthrows(url.parse(normalizedRequestUrl, true)); // `true` to parse the query param as an object.
|
|
48
50
|
|
|
49
51
|
const query = nullthrows(parsedURL.query);
|
|
50
52
|
const pathname =
|
|
@@ -85,7 +87,7 @@ module.exports = function parseOptionsFromUrl(
|
|
|
85
87
|
platform != null && platform.match(/^(android|ios)$/) ? "http" : "",
|
|
86
88
|
pathname: pathname.replace(/\.(bundle|delta)$/, ".map"),
|
|
87
89
|
}),
|
|
88
|
-
sourceUrl:
|
|
90
|
+
sourceUrl: jscSafeUrl.toJscSafeUrl(normalizedRequestUrl),
|
|
89
91
|
unstable_transformProfile: getTransformProfile(
|
|
90
92
|
query.unstable_transformProfile
|
|
91
93
|
),
|
|
@@ -16,6 +16,7 @@ import type {TransformProfile} from 'metro-babel-transformer';
|
|
|
16
16
|
const parsePlatformFilePath = require('../node-haste/lib/parsePlatformFilePath');
|
|
17
17
|
const parseCustomResolverOptions = require('./parseCustomResolverOptions');
|
|
18
18
|
const parseCustomTransformOptions = require('./parseCustomTransformOptions');
|
|
19
|
+
const jscSafeUrl = require('jsc-safe-url');
|
|
19
20
|
const nullthrows = require('nullthrows');
|
|
20
21
|
const path = require('path');
|
|
21
22
|
const url = require('url');
|
|
@@ -47,11 +48,11 @@ const getTransformProfile = (transformProfile: string): TransformProfile =>
|
|
|
47
48
|
: 'default';
|
|
48
49
|
|
|
49
50
|
module.exports = function parseOptionsFromUrl(
|
|
50
|
-
|
|
51
|
+
normalizedRequestUrl: string,
|
|
51
52
|
platforms: Set<string>,
|
|
52
53
|
bytecodeVersion: number,
|
|
53
54
|
): BundleOptions {
|
|
54
|
-
const parsedURL = nullthrows(url.parse(
|
|
55
|
+
const parsedURL = nullthrows(url.parse(normalizedRequestUrl, true)); // `true` to parse the query param as an object.
|
|
55
56
|
const query = nullthrows(parsedURL.query);
|
|
56
57
|
const pathname =
|
|
57
58
|
query.bundleEntry ||
|
|
@@ -92,7 +93,7 @@ module.exports = function parseOptionsFromUrl(
|
|
|
92
93
|
platform != null && platform.match(/^(android|ios)$/) ? 'http' : '',
|
|
93
94
|
pathname: pathname.replace(/\.(bundle|delta)$/, '.map'),
|
|
94
95
|
}),
|
|
95
|
-
sourceUrl:
|
|
96
|
+
sourceUrl: jscSafeUrl.toJscSafeUrl(normalizedRequestUrl),
|
|
96
97
|
unstable_transformProfile: getTransformProfile(
|
|
97
98
|
query.unstable_transformProfile,
|
|
98
99
|
),
|