metro 0.82.1 → 0.82.3
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 +17 -16
- package/src/Bundler.js.flow +1 -1
- package/src/DeltaBundler/Serializers/getRamBundleInfo.js.flow +1 -1
- package/src/DeltaBundler/Transformer.js.flow +1 -1
- package/src/DeltaBundler/Worker.flow.js +3 -0
- package/src/DeltaBundler/Worker.flow.js.flow +3 -0
- package/src/DeltaBundler/WorkerFarm.js +1 -0
- package/src/DeltaBundler/WorkerFarm.js.flow +8 -1
- package/src/DeltaBundler/types.flow.js.flow +2 -6
- package/src/HmrServer.js +1 -1
- package/src/HmrServer.js.flow +1 -1
- package/src/IncrementalBundler.js.flow +1 -1
- package/src/ModuleGraph/worker/collectDependencies.js +4 -0
- package/src/ModuleGraph/worker/collectDependencies.js.flow +6 -0
- package/src/ModuleGraph/worker/importLocationsPlugin.js +14 -19
- package/src/ModuleGraph/worker/importLocationsPlugin.js.flow +30 -24
- package/src/Server/symbolicate.js.flow +1 -1
- package/src/Server.js +22 -6
- package/src/Server.js.flow +37 -11
- package/src/index.flow.js +13 -1
- package/src/index.flow.js.flow +28 -7
- package/src/lib/JsonReporter.js.flow +1 -0
- package/src/lib/TerminalReporter.js.flow +1 -0
- package/src/lib/formatBundlingError.js +11 -8
- package/src/lib/formatBundlingError.js.flow +12 -9
- package/src/lib/parseJsonBody.js +35 -0
- package/src/lib/parseJsonBody.js.flow +60 -0
- package/src/lib/parseOptionsFromUrl.js.flow +5 -1
- package/src/lib/transformHelpers.js.flow +1 -1
- package/src/node-haste/DependencyGraph/createFileMap.js.flow +1 -1
- package/src/node-haste/DependencyGraph.js.flow +1 -1
- package/src/shared/output/RamBundle.js +0 -1
- package/src/shared/output/RamBundle.js.flow +0 -1
- package/src/shared/output/bundle.flow.js +0 -1
- package/src/shared/output/bundle.flow.js.flow +0 -1
- package/src/shared/types.d.ts +0 -12
- package/src/shared/types.flow.js.flow +1 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metro",
|
|
3
|
-
"version": "0.82.
|
|
3
|
+
"version": "0.82.3",
|
|
4
4
|
"description": "🚇 The JavaScript bundler for React Native.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": "src/cli.js",
|
|
@@ -36,24 +36,24 @@
|
|
|
36
36
|
"error-stack-parser": "^2.0.6",
|
|
37
37
|
"flow-enums-runtime": "^0.0.6",
|
|
38
38
|
"graceful-fs": "^4.2.4",
|
|
39
|
-
"hermes-parser": "0.
|
|
39
|
+
"hermes-parser": "0.28.1",
|
|
40
40
|
"image-size": "^1.0.2",
|
|
41
41
|
"invariant": "^2.2.4",
|
|
42
42
|
"jest-worker": "^29.7.0",
|
|
43
43
|
"jsc-safe-url": "^0.2.2",
|
|
44
44
|
"lodash.throttle": "^4.1.1",
|
|
45
|
-
"metro-babel-transformer": "0.82.
|
|
46
|
-
"metro-cache": "0.82.
|
|
47
|
-
"metro-cache-key": "0.82.
|
|
48
|
-
"metro-config": "0.82.
|
|
49
|
-
"metro-core": "0.82.
|
|
50
|
-
"metro-file-map": "0.82.
|
|
51
|
-
"metro-resolver": "0.82.
|
|
52
|
-
"metro-runtime": "0.82.
|
|
53
|
-
"metro-source-map": "0.82.
|
|
54
|
-
"metro-symbolicate": "0.82.
|
|
55
|
-
"metro-transform-plugins": "0.82.
|
|
56
|
-
"metro-transform-worker": "0.82.
|
|
45
|
+
"metro-babel-transformer": "0.82.3",
|
|
46
|
+
"metro-cache": "0.82.3",
|
|
47
|
+
"metro-cache-key": "0.82.3",
|
|
48
|
+
"metro-config": "0.82.3",
|
|
49
|
+
"metro-core": "0.82.3",
|
|
50
|
+
"metro-file-map": "0.82.3",
|
|
51
|
+
"metro-resolver": "0.82.3",
|
|
52
|
+
"metro-runtime": "0.82.3",
|
|
53
|
+
"metro-source-map": "0.82.3",
|
|
54
|
+
"metro-symbolicate": "0.82.3",
|
|
55
|
+
"metro-transform-plugins": "0.82.3",
|
|
56
|
+
"metro-transform-worker": "0.82.3",
|
|
57
57
|
"mime-types": "^2.1.27",
|
|
58
58
|
"nullthrows": "^1.1.1",
|
|
59
59
|
"serialize-error": "^2.1.0",
|
|
@@ -65,14 +65,15 @@
|
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@babel/plugin-transform-flow-strip-types": "^7.25.2",
|
|
67
67
|
"@babel/plugin-transform-modules-commonjs": "^7.24.8",
|
|
68
|
+
"@babel/plugin-transform-runtime": "^7.24.7",
|
|
68
69
|
"@react-native/babel-preset": "0.78.0",
|
|
69
70
|
"@react-native/metro-babel-transformer": "0.78.0",
|
|
70
71
|
"babel-jest": "^29.7.0",
|
|
71
72
|
"dedent": "^0.7.0",
|
|
72
73
|
"jest-snapshot": "^29.7.0",
|
|
73
74
|
"jest-snapshot-serializer-raw": "^1.2.0",
|
|
74
|
-
"metro-babel-register": "0.82.
|
|
75
|
-
"metro-memory-fs": "0.82.
|
|
75
|
+
"metro-babel-register": "0.82.3",
|
|
76
|
+
"metro-memory-fs": "0.82.3",
|
|
76
77
|
"mock-req": "^0.2.0",
|
|
77
78
|
"mock-res": "^0.6.0",
|
|
78
79
|
"stack-trace": "^0.0.10"
|
package/src/Bundler.js.flow
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import type {TransformResultWithSource} from './DeltaBundler';
|
|
15
15
|
import type {TransformOptions} from './DeltaBundler/Worker';
|
|
16
16
|
import type EventEmitter from 'events';
|
|
17
|
-
import type {ConfigT} from 'metro-config
|
|
17
|
+
import type {ConfigT} from 'metro-config';
|
|
18
18
|
|
|
19
19
|
const Transformer = require('./DeltaBundler/Transformer');
|
|
20
20
|
const DependencyGraph = require('./node-haste/DependencyGraph');
|
|
@@ -17,7 +17,7 @@ import type {
|
|
|
17
17
|
} from '../../shared/types.flow';
|
|
18
18
|
import type {Module, ReadOnlyGraph, SerializerOptions} from '../types.flow';
|
|
19
19
|
import type {SourceMapGeneratorOptions} from './sourceMapGenerator';
|
|
20
|
-
import type {GetTransformOptions} from 'metro-config
|
|
20
|
+
import type {GetTransformOptions} from 'metro-config';
|
|
21
21
|
|
|
22
22
|
const {createRamBundleGroups} = require('../../Bundler/util');
|
|
23
23
|
const getAppendScripts = require('../../lib/getAppendScripts');
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import type {TransformResult, TransformResultWithSource} from '../DeltaBundler';
|
|
15
15
|
import type {TransformerConfig, TransformOptions} from './Worker';
|
|
16
|
-
import type {ConfigT} from 'metro-config
|
|
16
|
+
import type {ConfigT} from 'metro-config';
|
|
17
17
|
|
|
18
18
|
import crypto from 'crypto';
|
|
19
19
|
|
|
@@ -11,6 +11,9 @@ function asDeserializedBuffer(value) {
|
|
|
11
11
|
if (value && value.type === "Buffer") {
|
|
12
12
|
return Buffer.from(value.data);
|
|
13
13
|
}
|
|
14
|
+
if (ArrayBuffer.isView(value)) {
|
|
15
|
+
return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
16
|
+
}
|
|
14
17
|
return null;
|
|
15
18
|
}
|
|
16
19
|
async function transform(
|
|
@@ -66,6 +66,9 @@ function asDeserializedBuffer(value: any): Buffer | null {
|
|
|
66
66
|
if (value && value.type === 'Buffer') {
|
|
67
67
|
return Buffer.from(value.data);
|
|
68
68
|
}
|
|
69
|
+
if (ArrayBuffer.isView(value)) {
|
|
70
|
+
return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
71
|
+
}
|
|
69
72
|
return null;
|
|
70
73
|
}
|
|
71
74
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import type {TransformResult} from '../DeltaBundler';
|
|
15
15
|
import type {TransformerConfig, TransformOptions, Worker} from './Worker';
|
|
16
|
-
import type {ConfigT} from 'metro-config
|
|
16
|
+
import type {ConfigT} from 'metro-config';
|
|
17
17
|
import type {Readable} from 'stream';
|
|
18
18
|
|
|
19
19
|
const {Worker: JestWorker} = require('jest-worker');
|
|
@@ -128,6 +128,12 @@ class WorkerFarm {
|
|
|
128
128
|
enableWorkerThreads: this._config.transformer.unstable_workerThreads,
|
|
129
129
|
forkOptions: {env},
|
|
130
130
|
numWorkers,
|
|
131
|
+
// Prefer using lower numbered available workers repeatedly rather than
|
|
132
|
+
// spreading jobs over the whole pool evenly (round-robin). This is more
|
|
133
|
+
// likely to use faster, hot workers earlier in graph traversal, when
|
|
134
|
+
// we want to be able to fan out as quickly as possible, and therefore
|
|
135
|
+
// gets us to full speed faster.
|
|
136
|
+
workerSchedulingPolicy: 'in-order',
|
|
131
137
|
});
|
|
132
138
|
}
|
|
133
139
|
|
|
@@ -145,6 +151,7 @@ class WorkerFarm {
|
|
|
145
151
|
_formatGenericError(err: any, filename: string): TransformError {
|
|
146
152
|
const error = new TransformError(`${filename}: ${err.message}`);
|
|
147
153
|
|
|
154
|
+
// $FlowFixMe[unsafe-object-assign]
|
|
148
155
|
return Object.assign(error, {
|
|
149
156
|
stack: (err.stack || '').split('\n').slice(0, -1).join('\n'),
|
|
150
157
|
lineNumber: 0,
|
|
@@ -89,13 +89,9 @@ export type ReadOnlyDependencies<T = MixedOutput> = $ReadOnlyMap<
|
|
|
89
89
|
Module<T>,
|
|
90
90
|
>;
|
|
91
91
|
|
|
92
|
-
export type TransformInputOptions =
|
|
92
|
+
export type TransformInputOptions = Omit<
|
|
93
93
|
JsTransformOptions,
|
|
94
|
-
|
|
95
|
-
inlinePlatform: boolean,
|
|
96
|
-
inlineRequires: boolean,
|
|
97
|
-
...
|
|
98
|
-
},
|
|
94
|
+
'inlinePlatform' | 'inlineRequires',
|
|
99
95
|
>;
|
|
100
96
|
|
|
101
97
|
export type GraphInputOptions = $ReadOnly<{
|
package/src/HmrServer.js
CHANGED
|
@@ -35,7 +35,7 @@ class HmrServer {
|
|
|
35
35
|
async _registerEntryPoint(client, requestUrl, sendFn) {
|
|
36
36
|
requestUrl = this._config.server.rewriteRequestUrl(requestUrl);
|
|
37
37
|
const clientUrl = nullthrows(url.parse(requestUrl, true));
|
|
38
|
-
const options = parseOptionsFromUrl(
|
|
38
|
+
const { bundleType: _bundleType, ...options } = parseOptionsFromUrl(
|
|
39
39
|
requestUrl,
|
|
40
40
|
new Set(this._config.resolver.platforms)
|
|
41
41
|
);
|
package/src/HmrServer.js.flow
CHANGED
|
@@ -101,7 +101,7 @@ class HmrServer<TClient: Client> {
|
|
|
101
101
|
): Promise<void> {
|
|
102
102
|
requestUrl = this._config.server.rewriteRequestUrl(requestUrl);
|
|
103
103
|
const clientUrl = nullthrows(url.parse(requestUrl, true));
|
|
104
|
-
const options = parseOptionsFromUrl(
|
|
104
|
+
const {bundleType: _bundleType, ...options} = parseOptionsFromUrl(
|
|
105
105
|
requestUrl,
|
|
106
106
|
new Set(this._config.resolver.platforms),
|
|
107
107
|
);
|
|
@@ -19,7 +19,7 @@ import type {
|
|
|
19
19
|
} from './DeltaBundler/types.flow';
|
|
20
20
|
import type {GraphId} from './lib/getGraphId';
|
|
21
21
|
import type {ResolverInputOptions} from './shared/types.flow';
|
|
22
|
-
import type {ConfigT} from 'metro-config
|
|
22
|
+
import type {ConfigT} from 'metro-config';
|
|
23
23
|
|
|
24
24
|
const Bundler = require('./Bundler');
|
|
25
25
|
const DeltaBundler = require('./DeltaBundler');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _types = require("@babel/types");
|
|
3
4
|
const generate = require("@babel/generator").default;
|
|
4
5
|
const template = require("@babel/template").default;
|
|
5
6
|
const traverse = require("@babel/traverse").default;
|
|
@@ -346,6 +347,9 @@ function getNearestLocFromPath(path) {
|
|
|
346
347
|
) {
|
|
347
348
|
current = current.parentPath;
|
|
348
349
|
}
|
|
350
|
+
if (current && (0, _types.isProgram)(current.node)) {
|
|
351
|
+
current = null;
|
|
352
|
+
}
|
|
349
353
|
return current?.node.METRO_INLINE_REQUIRES_INIT_LOC ?? current?.node.loc;
|
|
350
354
|
}
|
|
351
355
|
function registerDependency(state, qualifier, path) {
|
|
@@ -17,6 +17,8 @@ import type {
|
|
|
17
17
|
AsyncDependencyType,
|
|
18
18
|
} from 'metro/src/DeltaBundler/types.flow.js';
|
|
19
19
|
|
|
20
|
+
import {isProgram} from '@babel/types';
|
|
21
|
+
|
|
20
22
|
const generate = require('@babel/generator').default;
|
|
21
23
|
const template = require('@babel/template').default;
|
|
22
24
|
const traverse = require('@babel/traverse').default;
|
|
@@ -575,6 +577,10 @@ function getNearestLocFromPath(path: NodePath<>): ?BabelSourceLocation {
|
|
|
575
577
|
) {
|
|
576
578
|
current = current.parentPath;
|
|
577
579
|
}
|
|
580
|
+
// Do not use the location of the `Program` node
|
|
581
|
+
if (current && isProgram(current.node)) {
|
|
582
|
+
current = null;
|
|
583
|
+
}
|
|
578
584
|
return (
|
|
579
585
|
// $FlowIgnore[prop-missing] METRO_INLINE_REQUIRES_INIT_LOC is Metro-specific and not typed
|
|
580
586
|
current?.node.METRO_INLINE_REQUIRES_INIT_LOC ?? current?.node.loc
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
const invariant = require("invariant");
|
|
4
3
|
function importLocationsPlugin({ types: t }) {
|
|
5
|
-
const importDeclarationLocs = new Set();
|
|
6
4
|
return {
|
|
7
5
|
visitor: {
|
|
8
|
-
ImportDeclaration(path) {
|
|
6
|
+
ImportDeclaration(path, { importDeclarationLocs }) {
|
|
9
7
|
if (path.node.importKind !== "type" && path.node.loc != null) {
|
|
10
8
|
importDeclarationLocs.add(locToKey(path.node.loc));
|
|
11
9
|
}
|
|
12
10
|
},
|
|
13
|
-
ExportDeclaration(path) {
|
|
11
|
+
ExportDeclaration(path, { importDeclarationLocs }) {
|
|
14
12
|
if (
|
|
15
13
|
path.node.source != null &&
|
|
16
14
|
path.node.exportKind !== "type" &&
|
|
@@ -19,21 +17,18 @@ function importLocationsPlugin({ types: t }) {
|
|
|
19
17
|
importDeclarationLocs.add(locToKey(path.node.loc));
|
|
20
18
|
}
|
|
21
19
|
},
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
metroMetadata.metro.unstable_importDeclarationLocs =
|
|
35
|
-
importDeclarationLocs;
|
|
36
|
-
}
|
|
20
|
+
Program(path, state) {
|
|
21
|
+
state.importDeclarationLocs = new Set();
|
|
22
|
+
const metroMetadata = state.file.metadata;
|
|
23
|
+
if (!metroMetadata.metro) {
|
|
24
|
+
metroMetadata.metro = {
|
|
25
|
+
unstable_importDeclarationLocs: state.importDeclarationLocs,
|
|
26
|
+
};
|
|
27
|
+
} else {
|
|
28
|
+
metroMetadata.metro.unstable_importDeclarationLocs =
|
|
29
|
+
state.importDeclarationLocs;
|
|
30
|
+
}
|
|
31
|
+
},
|
|
37
32
|
},
|
|
38
33
|
};
|
|
39
34
|
}
|
|
@@ -11,19 +11,27 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
-
import type {PluginObj} from '@babel/core';
|
|
14
|
+
import type {File, PluginObj} from '@babel/core';
|
|
15
15
|
import typeof * as Types from '@babel/types';
|
|
16
16
|
import type {MetroBabelFileMetadata} from 'metro-babel-transformer';
|
|
17
17
|
|
|
18
|
-
const invariant = require('invariant');
|
|
19
|
-
|
|
20
18
|
type ImportDeclarationLocs = Set<string>;
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
type State = {
|
|
21
|
+
importDeclarationLocs: ImportDeclarationLocs,
|
|
22
|
+
file: File,
|
|
23
|
+
...
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function importLocationsPlugin({
|
|
27
|
+
types: t,
|
|
28
|
+
}: {
|
|
29
|
+
types: Types,
|
|
30
|
+
...
|
|
31
|
+
}): PluginObj<State> {
|
|
24
32
|
return {
|
|
25
33
|
visitor: {
|
|
26
|
-
ImportDeclaration(path) {
|
|
34
|
+
ImportDeclaration(path, {importDeclarationLocs}) {
|
|
27
35
|
if (
|
|
28
36
|
// Ignore type imports
|
|
29
37
|
path.node.importKind !== 'type' &&
|
|
@@ -35,7 +43,7 @@ function importLocationsPlugin({types: t}: {types: Types, ...}): PluginObj<> {
|
|
|
35
43
|
importDeclarationLocs.add(locToKey(path.node.loc));
|
|
36
44
|
}
|
|
37
45
|
},
|
|
38
|
-
ExportDeclaration(path) {
|
|
46
|
+
ExportDeclaration(path, {importDeclarationLocs}) {
|
|
39
47
|
if (
|
|
40
48
|
// If `source` is set, this is a re-export, so it declares an ESM
|
|
41
49
|
// dependency.
|
|
@@ -48,25 +56,23 @@ function importLocationsPlugin({types: t}: {types: Types, ...}): PluginObj<> {
|
|
|
48
56
|
importDeclarationLocs.add(locToKey(path.node.loc));
|
|
49
57
|
}
|
|
50
58
|
},
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
path && t.isProgram(path.node),
|
|
55
|
-
'path missing or not a program node',
|
|
56
|
-
);
|
|
59
|
+
Program(path, state) {
|
|
60
|
+
// Initialise state
|
|
61
|
+
state.importDeclarationLocs = new Set();
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
// $FlowFixMe[prop-missing] Babel `File` is not generically typed
|
|
64
|
+
const metroMetadata: MetroBabelFileMetadata = state.file.metadata;
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
// Set the result on a metadata property
|
|
67
|
+
if (!metroMetadata.metro) {
|
|
68
|
+
metroMetadata.metro = {
|
|
69
|
+
unstable_importDeclarationLocs: state.importDeclarationLocs,
|
|
70
|
+
};
|
|
71
|
+
} else {
|
|
72
|
+
metroMetadata.metro.unstable_importDeclarationLocs =
|
|
73
|
+
state.importDeclarationLocs;
|
|
74
|
+
}
|
|
75
|
+
},
|
|
70
76
|
},
|
|
71
77
|
};
|
|
72
78
|
}
|
|
@@ -15,7 +15,7 @@ import type {
|
|
|
15
15
|
MetroSourceMapSegmentTuple,
|
|
16
16
|
} from '../../../metro-source-map/src/source-map';
|
|
17
17
|
import type {ExplodedSourceMap} from '../DeltaBundler/Serializers/getExplodedSourceMap';
|
|
18
|
-
import type {ConfigT} from 'metro-config
|
|
18
|
+
import type {ConfigT} from 'metro-config';
|
|
19
19
|
|
|
20
20
|
const {greatestLowerBound} = require('metro-source-map/src/Consumer/search');
|
|
21
21
|
const {
|
package/src/Server.js
CHANGED
|
@@ -17,6 +17,7 @@ const ResourceNotFoundError = require("./IncrementalBundler/ResourceNotFoundErro
|
|
|
17
17
|
const bundleToString = require("./lib/bundleToString");
|
|
18
18
|
const formatBundlingError = require("./lib/formatBundlingError");
|
|
19
19
|
const getGraphId = require("./lib/getGraphId");
|
|
20
|
+
const parseJsonBody = require("./lib/parseJsonBody");
|
|
20
21
|
const parseOptionsFromUrl = require("./lib/parseOptionsFromUrl");
|
|
21
22
|
const splitBundleOptions = require("./lib/splitBundleOptions");
|
|
22
23
|
const transformHelpers = require("./lib/transformHelpers");
|
|
@@ -268,7 +269,6 @@ class Server {
|
|
|
268
269
|
splitBundleOptions({
|
|
269
270
|
...Server.DEFAULT_BUNDLE_OPTIONS,
|
|
270
271
|
...options,
|
|
271
|
-
bundleType: "bundle",
|
|
272
272
|
});
|
|
273
273
|
const { prepend, graph } = await this._bundler.buildGraph(
|
|
274
274
|
entryFile,
|
|
@@ -357,7 +357,11 @@ class Server {
|
|
|
357
357
|
this._processRequest(req, res, next).catch(next);
|
|
358
358
|
};
|
|
359
359
|
_parseOptions(url) {
|
|
360
|
-
|
|
360
|
+
const { bundleType: _bundleType, ...bundleOptions } = parseOptionsFromUrl(
|
|
361
|
+
url,
|
|
362
|
+
new Set(this._config.resolver.platforms)
|
|
363
|
+
);
|
|
364
|
+
return bundleOptions;
|
|
361
365
|
}
|
|
362
366
|
_rewriteAndNormalizeUrl(requestUrl) {
|
|
363
367
|
return jscSafeUrl.toNormalUrl(
|
|
@@ -471,6 +475,7 @@ class Server {
|
|
|
471
475
|
});
|
|
472
476
|
}
|
|
473
477
|
_createRequestProcessor({
|
|
478
|
+
bundleType,
|
|
474
479
|
createStartEntry,
|
|
475
480
|
createEndEntry,
|
|
476
481
|
build,
|
|
@@ -570,7 +575,7 @@ class Server {
|
|
|
570
575
|
this._reporter.update({
|
|
571
576
|
buildID: getBuildID(buildNumber),
|
|
572
577
|
bundleDetails: {
|
|
573
|
-
bundleType
|
|
578
|
+
bundleType,
|
|
574
579
|
customResolverOptions: bundleOptions.customResolverOptions,
|
|
575
580
|
customTransformOptions: bundleOptions.customTransformOptions,
|
|
576
581
|
dev: transformOptions.dev,
|
|
@@ -648,6 +653,7 @@ class Server {
|
|
|
648
653
|
};
|
|
649
654
|
}
|
|
650
655
|
_processBundleRequest = this._createRequestProcessor({
|
|
656
|
+
bundleType: "bundle",
|
|
651
657
|
createStartEntry(context) {
|
|
652
658
|
return {
|
|
653
659
|
action_name: "Requesting bundle",
|
|
@@ -826,6 +832,7 @@ class Server {
|
|
|
826
832
|
);
|
|
827
833
|
}
|
|
828
834
|
_processSourceMapRequest = this._createRequestProcessor({
|
|
835
|
+
bundleType: "map",
|
|
829
836
|
createStartEntry(context) {
|
|
830
837
|
return {
|
|
831
838
|
action_name: "Requesting sourcemap",
|
|
@@ -889,6 +896,7 @@ class Server {
|
|
|
889
896
|
},
|
|
890
897
|
});
|
|
891
898
|
_processAssetsRequest = this._createRequestProcessor({
|
|
899
|
+
bundleType: "assets",
|
|
892
900
|
createStartEntry(context) {
|
|
893
901
|
return {
|
|
894
902
|
action_name: "Requesting assets",
|
|
@@ -933,10 +941,13 @@ class Server {
|
|
|
933
941
|
});
|
|
934
942
|
async _symbolicate(req, res) {
|
|
935
943
|
const getCodeFrame = (urls, symbolicatedStack) => {
|
|
944
|
+
const allFramesCollapsed = symbolicatedStack.every(
|
|
945
|
+
({ collapse }) => collapse
|
|
946
|
+
);
|
|
936
947
|
for (let i = 0; i < symbolicatedStack.length; i++) {
|
|
937
948
|
const { collapse, column, file, lineNumber } = symbolicatedStack[i];
|
|
938
949
|
if (
|
|
939
|
-
collapse ||
|
|
950
|
+
(!allFramesCollapsed && collapse) ||
|
|
940
951
|
lineNumber == null ||
|
|
941
952
|
(file != null && urls.has(file))
|
|
942
953
|
) {
|
|
@@ -974,8 +985,13 @@ class Server {
|
|
|
974
985
|
createActionStartEntry("Symbolicating")
|
|
975
986
|
);
|
|
976
987
|
debug("Start symbolication");
|
|
977
|
-
|
|
978
|
-
|
|
988
|
+
let parsedBody;
|
|
989
|
+
if ("rawBody" in req) {
|
|
990
|
+
const body = await req.rawBody;
|
|
991
|
+
parsedBody = JSON.parse(body);
|
|
992
|
+
} else {
|
|
993
|
+
parsedBody = await parseJsonBody(req);
|
|
994
|
+
}
|
|
979
995
|
const rewriteAndNormalizeStackFrame = (frame, lineNumber) => {
|
|
980
996
|
invariant(
|
|
981
997
|
frame != null && typeof frame === "object",
|
package/src/Server.js.flow
CHANGED
|
@@ -24,7 +24,7 @@ import type {
|
|
|
24
24
|
import type {RevisionId} from './IncrementalBundler';
|
|
25
25
|
import type {GraphId} from './lib/getGraphId';
|
|
26
26
|
import type {Reporter} from './lib/reporting';
|
|
27
|
-
import type {StackFrameOutput} from './Server/symbolicate';
|
|
27
|
+
import type {StackFrameInput, StackFrameOutput} from './Server/symbolicate';
|
|
28
28
|
import type {
|
|
29
29
|
BundleOptions,
|
|
30
30
|
GraphOptions,
|
|
@@ -34,11 +34,10 @@ import type {
|
|
|
34
34
|
import type {IncomingMessage} from 'connect';
|
|
35
35
|
import type {ServerResponse} from 'http';
|
|
36
36
|
import type {CacheStore} from 'metro-cache';
|
|
37
|
-
import type {ConfigT, RootPerfLogger} from 'metro-config
|
|
37
|
+
import type {ConfigT, RootPerfLogger} from 'metro-config';
|
|
38
38
|
import type {
|
|
39
39
|
ActionLogEntryData,
|
|
40
40
|
ActionStartLogEntry,
|
|
41
|
-
LogEntry,
|
|
42
41
|
} from 'metro-core/src/Logger';
|
|
43
42
|
import type {CustomResolverOptions} from 'metro-resolver/src/types';
|
|
44
43
|
import type {CustomTransformOptions} from 'metro-transform-worker';
|
|
@@ -61,6 +60,7 @@ const ResourceNotFoundError = require('./IncrementalBundler/ResourceNotFoundErro
|
|
|
61
60
|
const bundleToString = require('./lib/bundleToString');
|
|
62
61
|
const formatBundlingError = require('./lib/formatBundlingError');
|
|
63
62
|
const getGraphId = require('./lib/getGraphId');
|
|
63
|
+
const parseJsonBody = require('./lib/parseJsonBody');
|
|
64
64
|
const parseOptionsFromUrl = require('./lib/parseOptionsFromUrl');
|
|
65
65
|
const splitBundleOptions = require('./lib/splitBundleOptions');
|
|
66
66
|
const transformHelpers = require('./lib/transformHelpers');
|
|
@@ -404,7 +404,6 @@ class Server {
|
|
|
404
404
|
} = splitBundleOptions({
|
|
405
405
|
...Server.DEFAULT_BUNDLE_OPTIONS,
|
|
406
406
|
...options,
|
|
407
|
-
bundleType: 'bundle',
|
|
408
407
|
});
|
|
409
408
|
|
|
410
409
|
const {prepend, graph} = await this._bundler.buildGraph(
|
|
@@ -469,6 +468,7 @@ class Server {
|
|
|
469
468
|
urlObj.query.unstable_path.match(/^([^?]*)\??(.*)$/),
|
|
470
469
|
);
|
|
471
470
|
if (secondaryQuery) {
|
|
471
|
+
// $FlowFixMe[unsafe-object-assign]
|
|
472
472
|
Object.assign(urlObj.query, querystring.parse(secondaryQuery));
|
|
473
473
|
}
|
|
474
474
|
assetPath = actualPath;
|
|
@@ -524,7 +524,11 @@ class Server {
|
|
|
524
524
|
};
|
|
525
525
|
|
|
526
526
|
_parseOptions(url: string): BundleOptions {
|
|
527
|
-
|
|
527
|
+
const {bundleType: _bundleType, ...bundleOptions} = parseOptionsFromUrl(
|
|
528
|
+
url,
|
|
529
|
+
new Set(this._config.resolver.platforms),
|
|
530
|
+
);
|
|
531
|
+
return bundleOptions;
|
|
528
532
|
}
|
|
529
533
|
|
|
530
534
|
_rewriteAndNormalizeUrl(requestUrl: string): string {
|
|
@@ -652,16 +656,18 @@ class Server {
|
|
|
652
656
|
}
|
|
653
657
|
|
|
654
658
|
_createRequestProcessor<T>({
|
|
659
|
+
bundleType,
|
|
655
660
|
createStartEntry,
|
|
656
661
|
createEndEntry,
|
|
657
662
|
build,
|
|
658
663
|
delete: deleteFn,
|
|
659
664
|
finish,
|
|
660
665
|
}: {
|
|
666
|
+
+bundleType: 'assets' | 'bundle' | 'map',
|
|
661
667
|
+createStartEntry: (context: ProcessStartContext) => ActionLogEntryData,
|
|
662
668
|
+createEndEntry: (
|
|
663
669
|
context: ProcessEndContext<T>,
|
|
664
|
-
) =>
|
|
670
|
+
) => Partial<ActionStartLogEntry>,
|
|
665
671
|
+build: (context: ProcessStartContext) => Promise<T>,
|
|
666
672
|
+delete?: (context: ProcessDeleteContext) => Promise<void>,
|
|
667
673
|
+finish: (context: ProcessEndContext<T>) => void,
|
|
@@ -796,7 +802,7 @@ class Server {
|
|
|
796
802
|
this._reporter.update({
|
|
797
803
|
buildID: getBuildID(buildNumber),
|
|
798
804
|
bundleDetails: {
|
|
799
|
-
bundleType
|
|
805
|
+
bundleType,
|
|
800
806
|
customResolverOptions: bundleOptions.customResolverOptions,
|
|
801
807
|
customTransformOptions: bundleOptions.customTransformOptions,
|
|
802
808
|
dev: transformOptions.dev,
|
|
@@ -895,6 +901,7 @@ class Server {
|
|
|
895
901
|
bundlePerfLogger: RootPerfLogger,
|
|
896
902
|
}>,
|
|
897
903
|
) => Promise<void> = this._createRequestProcessor({
|
|
904
|
+
bundleType: 'bundle',
|
|
898
905
|
createStartEntry(context: ProcessStartContext) {
|
|
899
906
|
return {
|
|
900
907
|
action_name: 'Requesting bundle',
|
|
@@ -1104,6 +1111,7 @@ class Server {
|
|
|
1104
1111
|
bundlePerfLogger: RootPerfLogger,
|
|
1105
1112
|
}>,
|
|
1106
1113
|
) => Promise<void> = this._createRequestProcessor({
|
|
1114
|
+
bundleType: 'map',
|
|
1107
1115
|
createStartEntry(context: ProcessStartContext) {
|
|
1108
1116
|
return {
|
|
1109
1117
|
action_name: 'Requesting sourcemap',
|
|
@@ -1175,6 +1183,7 @@ class Server {
|
|
|
1175
1183
|
bundlePerfLogger: RootPerfLogger,
|
|
1176
1184
|
}>,
|
|
1177
1185
|
) => Promise<void> = this._createRequestProcessor({
|
|
1186
|
+
bundleType: 'assets',
|
|
1178
1187
|
createStartEntry(context: ProcessStartContext) {
|
|
1179
1188
|
return {
|
|
1180
1189
|
action_name: 'Requesting assets',
|
|
@@ -1220,11 +1229,17 @@ class Server {
|
|
|
1220
1229
|
urls: Set<string>,
|
|
1221
1230
|
symbolicatedStack: $ReadOnlyArray<StackFrameOutput>,
|
|
1222
1231
|
) => {
|
|
1232
|
+
const allFramesCollapsed = symbolicatedStack.every(
|
|
1233
|
+
({collapse}) => collapse,
|
|
1234
|
+
);
|
|
1235
|
+
|
|
1223
1236
|
for (let i = 0; i < symbolicatedStack.length; i++) {
|
|
1224
1237
|
const {collapse, column, file, lineNumber} = symbolicatedStack[i];
|
|
1225
1238
|
|
|
1226
1239
|
if (
|
|
1227
|
-
collapse
|
|
1240
|
+
// If all the frames are collapsed then we should ignore the collapse flag
|
|
1241
|
+
// and always show the first valid frame.
|
|
1242
|
+
(!allFramesCollapsed && collapse) ||
|
|
1228
1243
|
lineNumber == null ||
|
|
1229
1244
|
(file != null && urls.has(file))
|
|
1230
1245
|
) {
|
|
@@ -1262,9 +1277,20 @@ class Server {
|
|
|
1262
1277
|
createActionStartEntry('Symbolicating'),
|
|
1263
1278
|
);
|
|
1264
1279
|
debug('Start symbolication');
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1280
|
+
|
|
1281
|
+
let parsedBody;
|
|
1282
|
+
if ('rawBody' in req) {
|
|
1283
|
+
// TODO: Remove this branch once we are no longer targeting React Native
|
|
1284
|
+
// < 0.80 and Expo SDK < 53
|
|
1285
|
+
// $FlowFixMe[prop-missing] - rawBody assigned by legacy CLI integrations
|
|
1286
|
+
const body = await req.rawBody;
|
|
1287
|
+
parsedBody = JSON.parse(body);
|
|
1288
|
+
} else {
|
|
1289
|
+
parsedBody = (await parseJsonBody(req)) as {
|
|
1290
|
+
stack: $ReadOnlyArray<StackFrameInput>,
|
|
1291
|
+
extraData: {[string]: mixed},
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1268
1294
|
|
|
1269
1295
|
const rewriteAndNormalizeStackFrame = <T>(
|
|
1270
1296
|
frame: T,
|
package/src/index.flow.js
CHANGED
|
@@ -216,6 +216,7 @@ exports.runServer = async (
|
|
|
216
216
|
exports.runBuild = async (
|
|
217
217
|
config,
|
|
218
218
|
{
|
|
219
|
+
assets = false,
|
|
219
220
|
customResolverOptions,
|
|
220
221
|
customTransformOptions,
|
|
221
222
|
dev = false,
|
|
@@ -229,6 +230,7 @@ exports.runBuild = async (
|
|
|
229
230
|
platform = "web",
|
|
230
231
|
sourceMap = false,
|
|
231
232
|
sourceMapUrl,
|
|
233
|
+
unstable_transformProfile,
|
|
232
234
|
}
|
|
233
235
|
) => {
|
|
234
236
|
const metroServer = await runMetro(config, {
|
|
@@ -246,11 +248,21 @@ exports.runBuild = async (
|
|
|
246
248
|
onProgress,
|
|
247
249
|
customResolverOptions,
|
|
248
250
|
customTransformOptions,
|
|
251
|
+
unstable_transformProfile,
|
|
249
252
|
};
|
|
250
253
|
if (onBegin) {
|
|
251
254
|
onBegin();
|
|
252
255
|
}
|
|
253
256
|
const metroBundle = await output.build(metroServer, requestOptions);
|
|
257
|
+
const result = {
|
|
258
|
+
...metroBundle,
|
|
259
|
+
};
|
|
260
|
+
if (assets) {
|
|
261
|
+
result.assets = await metroServer.getAssets({
|
|
262
|
+
...MetroServer.DEFAULT_BUNDLE_OPTIONS,
|
|
263
|
+
...requestOptions,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
254
266
|
if (onComplete) {
|
|
255
267
|
onComplete();
|
|
256
268
|
}
|
|
@@ -271,7 +283,7 @@ exports.runBuild = async (
|
|
|
271
283
|
})
|
|
272
284
|
);
|
|
273
285
|
}
|
|
274
|
-
return
|
|
286
|
+
return result;
|
|
275
287
|
} finally {
|
|
276
288
|
await metroServer.end();
|
|
277
289
|
}
|
package/src/index.flow.js.flow
CHANGED
|
@@ -11,18 +11,20 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
+
import type {AssetData} from './Assets';
|
|
14
15
|
import type {ReadOnlyGraph} from './DeltaBundler';
|
|
15
16
|
import type {ServerOptions} from './Server';
|
|
16
17
|
import type {OutputOptions, RequestOptions} from './shared/types.flow.js';
|
|
17
18
|
import type {HandleFunction} from 'connect';
|
|
18
19
|
import type {Server as HttpServer} from 'http';
|
|
19
20
|
import type {Server as HttpsServer} from 'https';
|
|
21
|
+
import type {TransformProfile} from 'metro-babel-transformer';
|
|
20
22
|
import type {
|
|
21
23
|
ConfigT,
|
|
22
24
|
InputConfigT,
|
|
23
25
|
MetroConfig,
|
|
24
26
|
Middleware,
|
|
25
|
-
} from 'metro-config
|
|
27
|
+
} from 'metro-config';
|
|
26
28
|
import type {CustomResolverOptions} from 'metro-resolver';
|
|
27
29
|
import type {CustomTransformOptions} from 'metro-transform-worker';
|
|
28
30
|
import typeof Yargs from 'yargs';
|
|
@@ -92,6 +94,7 @@ type BuildGraphOptions = {
|
|
|
92
94
|
|
|
93
95
|
export type RunBuildOptions = {
|
|
94
96
|
entry: string,
|
|
97
|
+
assets?: boolean,
|
|
95
98
|
dev?: boolean,
|
|
96
99
|
out?: string,
|
|
97
100
|
onBegin?: () => void,
|
|
@@ -123,6 +126,14 @@ export type RunBuildOptions = {
|
|
|
123
126
|
sourceMapUrl?: string,
|
|
124
127
|
customResolverOptions?: CustomResolverOptions,
|
|
125
128
|
customTransformOptions?: CustomTransformOptions,
|
|
129
|
+
unstable_transformProfile?: TransformProfile,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export type RunBuildResult = {
|
|
133
|
+
code: string,
|
|
134
|
+
map: string,
|
|
135
|
+
assets?: $ReadOnlyArray<AssetData>,
|
|
136
|
+
...
|
|
126
137
|
};
|
|
127
138
|
|
|
128
139
|
type BuildCommandOptions = {} | null;
|
|
@@ -131,6 +142,9 @@ type ServeCommandOptions = {} | null;
|
|
|
131
142
|
exports.Terminal = Terminal;
|
|
132
143
|
exports.TerminalReporter = TerminalReporter;
|
|
133
144
|
|
|
145
|
+
export type {AssetData} from './Assets';
|
|
146
|
+
export type {Reporter, ReportableEvent} from './lib/reporting';
|
|
147
|
+
export type {TerminalReportableEvent} from './lib/TerminalReporter';
|
|
134
148
|
export type {MetroConfig};
|
|
135
149
|
|
|
136
150
|
async function getConfig(config: InputConfigT): Promise<ConfigT> {
|
|
@@ -369,6 +383,7 @@ exports.runServer = async (
|
|
|
369
383
|
exports.runBuild = async (
|
|
370
384
|
config: ConfigT,
|
|
371
385
|
{
|
|
386
|
+
assets = false,
|
|
372
387
|
customResolverOptions,
|
|
373
388
|
customTransformOptions,
|
|
374
389
|
dev = false,
|
|
@@ -382,12 +397,9 @@ exports.runBuild = async (
|
|
|
382
397
|
platform = 'web',
|
|
383
398
|
sourceMap = false,
|
|
384
399
|
sourceMapUrl,
|
|
400
|
+
unstable_transformProfile,
|
|
385
401
|
}: RunBuildOptions,
|
|
386
|
-
): Promise<{
|
|
387
|
-
code: string,
|
|
388
|
-
map: string,
|
|
389
|
-
...
|
|
390
|
-
}> => {
|
|
402
|
+
): Promise<RunBuildResult> => {
|
|
391
403
|
const metroServer = await runMetro(config, {
|
|
392
404
|
watch: false,
|
|
393
405
|
});
|
|
@@ -404,6 +416,7 @@ exports.runBuild = async (
|
|
|
404
416
|
onProgress,
|
|
405
417
|
customResolverOptions,
|
|
406
418
|
customTransformOptions,
|
|
419
|
+
unstable_transformProfile,
|
|
407
420
|
};
|
|
408
421
|
|
|
409
422
|
if (onBegin) {
|
|
@@ -411,6 +424,14 @@ exports.runBuild = async (
|
|
|
411
424
|
}
|
|
412
425
|
|
|
413
426
|
const metroBundle = await output.build(metroServer, requestOptions);
|
|
427
|
+
const result: RunBuildResult = {...metroBundle};
|
|
428
|
+
|
|
429
|
+
if (assets) {
|
|
430
|
+
result.assets = await metroServer.getAssets({
|
|
431
|
+
...MetroServer.DEFAULT_BUNDLE_OPTIONS,
|
|
432
|
+
...requestOptions,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
414
435
|
|
|
415
436
|
if (onComplete) {
|
|
416
437
|
onComplete();
|
|
@@ -436,7 +457,7 @@ exports.runBuild = async (
|
|
|
436
457
|
);
|
|
437
458
|
}
|
|
438
459
|
|
|
439
|
-
return
|
|
460
|
+
return result;
|
|
440
461
|
} finally {
|
|
441
462
|
await metroServer.end();
|
|
442
463
|
}
|
|
@@ -46,6 +46,7 @@ class JsonReporter<TEvent: {[string]: any, ...}> {
|
|
|
46
46
|
update(event: TEvent): void {
|
|
47
47
|
if (event.error instanceof Error) {
|
|
48
48
|
const {message, stack} = event.error;
|
|
49
|
+
// $FlowFixMe[unsafe-object-assign]
|
|
49
50
|
event = Object.assign(event, {
|
|
50
51
|
error: serializeError(event.error),
|
|
51
52
|
// TODO: Preexisting issue - this writes message, stack, etc. as
|
|
@@ -38,14 +38,17 @@ function formatBundlingError(error) {
|
|
|
38
38
|
(error instanceof Error &&
|
|
39
39
|
(error.type === "TransformError" || error.type === "NotFoundError"))
|
|
40
40
|
) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
return {
|
|
42
|
+
...serializeError(error),
|
|
43
|
+
type: error.type,
|
|
44
|
+
errors: [
|
|
45
|
+
{
|
|
46
|
+
description: error.message,
|
|
47
|
+
filename: error.filename,
|
|
48
|
+
lineNumber: error.lineNumber,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
};
|
|
49
52
|
} else if (error instanceof ResourceNotFoundError) {
|
|
50
53
|
return {
|
|
51
54
|
type: "ResourceNotFoundError",
|
|
@@ -62,15 +62,18 @@ function formatBundlingError(error: CustomError): FormattedError {
|
|
|
62
62
|
(error instanceof Error &&
|
|
63
63
|
(error.type === 'TransformError' || error.type === 'NotFoundError'))
|
|
64
64
|
) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
65
|
+
return {
|
|
66
|
+
...serializeError(error),
|
|
67
|
+
// Ensure the type is passed to the client.
|
|
68
|
+
type: error.type,
|
|
69
|
+
errors: [
|
|
70
|
+
{
|
|
71
|
+
description: error.message,
|
|
72
|
+
filename: error.filename,
|
|
73
|
+
lineNumber: error.lineNumber,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
74
77
|
} else if (error instanceof ResourceNotFoundError) {
|
|
75
78
|
return {
|
|
76
79
|
type: 'ResourceNotFoundError',
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const CONTENT_TYPE = "application/json";
|
|
4
|
+
const SIZE_LIMIT = 100 * 1024 * 1024;
|
|
5
|
+
function parseJsonBody(req, options = {}) {
|
|
6
|
+
const { strict = true } = options;
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
if (strict) {
|
|
9
|
+
const contentType = req.headers["content-type"] || "";
|
|
10
|
+
if (!contentType.includes(CONTENT_TYPE)) {
|
|
11
|
+
reject(new Error(`Invalid content type, expected ${CONTENT_TYPE}`));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
let size = 0;
|
|
16
|
+
let data = "";
|
|
17
|
+
req.on("data", (chunk) => {
|
|
18
|
+
size += Buffer.byteLength(chunk);
|
|
19
|
+
if (size > SIZE_LIMIT) {
|
|
20
|
+
req.destroy();
|
|
21
|
+
reject(new Error("Request body size exceeds size limit (100MB)"));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
data += chunk;
|
|
25
|
+
});
|
|
26
|
+
req.on("end", () => {
|
|
27
|
+
try {
|
|
28
|
+
resolve(JSON.parse(data));
|
|
29
|
+
} catch (e) {
|
|
30
|
+
reject(e);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
module.exports = parseJsonBody;
|
|
@@ -0,0 +1,60 @@
|
|
|
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-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall react_native
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {IncomingMessage} from 'http';
|
|
13
|
+
|
|
14
|
+
const CONTENT_TYPE = 'application/json';
|
|
15
|
+
const SIZE_LIMIT = 100 * 1024 * 1024; // 100MB
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Attempt to parse a request body as JSON.
|
|
19
|
+
*/
|
|
20
|
+
function parseJsonBody(
|
|
21
|
+
req: IncomingMessage,
|
|
22
|
+
options: {strict?: boolean} = {},
|
|
23
|
+
): Promise<$FlowFixMe> {
|
|
24
|
+
const {strict = true} = options;
|
|
25
|
+
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
if (strict) {
|
|
28
|
+
const contentType = req.headers['content-type'] || '';
|
|
29
|
+
if (!contentType.includes(CONTENT_TYPE)) {
|
|
30
|
+
reject(new Error(`Invalid content type, expected ${CONTENT_TYPE}`));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let size = 0;
|
|
36
|
+
let data = '';
|
|
37
|
+
|
|
38
|
+
req.on('data', (chunk: string) => {
|
|
39
|
+
size += Buffer.byteLength(chunk);
|
|
40
|
+
|
|
41
|
+
if (size > SIZE_LIMIT) {
|
|
42
|
+
req.destroy();
|
|
43
|
+
reject(new Error('Request body size exceeds size limit (100MB)'));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
data += chunk;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
req.on('end', () => {
|
|
51
|
+
try {
|
|
52
|
+
resolve(JSON.parse(data));
|
|
53
|
+
} catch (e) {
|
|
54
|
+
reject(e);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = parseJsonBody;
|
|
@@ -44,7 +44,11 @@ const getTransformProfile = (transformProfile: string): TransformProfile =>
|
|
|
44
44
|
module.exports = function parseOptionsFromUrl(
|
|
45
45
|
normalizedRequestUrl: string,
|
|
46
46
|
platforms: Set<string>,
|
|
47
|
-
):
|
|
47
|
+
): {
|
|
48
|
+
...BundleOptions,
|
|
49
|
+
// Retained for backwards compatibility, unused in Metro, to be removed.
|
|
50
|
+
bundleType: string,
|
|
51
|
+
} {
|
|
48
52
|
const parsedURL = nullthrows(url.parse(normalizedRequestUrl, true)); // `true` to parse the query param as an object.
|
|
49
53
|
const query = nullthrows(parsedURL.query);
|
|
50
54
|
const pathname =
|
|
@@ -21,7 +21,7 @@ import type {
|
|
|
21
21
|
import type {TransformOptions} from '../DeltaBundler/Worker';
|
|
22
22
|
import type {ResolverInputOptions} from '../shared/types.flow';
|
|
23
23
|
import type {RequireContext} from './contextModule';
|
|
24
|
-
import type {ConfigT} from 'metro-config
|
|
24
|
+
import type {ConfigT} from 'metro-config';
|
|
25
25
|
import type {Type} from 'metro-transform-worker';
|
|
26
26
|
|
|
27
27
|
import {getContextModuleTemplate} from './contextModuleTemplates';
|
|
@@ -15,7 +15,7 @@ import type {
|
|
|
15
15
|
} from '../DeltaBundler/types.flow';
|
|
16
16
|
import type {ResolverInputOptions} from '../shared/types.flow';
|
|
17
17
|
import type Package from './Package';
|
|
18
|
-
import type {ConfigT} from 'metro-config
|
|
18
|
+
import type {ConfigT} from 'metro-config';
|
|
19
19
|
import type MetroFileMap, {
|
|
20
20
|
ChangeEvent,
|
|
21
21
|
FileSystem,
|
package/src/shared/types.d.ts
CHANGED
|
@@ -23,21 +23,9 @@ import type {
|
|
|
23
23
|
MinifierOptions,
|
|
24
24
|
} from 'metro-transform-worker';
|
|
25
25
|
|
|
26
|
-
export type BundleType =
|
|
27
|
-
| 'bundle'
|
|
28
|
-
| 'delta'
|
|
29
|
-
| 'meta'
|
|
30
|
-
| 'map'
|
|
31
|
-
| 'ram'
|
|
32
|
-
| 'cli'
|
|
33
|
-
| 'hmr'
|
|
34
|
-
| 'todo'
|
|
35
|
-
| 'graph';
|
|
36
|
-
|
|
37
26
|
type MetroSourceMapOrMappings = MixedSourceMap | MetroSourceMapSegmentTuple[];
|
|
38
27
|
|
|
39
28
|
export interface BundleOptions {
|
|
40
|
-
bundleType: BundleType;
|
|
41
29
|
readonly customResolverOptions: CustomResolverOptions;
|
|
42
30
|
customTransformOptions: CustomTransformOptions;
|
|
43
31
|
dev: boolean;
|
|
@@ -26,17 +26,6 @@ import type {
|
|
|
26
26
|
MinifierOptions,
|
|
27
27
|
} from 'metro-transform-worker';
|
|
28
28
|
|
|
29
|
-
type BundleType =
|
|
30
|
-
| 'bundle'
|
|
31
|
-
| 'delta'
|
|
32
|
-
| 'meta'
|
|
33
|
-
| 'map'
|
|
34
|
-
| 'ram'
|
|
35
|
-
| 'cli'
|
|
36
|
-
| 'hmr'
|
|
37
|
-
| 'todo'
|
|
38
|
-
| 'graph';
|
|
39
|
-
|
|
40
29
|
type MetroSourceMapOrMappings =
|
|
41
30
|
| MixedSourceMap
|
|
42
31
|
| Array<MetroSourceMapSegmentTuple>;
|
|
@@ -49,7 +38,6 @@ export enum SourcePathsMode {
|
|
|
49
38
|
}
|
|
50
39
|
|
|
51
40
|
export type BundleOptions = {
|
|
52
|
-
bundleType: BundleType,
|
|
53
41
|
+customResolverOptions: CustomResolverOptions,
|
|
54
42
|
customTransformOptions: CustomTransformOptions,
|
|
55
43
|
dev: boolean,
|
|
@@ -151,6 +139,7 @@ export type RequestOptions = {
|
|
|
151
139
|
onProgress?: (transformedFileCount: number, totalFileCount: number) => void,
|
|
152
140
|
+customResolverOptions?: CustomResolverOptions,
|
|
153
141
|
+customTransformOptions?: CustomTransformOptions,
|
|
142
|
+
+unstable_transformProfile?: TransformProfile,
|
|
154
143
|
};
|
|
155
144
|
|
|
156
145
|
export type {MinifierOptions};
|