metro 0.71.1 → 0.72.0
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 -22
- package/src/Assets.js +3 -2
- package/src/Assets.js.flow +3 -2
- package/src/Bundler.js +0 -2
- package/src/Bundler.js.flow +1 -1
- package/src/DeltaBundler/DeltaCalculator.js +2 -0
- package/src/DeltaBundler/DeltaCalculator.js.flow +2 -0
- package/src/DeltaBundler/WorkerFarm.js.flow +2 -2
- package/src/DeltaBundler/graphOperations.js +50 -47
- package/src/DeltaBundler/graphOperations.js.flow +46 -52
- package/src/DeltaBundler/types.flow.js +6 -0
- package/src/DeltaBundler/types.flow.js.flow +12 -3
- package/src/DeltaBundler.js +0 -2
- package/src/DeltaBundler.js.flow +1 -1
- package/src/HmrServer.js +0 -2
- package/src/HmrServer.js.flow +1 -2
- package/src/ModuleGraph/node-haste/node-haste.flow.js +0 -1
- package/src/ModuleGraph/node-haste/node-haste.flow.js.flow +1 -2
- package/src/ModuleGraph/node-haste/node-haste.js +12 -3
- package/src/ModuleGraph/node-haste/node-haste.js.flow +34 -7
- package/src/ModuleGraph/output/util.js +1 -0
- package/src/ModuleGraph/output/util.js.flow +3 -2
- package/src/ModuleGraph/silent-console.js +5 -4
- package/src/ModuleGraph/silent-console.js.flow +8 -4
- package/src/ModuleGraph/worker/collectDependencies.js +229 -33
- package/src/ModuleGraph/worker/collectDependencies.js.flow +250 -48
- package/src/Server.js +4 -0
- package/src/Server.js.flow +11 -2
- package/src/cli-utils.js.flow +1 -1
- package/src/commands/build.js +1 -2
- package/src/commands/build.js.flow +6 -9
- package/src/commands/dependencies.js +1 -1
- package/src/commands/serve.js +2 -1
- package/src/commands/serve.js.flow +7 -8
- package/src/index.flow.js +11 -8
- package/src/index.flow.js.flow +10 -7
- package/src/lib/CountingSet.js +116 -0
- package/src/lib/CountingSet.js.flow +126 -0
- package/src/lib/JsonReporter.js +0 -2
- package/src/lib/JsonReporter.js.flow +1 -1
- package/src/lib/getAppendScripts.js +10 -4
- package/src/lib/getAppendScripts.js.flow +6 -4
- package/src/lib/getPreludeCode.js +19 -1
- package/src/lib/getPreludeCode.js.flow +15 -0
- package/src/lib/getPrependedScripts.js +10 -2
- package/src/lib/getPrependedScripts.js.flow +11 -2
- package/src/lib/reporting.js +0 -2
- package/src/lib/reporting.js.flow +2 -1
- package/src/node-haste/DependencyGraph/createHasteMap.js +8 -1
- package/src/node-haste/DependencyGraph/createHasteMap.js.flow +9 -2
- package/src/node-haste/DependencyGraph.js +2 -2
- package/src/node-haste/DependencyGraph.js.flow +4 -2
- package/src/shared/output/bundle.flow.js +67 -0
- package/src/shared/output/bundle.flow.js.flow +89 -0
- package/src/shared/output/bundle.js +8 -55
- package/src/shared/output/bundle.js.flow +8 -75
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
AsyncDependencyType,
|
|
18
18
|
} from 'metro/src/DeltaBundler/types.flow.js';
|
|
19
19
|
|
|
20
|
+
const crypto = require('crypto');
|
|
20
21
|
const generate = require('@babel/generator').default;
|
|
21
22
|
const template = require('@babel/template').default;
|
|
22
23
|
const traverse = require('@babel/traverse').default;
|
|
@@ -37,7 +38,23 @@ export type Dependency<TSplitCondition> = $ReadOnly<{
|
|
|
37
38
|
name: string,
|
|
38
39
|
}>;
|
|
39
40
|
|
|
41
|
+
// TODO: Convert to a Flow enum
|
|
42
|
+
type ContextMode = 'sync' | 'eager' | 'lazy' | 'lazy-once';
|
|
43
|
+
|
|
44
|
+
type ContextFilter = {pattern: string, flags: string};
|
|
45
|
+
|
|
46
|
+
export type RequireContextParams = $ReadOnly<{
|
|
47
|
+
/* Should search for files recursively. Optional, default `true` when `require.context` is used */
|
|
48
|
+
recursive: boolean,
|
|
49
|
+
/* Filename filter pattern for use in `require.context`. Optional, default `.*` (any file) when `require.context` is used */
|
|
50
|
+
filter: $ReadOnly<ContextFilter>,
|
|
51
|
+
/** Mode for resolving dynamic dependencies. Defaults to `sync` */
|
|
52
|
+
mode: ContextMode,
|
|
53
|
+
}>;
|
|
54
|
+
|
|
40
55
|
type DependencyData<TSplitCondition> = $ReadOnly<{
|
|
56
|
+
// A locally unique key for this dependency within the current module.
|
|
57
|
+
key: string,
|
|
41
58
|
// If null, then the dependency is synchronous.
|
|
42
59
|
// (ex. `require('foo')`)
|
|
43
60
|
asyncType: AsyncDependencyType | null,
|
|
@@ -45,6 +62,8 @@ type DependencyData<TSplitCondition> = $ReadOnly<{
|
|
|
45
62
|
// If left unspecified, then the dependency is unconditionally split.
|
|
46
63
|
splitCondition?: TSplitCondition,
|
|
47
64
|
locs: Array<BabelSourceLocation>,
|
|
65
|
+
/** Context for requiring a collection of modules. */
|
|
66
|
+
contextParams?: RequireContextParams,
|
|
48
67
|
}>;
|
|
49
68
|
|
|
50
69
|
export type MutableInternalDependency<TSplitCondition> = {
|
|
@@ -66,6 +85,8 @@ export type State<TSplitCondition> = {
|
|
|
66
85
|
dependencyMapIdentifier: ?Identifier,
|
|
67
86
|
keepRequireNames: boolean,
|
|
68
87
|
allowOptionalDependencies: AllowOptionalDependencies,
|
|
88
|
+
/** Enable `require.context` statements which can be used to import multiple files in a directory. */
|
|
89
|
+
unstable_allowRequireContext: boolean,
|
|
69
90
|
};
|
|
70
91
|
|
|
71
92
|
export type Options<TSplitCondition = void> = $ReadOnly<{
|
|
@@ -77,6 +98,8 @@ export type Options<TSplitCondition = void> = $ReadOnly<{
|
|
|
77
98
|
allowOptionalDependencies: AllowOptionalDependencies,
|
|
78
99
|
dependencyRegistry?: ModuleDependencyRegistry<TSplitCondition>,
|
|
79
100
|
dependencyTransformer?: DependencyTransformer<TSplitCondition>,
|
|
101
|
+
/** Enable `require.context` statements which can be used to import multiple files in a directory. */
|
|
102
|
+
unstable_allowRequireContext: boolean,
|
|
80
103
|
}>;
|
|
81
104
|
|
|
82
105
|
export type CollectedDependencies<+TSplitCondition> = $ReadOnly<{
|
|
@@ -87,8 +110,8 @@ export type CollectedDependencies<+TSplitCondition> = $ReadOnly<{
|
|
|
87
110
|
|
|
88
111
|
// Registry for the dependency of a module.
|
|
89
112
|
// Defines when dependencies should be collapsed.
|
|
90
|
-
// E.g. should a module that's once required
|
|
91
|
-
// be
|
|
113
|
+
// E.g. should a module that's once required optionally and once not
|
|
114
|
+
// be treated as the same or different dependencies.
|
|
92
115
|
export interface ModuleDependencyRegistry<+TSplitCondition> {
|
|
93
116
|
registerDependency(
|
|
94
117
|
qualifier: ImportQualifier,
|
|
@@ -151,10 +174,14 @@ function collectDependencies<TSplitCondition = void>(
|
|
|
151
174
|
dynamicRequires: options.dynamicRequires,
|
|
152
175
|
keepRequireNames: options.keepRequireNames,
|
|
153
176
|
allowOptionalDependencies: options.allowOptionalDependencies,
|
|
177
|
+
unstable_allowRequireContext: options.unstable_allowRequireContext,
|
|
154
178
|
};
|
|
155
179
|
|
|
156
180
|
const visitor = {
|
|
157
|
-
CallExpression(
|
|
181
|
+
CallExpression(
|
|
182
|
+
path: NodePath<BabelNodeCallExpression>,
|
|
183
|
+
state: State<TSplitCondition>,
|
|
184
|
+
): void {
|
|
158
185
|
if (visited.has(path.node)) {
|
|
159
186
|
return;
|
|
160
187
|
}
|
|
@@ -199,6 +226,26 @@ function collectDependencies<TSplitCondition = void>(
|
|
|
199
226
|
return;
|
|
200
227
|
}
|
|
201
228
|
|
|
229
|
+
// Match `require.context`
|
|
230
|
+
if (
|
|
231
|
+
// Feature gate, defaults to `false`.
|
|
232
|
+
state.unstable_allowRequireContext &&
|
|
233
|
+
callee.type === 'MemberExpression' &&
|
|
234
|
+
// `require`
|
|
235
|
+
callee.object.type === 'Identifier' &&
|
|
236
|
+
callee.object.name === 'require' &&
|
|
237
|
+
// `context`
|
|
238
|
+
callee.property.type === 'Identifier' &&
|
|
239
|
+
callee.property.name === 'context' &&
|
|
240
|
+
!callee.computed &&
|
|
241
|
+
// Ensure `require` refers to the global and not something else.
|
|
242
|
+
!path.scope.getBinding('require')
|
|
243
|
+
) {
|
|
244
|
+
processRequireContextCall(path, state);
|
|
245
|
+
visited.add(path.node);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
202
249
|
if (
|
|
203
250
|
name != null &&
|
|
204
251
|
state.dependencyCalls.has(name) &&
|
|
@@ -213,7 +260,7 @@ function collectDependencies<TSplitCondition = void>(
|
|
|
213
260
|
ExportNamedDeclaration: collectImports,
|
|
214
261
|
ExportAllDeclaration: collectImports,
|
|
215
262
|
|
|
216
|
-
Program(path
|
|
263
|
+
Program(path: NodePath<BabelNodeProgram>, state: State<TSplitCondition>) {
|
|
217
264
|
state.asyncRequireModulePathStringLiteral = types.stringLiteral(
|
|
218
265
|
options.asyncRequireModulePath,
|
|
219
266
|
);
|
|
@@ -251,6 +298,132 @@ function collectDependencies<TSplitCondition = void>(
|
|
|
251
298
|
};
|
|
252
299
|
}
|
|
253
300
|
|
|
301
|
+
/** Extract args passed to the `require.context` method. */
|
|
302
|
+
function getRequireContextArgs(
|
|
303
|
+
path: NodePath<CallExpression>,
|
|
304
|
+
): [string, RequireContextParams] {
|
|
305
|
+
const args = path.get('arguments');
|
|
306
|
+
|
|
307
|
+
let directory: string;
|
|
308
|
+
if (!Array.isArray(args) || args.length < 1) {
|
|
309
|
+
throw new InvalidRequireCallError(path);
|
|
310
|
+
} else {
|
|
311
|
+
const result = args[0].evaluate();
|
|
312
|
+
if (result.confident && typeof result.value === 'string') {
|
|
313
|
+
directory = result.value;
|
|
314
|
+
} else {
|
|
315
|
+
throw new InvalidRequireCallError(
|
|
316
|
+
result.deopt ?? args[0],
|
|
317
|
+
'First argument of `require.context` should be a string denoting the directory to require.',
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Default to requiring through all directories.
|
|
323
|
+
let recursive: boolean = true;
|
|
324
|
+
if (args.length > 1) {
|
|
325
|
+
const result = args[1].evaluate();
|
|
326
|
+
if (result.confident && typeof result.value === 'boolean') {
|
|
327
|
+
recursive = result.value;
|
|
328
|
+
} else if (!(result.confident && typeof result.value === 'undefined')) {
|
|
329
|
+
throw new InvalidRequireCallError(
|
|
330
|
+
result.deopt ?? args[1],
|
|
331
|
+
'Second argument of `require.context` should be an optional boolean indicating if files should be imported recursively or not.',
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Default to all files.
|
|
337
|
+
let filter: ContextFilter = {pattern: '.*', flags: ''};
|
|
338
|
+
if (args.length > 2) {
|
|
339
|
+
// evaluate() to check for undefined (because it's technically a scope lookup)
|
|
340
|
+
// but check the AST for the regex literal, since evaluate() doesn't do regex.
|
|
341
|
+
const result = args[2].evaluate();
|
|
342
|
+
const argNode = args[2].node;
|
|
343
|
+
if (argNode.type === 'RegExpLiteral') {
|
|
344
|
+
// TODO: Handle `new RegExp(...)` -- `argNode.type === 'NewExpression'`
|
|
345
|
+
filter = {
|
|
346
|
+
pattern: argNode.pattern,
|
|
347
|
+
flags: argNode.flags || '',
|
|
348
|
+
};
|
|
349
|
+
} else if (!(result.confident && typeof result.value === 'undefined')) {
|
|
350
|
+
throw new InvalidRequireCallError(
|
|
351
|
+
args[2],
|
|
352
|
+
`Third argument of \`require.context\` should be an optional RegExp pattern matching all of the files to import, instead found node of type: ${argNode.type}.`,
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Default to `sync`.
|
|
358
|
+
let mode: ContextMode = 'sync';
|
|
359
|
+
if (args.length > 3) {
|
|
360
|
+
const result = args[3].evaluate();
|
|
361
|
+
if (result.confident && typeof result.value === 'string') {
|
|
362
|
+
mode = getContextMode(args[3], result.value);
|
|
363
|
+
} else if (!(result.confident && typeof result.value === 'undefined')) {
|
|
364
|
+
throw new InvalidRequireCallError(
|
|
365
|
+
result.deopt ?? args[3],
|
|
366
|
+
'Fourth argument of `require.context` should be an optional string "mode" denoting how the modules will be resolved.',
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (args.length > 4) {
|
|
372
|
+
throw new InvalidRequireCallError(
|
|
373
|
+
path,
|
|
374
|
+
`Too many arguments provided to \`require.context\` call. Expected 4, got: ${args.length}`,
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return [
|
|
379
|
+
directory,
|
|
380
|
+
{
|
|
381
|
+
recursive,
|
|
382
|
+
filter,
|
|
383
|
+
mode,
|
|
384
|
+
},
|
|
385
|
+
];
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function getContextMode(path: NodePath<>, mode: string): ContextMode {
|
|
389
|
+
if (
|
|
390
|
+
mode === 'sync' ||
|
|
391
|
+
mode === 'eager' ||
|
|
392
|
+
mode === 'lazy' ||
|
|
393
|
+
mode === 'lazy-once'
|
|
394
|
+
) {
|
|
395
|
+
return mode;
|
|
396
|
+
}
|
|
397
|
+
throw new InvalidRequireCallError(
|
|
398
|
+
path,
|
|
399
|
+
`require.context "${mode}" mode is not supported. Expected one of: sync, eager, lazy, lazy-once`,
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function processRequireContextCall<TSplitCondition>(
|
|
404
|
+
path: NodePath<CallExpression>,
|
|
405
|
+
state: State<TSplitCondition>,
|
|
406
|
+
): void {
|
|
407
|
+
const [directory, contextParams] = getRequireContextArgs(path);
|
|
408
|
+
const transformer = state.dependencyTransformer;
|
|
409
|
+
const dep = registerDependency(
|
|
410
|
+
state,
|
|
411
|
+
{
|
|
412
|
+
// We basically want to "import" every file in a folder and then filter them out with the given `filter` RegExp.
|
|
413
|
+
name: directory,
|
|
414
|
+
// Capture the matching context
|
|
415
|
+
contextParams,
|
|
416
|
+
asyncType: null,
|
|
417
|
+
optional: isOptionalDependency(directory, path, state),
|
|
418
|
+
},
|
|
419
|
+
path,
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
// require() the generated module representing this context
|
|
423
|
+
path.get('callee').replaceWith(types.identifier('require'));
|
|
424
|
+
transformer.transformSyncRequire(path, dep, state);
|
|
425
|
+
}
|
|
426
|
+
|
|
254
427
|
function collectImports<TSplitCondition>(
|
|
255
428
|
path: NodePath<>,
|
|
256
429
|
state: State<TSplitCondition>,
|
|
@@ -344,6 +517,7 @@ export type ImportQualifier = $ReadOnly<{
|
|
|
344
517
|
asyncType: AsyncDependencyType | null,
|
|
345
518
|
splitCondition?: NodePath<>,
|
|
346
519
|
optional: boolean,
|
|
520
|
+
contextParams?: RequireContextParams,
|
|
347
521
|
}>;
|
|
348
522
|
|
|
349
523
|
function registerDependency<TSplitCondition>(
|
|
@@ -352,7 +526,6 @@ function registerDependency<TSplitCondition>(
|
|
|
352
526
|
path: NodePath<>,
|
|
353
527
|
): InternalDependency<TSplitCondition> {
|
|
354
528
|
const dependency = state.dependencyRegistry.registerDependency(qualifier);
|
|
355
|
-
|
|
356
529
|
const loc = getNearestLocFromPath(path);
|
|
357
530
|
if (loc != null) {
|
|
358
531
|
dependency.locs.push(loc);
|
|
@@ -419,14 +592,20 @@ function getModuleNameFromCallArgs(path: NodePath<CallExpression>): ?string {
|
|
|
419
592
|
|
|
420
593
|
return null;
|
|
421
594
|
}
|
|
595
|
+
|
|
422
596
|
collectDependencies.getModuleNameFromCallArgs = getModuleNameFromCallArgs;
|
|
423
597
|
|
|
424
598
|
class InvalidRequireCallError extends Error {
|
|
425
|
-
constructor({node}:
|
|
599
|
+
constructor({node}: NodePath<>, message?: string) {
|
|
426
600
|
const line = node.loc && node.loc.start && node.loc.start.line;
|
|
427
601
|
|
|
428
602
|
super(
|
|
429
|
-
|
|
603
|
+
[
|
|
604
|
+
`Invalid call at line ${line || '<unknown>'}: ${generate(node).code}`,
|
|
605
|
+
message,
|
|
606
|
+
]
|
|
607
|
+
.filter(Boolean)
|
|
608
|
+
.join('\n'),
|
|
430
609
|
);
|
|
431
610
|
}
|
|
432
611
|
}
|
|
@@ -469,9 +648,11 @@ const DefaultDependencyTransformer: DependencyTransformer<mixed> = {
|
|
|
469
648
|
state: State<mixed>,
|
|
470
649
|
): void {
|
|
471
650
|
const moduleIDExpression = createModuleIDExpression(dependency, state);
|
|
472
|
-
path.node.arguments =
|
|
473
|
-
|
|
474
|
-
|
|
651
|
+
path.node.arguments = [moduleIDExpression];
|
|
652
|
+
// Always add the debug name argument last
|
|
653
|
+
if (state.keepRequireNames) {
|
|
654
|
+
path.node.arguments.push(types.stringLiteral(dependency.name));
|
|
655
|
+
}
|
|
475
656
|
},
|
|
476
657
|
|
|
477
658
|
transformImportCall(
|
|
@@ -546,6 +727,50 @@ function createModuleNameLiteral(dependency: InternalDependency<mixed>) {
|
|
|
546
727
|
return types.stringLiteral(dependency.name);
|
|
547
728
|
}
|
|
548
729
|
|
|
730
|
+
/**
|
|
731
|
+
* Given an import qualifier, return a key used to register the dependency.
|
|
732
|
+
* Generally this return the `ImportQualifier.name` property, but more
|
|
733
|
+
* attributes can be appended to distinguish various combinations that would
|
|
734
|
+
* otherwise conflict.
|
|
735
|
+
*
|
|
736
|
+
* For example, the following case would have collision issues if they all utilized the `name` property:
|
|
737
|
+
* ```
|
|
738
|
+
* require('./foo');
|
|
739
|
+
* require.context('./foo');
|
|
740
|
+
* require.context('./foo', true, /something/);
|
|
741
|
+
* require.context('./foo', false, /something/);
|
|
742
|
+
* require.context('./foo', false, /something/, 'lazy');
|
|
743
|
+
* ```
|
|
744
|
+
*
|
|
745
|
+
* This method should be utilized by `registerDependency`.
|
|
746
|
+
*/
|
|
747
|
+
function getKeyForDependency(qualifier: ImportQualifier): string {
|
|
748
|
+
let key = qualifier.name;
|
|
749
|
+
|
|
750
|
+
const {asyncType} = qualifier;
|
|
751
|
+
if (asyncType) {
|
|
752
|
+
key += ['', asyncType].join('\0');
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
const {contextParams} = qualifier;
|
|
756
|
+
// Add extra qualifiers when using `require.context` to prevent collisions.
|
|
757
|
+
if (contextParams) {
|
|
758
|
+
// NOTE(EvanBacon): Keep this synchronized with `RequireContextParams`, if any other properties are added
|
|
759
|
+
// then this key algorithm should be updated to account for those properties.
|
|
760
|
+
// Example: `./directory__true__/foobar/m__lazy`
|
|
761
|
+
key += [
|
|
762
|
+
'',
|
|
763
|
+
'context',
|
|
764
|
+
String(contextParams.recursive),
|
|
765
|
+
String(contextParams.filter.pattern),
|
|
766
|
+
String(contextParams.filter.flags),
|
|
767
|
+
contextParams.mode,
|
|
768
|
+
// Join together and append to the name:
|
|
769
|
+
].join('\0');
|
|
770
|
+
}
|
|
771
|
+
return key;
|
|
772
|
+
}
|
|
773
|
+
|
|
549
774
|
class DefaultModuleDependencyRegistry<TSplitCondition = void>
|
|
550
775
|
implements ModuleDependencyRegistry<TSplitCondition>
|
|
551
776
|
{
|
|
@@ -554,8 +779,9 @@ class DefaultModuleDependencyRegistry<TSplitCondition = void>
|
|
|
554
779
|
registerDependency(
|
|
555
780
|
qualifier: ImportQualifier,
|
|
556
781
|
): InternalDependency<TSplitCondition> {
|
|
782
|
+
const key = getKeyForDependency(qualifier);
|
|
557
783
|
let dependency: ?InternalDependency<TSplitCondition> =
|
|
558
|
-
this._dependencies.get(
|
|
784
|
+
this._dependencies.get(key);
|
|
559
785
|
|
|
560
786
|
if (dependency == null) {
|
|
561
787
|
const newDependency: MutableInternalDependency<TSplitCondition> = {
|
|
@@ -563,22 +789,30 @@ class DefaultModuleDependencyRegistry<TSplitCondition = void>
|
|
|
563
789
|
asyncType: qualifier.asyncType,
|
|
564
790
|
locs: [],
|
|
565
791
|
index: this._dependencies.size,
|
|
792
|
+
key: crypto.createHash('sha1').update(key).digest('base64'),
|
|
566
793
|
};
|
|
567
794
|
|
|
568
795
|
if (qualifier.optional) {
|
|
569
796
|
newDependency.isOptional = true;
|
|
570
797
|
}
|
|
798
|
+
if (qualifier.contextParams) {
|
|
799
|
+
newDependency.contextParams = qualifier.contextParams;
|
|
800
|
+
}
|
|
571
801
|
|
|
572
802
|
dependency = newDependency;
|
|
573
|
-
this._dependencies.set(qualifier.name, dependency);
|
|
574
803
|
} else {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
804
|
+
if (dependency.isOptional && !qualifier.optional) {
|
|
805
|
+
// A previously optionally required dependency was required non-optionally.
|
|
806
|
+
// Mark it non optional for the whole module
|
|
807
|
+
dependency = {
|
|
808
|
+
...dependency,
|
|
809
|
+
isOptional: false,
|
|
810
|
+
};
|
|
579
811
|
}
|
|
580
812
|
}
|
|
581
813
|
|
|
814
|
+
this._dependencies.set(key, dependency);
|
|
815
|
+
|
|
582
816
|
return dependency;
|
|
583
817
|
}
|
|
584
818
|
|
|
@@ -587,36 +821,4 @@ class DefaultModuleDependencyRegistry<TSplitCondition = void>
|
|
|
587
821
|
}
|
|
588
822
|
}
|
|
589
823
|
|
|
590
|
-
function collapseDependencies<TSplitCondition>(
|
|
591
|
-
dependency: InternalDependency<TSplitCondition>,
|
|
592
|
-
qualifier: ImportQualifier,
|
|
593
|
-
): InternalDependency<TSplitCondition> {
|
|
594
|
-
let collapsed = dependency;
|
|
595
|
-
|
|
596
|
-
// A previously optionally required dependency was required non-optionaly.
|
|
597
|
-
// Mark it non optional for the whole module
|
|
598
|
-
if (collapsed.isOptional && !qualifier.optional) {
|
|
599
|
-
collapsed = {
|
|
600
|
-
...dependency,
|
|
601
|
-
isOptional: false,
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
// A previously asynchronously (or prefetch) required module was required synchronously.
|
|
606
|
-
// Make the dependency sync.
|
|
607
|
-
if (collapsed.asyncType != null && qualifier.asyncType == null) {
|
|
608
|
-
collapsed = {...dependency, asyncType: null};
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// A prefetched dependency was required async in the module. Mark it as async.
|
|
612
|
-
if (collapsed.asyncType === 'prefetch' && qualifier.asyncType === 'async') {
|
|
613
|
-
collapsed = {
|
|
614
|
-
...dependency,
|
|
615
|
-
asyncType: 'async',
|
|
616
|
-
};
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
return collapsed;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
824
|
module.exports = collectDependencies;
|
package/src/Server.js
CHANGED
|
@@ -453,6 +453,8 @@ class Server {
|
|
|
453
453
|
delete: deleteFn,
|
|
454
454
|
finish,
|
|
455
455
|
}) {
|
|
456
|
+
/* $FlowFixMe[missing-this-annot] The 'this' type annotation(s) required by
|
|
457
|
+
* Flow's LTI update could not be added via codemod */
|
|
456
458
|
return async function requestProcessor(req, res, bundleOptions) {
|
|
457
459
|
const { entryFile, graphOptions, transformOptions, serializerOptions } =
|
|
458
460
|
splitBundleOptions(bundleOptions);
|
|
@@ -660,6 +662,8 @@ class Server {
|
|
|
660
662
|
|
|
661
663
|
const serializer =
|
|
662
664
|
this._config.serializer.customSerializer ||
|
|
665
|
+
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by
|
|
666
|
+
* Flow's LTI update could not be added via codemod */
|
|
663
667
|
((...args) => bundleToString(baseJSBundle(...args)).code);
|
|
664
668
|
|
|
665
669
|
const bundle = await serializer(
|
package/src/Server.js.flow
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
12
|
+
|
|
13
|
+
import type {StackFrameOutput} from './Server/symbolicate';
|
|
12
14
|
import type {AssetData} from './Assets';
|
|
13
15
|
import type {ExplodedSourceMap} from './DeltaBundler/Serializers/getExplodedSourceMap';
|
|
14
16
|
import type {RamBundleInfo} from './DeltaBundler/Serializers/getRamBundleInfo';
|
|
@@ -513,6 +515,8 @@ class Server {
|
|
|
513
515
|
+delete?: (context: ProcessDeleteContext) => Promise<void>,
|
|
514
516
|
+finish: (context: ProcessEndContext<T>) => void,
|
|
515
517
|
}) {
|
|
518
|
+
/* $FlowFixMe[missing-this-annot] The 'this' type annotation(s) required by
|
|
519
|
+
* Flow's LTI update could not be added via codemod */
|
|
516
520
|
return async function requestProcessor(
|
|
517
521
|
req: IncomingMessage,
|
|
518
522
|
res: ServerResponse,
|
|
@@ -733,6 +737,8 @@ class Server {
|
|
|
733
737
|
|
|
734
738
|
const serializer =
|
|
735
739
|
this._config.serializer.customSerializer ||
|
|
740
|
+
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by
|
|
741
|
+
* Flow's LTI update could not be added via codemod */
|
|
736
742
|
((...args) => bundleToString(baseJSBundle(...args)).code);
|
|
737
743
|
|
|
738
744
|
const bundle = await serializer(
|
|
@@ -1011,7 +1017,10 @@ class Server {
|
|
|
1011
1017
|
});
|
|
1012
1018
|
|
|
1013
1019
|
async _symbolicate(req: IncomingMessage, res: ServerResponse) {
|
|
1014
|
-
const getCodeFrame = (
|
|
1020
|
+
const getCodeFrame = (
|
|
1021
|
+
urls: Set<string>,
|
|
1022
|
+
symbolicatedStack: $ReadOnlyArray<StackFrameOutput>,
|
|
1023
|
+
) => {
|
|
1015
1024
|
for (let i = 0; i < symbolicatedStack.length; i++) {
|
|
1016
1025
|
const {collapse, column, file, lineNumber} = symbolicatedStack[i];
|
|
1017
1026
|
const fileAbsolute = path.resolve(this._config.projectRoot, file ?? '');
|
|
@@ -1161,7 +1170,7 @@ class Server {
|
|
|
1161
1170
|
}
|
|
1162
1171
|
|
|
1163
1172
|
async _resolveRelativePath(
|
|
1164
|
-
filePath,
|
|
1173
|
+
filePath: string,
|
|
1165
1174
|
{
|
|
1166
1175
|
transformOptions,
|
|
1167
1176
|
relativeTo,
|
package/src/cli-utils.js.flow
CHANGED
|
@@ -27,7 +27,7 @@ exports.watchFile = async function (
|
|
|
27
27
|
|
|
28
28
|
exports.makeAsyncCommand =
|
|
29
29
|
(
|
|
30
|
-
command: (argv: YargArguments) => Promise<
|
|
30
|
+
command: (argv: YargArguments) => Promise<void>,
|
|
31
31
|
): ((argv: YargArguments) => void) =>
|
|
32
32
|
(argv: YargArguments) => {
|
|
33
33
|
Promise.resolve(command(argv)).catch(error => {
|
package/src/commands/build.js
CHANGED
|
@@ -22,8 +22,7 @@ const updateReporter = new TerminalReporter(term);
|
|
|
22
22
|
|
|
23
23
|
module.exports = () => ({
|
|
24
24
|
command: "build <entry>",
|
|
25
|
-
|
|
26
|
-
"Generates a JavaScript bundle containing the specified entrypoint and its descendants",
|
|
25
|
+
desc: "Generates a JavaScript bundle containing the specified entrypoint and its descendants",
|
|
27
26
|
builder: (yargs) => {
|
|
28
27
|
yargs.option("project-roots", {
|
|
29
28
|
alias: "P",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import type {RunBuildOptions} from '../index';
|
|
14
14
|
import type {YargArguments} from 'metro-config/src/configTypes.flow';
|
|
15
15
|
import typeof Yargs from 'yargs';
|
|
16
|
+
import type {ModuleObject} from 'yargs';
|
|
16
17
|
|
|
17
18
|
const {makeAsyncCommand} = require('../cli-utils');
|
|
18
19
|
const TerminalReporter = require('../lib/TerminalReporter');
|
|
@@ -22,16 +23,12 @@ const {Terminal} = require('metro-core');
|
|
|
22
23
|
const term = new Terminal(process.stdout);
|
|
23
24
|
const updateReporter = new TerminalReporter(term);
|
|
24
25
|
|
|
25
|
-
module.exports = ():
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
handler: (argv: YargArguments) => void,
|
|
30
|
-
}) => ({
|
|
26
|
+
module.exports = (): {
|
|
27
|
+
...ModuleObject,
|
|
28
|
+
handler: Function,
|
|
29
|
+
} => ({
|
|
31
30
|
command: 'build <entry>',
|
|
32
|
-
|
|
33
|
-
description:
|
|
34
|
-
'Generates a JavaScript bundle containing the specified entrypoint and its descendants',
|
|
31
|
+
desc: 'Generates a JavaScript bundle containing the specified entrypoint and its descendants',
|
|
35
32
|
|
|
36
33
|
builder: (yargs: Yargs): void => {
|
|
37
34
|
yargs.option('project-roots', {
|
package/src/commands/serve.js
CHANGED
|
@@ -17,7 +17,8 @@ const { promisify } = require("util");
|
|
|
17
17
|
|
|
18
18
|
module.exports = () => ({
|
|
19
19
|
command: "serve",
|
|
20
|
-
|
|
20
|
+
aliases: ["start"],
|
|
21
|
+
desc: "Starts Metro on the given port, building bundles on the fly",
|
|
21
22
|
builder: (yargs) => {
|
|
22
23
|
yargs.option("project-roots", {
|
|
23
24
|
alias: "P",
|
|
@@ -13,20 +13,19 @@
|
|
|
13
13
|
import type {RunServerOptions} from '../index';
|
|
14
14
|
import type {YargArguments} from 'metro-config/src/configTypes.flow';
|
|
15
15
|
import typeof Yargs from 'yargs';
|
|
16
|
+
import type {ModuleObject} from 'yargs';
|
|
16
17
|
|
|
17
18
|
const {makeAsyncCommand, watchFile} = require('../cli-utils');
|
|
18
19
|
const {loadConfig, resolveConfig} = require('metro-config');
|
|
19
20
|
const {promisify} = require('util');
|
|
20
21
|
|
|
21
|
-
module.exports = ():
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
handler: (argv: YargArguments) => void,
|
|
26
|
-
}) => ({
|
|
22
|
+
module.exports = (): {
|
|
23
|
+
...ModuleObject,
|
|
24
|
+
handler: Function,
|
|
25
|
+
} => ({
|
|
27
26
|
command: 'serve',
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
aliases: ['start'],
|
|
28
|
+
desc: 'Starts Metro on the given port, building bundles on the fly',
|
|
30
29
|
|
|
31
30
|
builder: (yargs: Yargs): void => {
|
|
32
31
|
yargs.option('project-roots', {
|
package/src/index.flow.js
CHANGED
|
@@ -355,22 +355,25 @@ exports.buildGraph = async function (
|
|
|
355
355
|
|
|
356
356
|
exports.attachMetroCli = function (
|
|
357
357
|
yargs,
|
|
358
|
-
|
|
358
|
+
// $FlowFixMe[prop-missing]
|
|
359
|
+
{
|
|
360
|
+
build = {},
|
|
361
|
+
serve = {},
|
|
362
|
+
dependencies = {}
|
|
363
|
+
} = {} // prettier-ignore
|
|
359
364
|
) {
|
|
365
|
+
yargs.strict();
|
|
366
|
+
|
|
360
367
|
if (build) {
|
|
361
|
-
|
|
362
|
-
yargs.command(command, description, builder, handler);
|
|
368
|
+
yargs.command(makeBuildCommand());
|
|
363
369
|
}
|
|
364
370
|
|
|
365
371
|
if (serve) {
|
|
366
|
-
|
|
367
|
-
yargs.command(command, description, builder, handler);
|
|
372
|
+
yargs.command(makeServeCommand());
|
|
368
373
|
}
|
|
369
374
|
|
|
370
375
|
if (dependencies) {
|
|
371
|
-
|
|
372
|
-
makeDependenciesCommand();
|
|
373
|
-
yargs.command(command, description, builder, handler);
|
|
376
|
+
yargs.command(makeDependenciesCommand());
|
|
374
377
|
}
|
|
375
378
|
|
|
376
379
|
return yargs;
|
package/src/index.flow.js.flow
CHANGED
|
@@ -448,20 +448,23 @@ exports.attachMetroCli = function (
|
|
|
448
448
|
serve: ServeCommandOptions,
|
|
449
449
|
dependencies: any,
|
|
450
450
|
...
|
|
451
|
-
}
|
|
451
|
+
}
|
|
452
|
+
// prettier-ignore
|
|
453
|
+
// $FlowFixMe[prop-missing]
|
|
454
|
+
= {},
|
|
452
455
|
): Yargs {
|
|
456
|
+
yargs.strict();
|
|
457
|
+
|
|
453
458
|
if (build) {
|
|
454
|
-
|
|
455
|
-
yargs.command(command, description, builder, handler);
|
|
459
|
+
yargs.command(makeBuildCommand());
|
|
456
460
|
}
|
|
457
461
|
if (serve) {
|
|
458
|
-
|
|
459
|
-
yargs.command(command, description, builder, handler);
|
|
462
|
+
yargs.command(makeServeCommand());
|
|
460
463
|
}
|
|
461
464
|
if (dependencies) {
|
|
462
|
-
|
|
463
|
-
yargs.command(command, description, builder, handler);
|
|
465
|
+
yargs.command(makeDependenciesCommand());
|
|
464
466
|
}
|
|
467
|
+
|
|
465
468
|
return yargs;
|
|
466
469
|
};
|
|
467
470
|
|