metro 0.84.3 → 0.85.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.
Files changed (56) hide show
  1. package/package.json +17 -18
  2. package/src/Assets.js +23 -14
  3. package/src/Assets.js.flow +51 -38
  4. package/src/Bundler.d.ts +1 -5
  5. package/src/DeltaBundler/DeltaCalculator.d.ts +1 -16
  6. package/src/DeltaBundler/DeltaCalculator.js.flow +1 -1
  7. package/src/DeltaBundler/Graph.d.ts +1 -102
  8. package/src/DeltaBundler/Graph.js.flow +7 -7
  9. package/src/DeltaBundler/Serializers/getAllFiles.js.flow +1 -1
  10. package/src/DeltaBundler/Serializers/getAssets.js.flow +1 -1
  11. package/src/DeltaBundler/Serializers/getExplodedSourceMap.js.flow +5 -5
  12. package/src/DeltaBundler/Serializers/helpers/getSourceMapInfo.js.flow +9 -9
  13. package/src/DeltaBundler/Serializers/hmrJSBundle.js.flow +3 -3
  14. package/src/DeltaBundler/Transformer.d.ts +2 -10
  15. package/src/DeltaBundler/Worker.flow.js.flow +1 -1
  16. package/src/DeltaBundler/WorkerFarm.d.ts +2 -47
  17. package/src/DeltaBundler/getTransformCacheKey.js.flow +3 -3
  18. package/src/DeltaBundler/types.js.flow +10 -10
  19. package/src/DeltaBundler.d.ts +1 -5
  20. package/src/HmrServer.d.ts +2 -45
  21. package/src/HmrServer.js.flow +10 -10
  22. package/src/IncrementalBundler.d.ts +1 -9
  23. package/src/IncrementalBundler.js.flow +9 -6
  24. package/src/ModuleGraph/worker/collectDependencies.d.ts +1 -2
  25. package/src/ModuleGraph/worker/collectDependencies.js +52 -0
  26. package/src/ModuleGraph/worker/collectDependencies.js.flow +67 -0
  27. package/src/Server/symbolicate.js.flow +13 -13
  28. package/src/Server.d.ts +3 -176
  29. package/src/Server.js +42 -5
  30. package/src/Server.js.flow +70 -28
  31. package/src/index.flow.js +2 -2
  32. package/src/index.flow.js.flow +2 -2
  33. package/src/lib/BatchProcessor.d.ts +1 -21
  34. package/src/lib/CountingSet.js.flow +1 -1
  35. package/src/lib/JsonReporter.d.ts +1 -2
  36. package/src/lib/JsonReporter.js.flow +4 -2
  37. package/src/lib/RamBundleParser.d.ts +1 -6
  38. package/src/lib/TerminalReporter.d.ts +2 -78
  39. package/src/lib/TerminalReporter.js +39 -41
  40. package/src/lib/TerminalReporter.js.flow +52 -33
  41. package/src/lib/bundleToString.js.flow +2 -2
  42. package/src/lib/createWebsocketServer.js.flow +4 -4
  43. package/src/lib/formatBundlingError.js.flow +1 -1
  44. package/src/lib/getPreludeCode.js.flow +5 -5
  45. package/src/lib/logToConsole.js +8 -7
  46. package/src/lib/logToConsole.js.flow +7 -7
  47. package/src/lib/reporting.js +16 -7
  48. package/src/lib/reporting.js.flow +16 -5
  49. package/src/node-haste/DependencyGraph/ModuleResolution.d.ts +1 -13
  50. package/src/node-haste/DependencyGraph/ModuleResolution.js.flow +1 -1
  51. package/src/node-haste/DependencyGraph/createFileMap.js +0 -2
  52. package/src/node-haste/DependencyGraph/createFileMap.js.flow +0 -2
  53. package/src/node-haste/DependencyGraph.d.ts +1 -30
  54. package/src/node-haste/DependencyGraph.js.flow +2 -2
  55. package/src/shared/output/RamBundle/util.js.flow +4 -2
  56. package/src/shared/types.js.flow +31 -31
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @noformat
8
8
  * @oncall react_native
9
- * @generated SignedSource<<bbd52f1dc5e4a9253455034b585115ac>>
9
+ * @generated SignedSource<<d9d13bcad23924cbcf706b93e621e91c>>
10
10
  *
11
11
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
12
  * Original file: packages/metro/src/DeltaBundler/WorkerFarm.js
@@ -16,29 +16,11 @@
16
16
  */
17
17
 
18
18
  import type {TransformResult} from '../DeltaBundler';
19
- import type {TransformerConfig, TransformOptions, Worker} from './Worker';
19
+ import type {TransformerConfig, TransformOptions} from './Worker';
20
20
  import type {ConfigT} from 'metro-config';
21
- import type {Readable} from 'stream';
22
21
 
23
- type WorkerInterface = Readonly<
24
- Omit<
25
- Worker,
26
- keyof {
27
- end(): void | Promise<void>;
28
- getStdout(): Readable;
29
- getStderr(): Readable;
30
- }
31
- > & {
32
- end(): void | Promise<void>;
33
- getStdout(): Readable;
34
- getStderr(): Readable;
35
- }
36
- >;
37
22
  type TransformerResult = Readonly<{result: TransformResult; sha1: string}>;
38
23
  declare class WorkerFarm {
39
- _config: ConfigT;
40
- _transformerConfig: TransformerConfig;
41
- _worker: WorkerInterface | Worker;
42
24
  constructor(config: ConfigT, transformerConfig: TransformerConfig);
43
25
  kill(): Promise<void>;
44
26
  transform(
@@ -46,32 +28,5 @@ declare class WorkerFarm {
46
28
  options: TransformOptions,
47
29
  fileBuffer?: Buffer,
48
30
  ): Promise<TransformerResult>;
49
- _makeFarm(
50
- absoluteWorkerPath: string,
51
- exposedMethods: ReadonlyArray<string>,
52
- numWorkers: number,
53
- ): WorkerInterface;
54
- _computeWorkerKey(
55
- method: string,
56
- filename: string,
57
- ): null | undefined | string;
58
- _formatGenericError(
59
- err: Readonly<{message: string; stack?: string}>,
60
- filename: string,
61
- ): TransformError;
62
- _formatBabelError(
63
- err: Readonly<{
64
- message: string;
65
- stack?: string;
66
- type?: string;
67
- codeFrame?: unknown;
68
- loc: {line?: number; column?: number};
69
- }>,
70
- filename: string,
71
- ): TransformError;
72
31
  }
73
32
  export default WorkerFarm;
74
- declare class TransformError extends SyntaxError {
75
- type: string;
76
- constructor(message: string);
77
- }
@@ -26,9 +26,9 @@ type CacheKeyProvider = {
26
26
  };
27
27
 
28
28
  export default function getTransformCacheKey(opts: {
29
- +cacheVersion: string,
30
- +projectRoot: string,
31
- +transformerConfig: TransformerConfig,
29
+ readonly cacheVersion: string,
30
+ readonly projectRoot: string,
31
+ readonly transformerConfig: TransformerConfig,
32
32
  }): string {
33
33
  const {transformerPath, transformerConfig} = opts.transformerConfig;
34
34
 
@@ -18,8 +18,8 @@ import type {JsTransformOptions} from 'metro-transform-worker';
18
18
  import CountingSet from '../lib/CountingSet';
19
19
 
20
20
  export type MixedOutput = {
21
- +data: unknown,
22
- +type: string,
21
+ readonly data: unknown,
22
+ readonly type: string,
23
23
  };
24
24
 
25
25
  export type AsyncDependencyType = 'async' | 'maybeSync' | 'prefetch' | 'weak';
@@ -106,10 +106,10 @@ export type GraphInputOptions = Readonly<{
106
106
  }>;
107
107
 
108
108
  export interface ReadOnlyGraph<T = MixedOutput> {
109
- +entryPoints: ReadonlySet<string>;
109
+ readonly entryPoints: ReadonlySet<string>;
110
110
  // Unused in core but useful for custom serializers / experimentalSerializerHook
111
- +transformOptions: Readonly<TransformInputOptions>;
112
- +dependencies: ReadOnlyDependencies<T>;
111
+ readonly transformOptions: Readonly<TransformInputOptions>;
112
+ readonly dependencies: ReadOnlyDependencies<T>;
113
113
  }
114
114
 
115
115
  export type {Graph};
@@ -136,7 +136,7 @@ export type ResolveFn = (
136
136
  ) => BundlerResolution;
137
137
 
138
138
  export type AllowOptionalDependenciesWithOptions = {
139
- +exclude: Array<string>,
139
+ readonly exclude: Array<string>,
140
140
  };
141
141
  export type AllowOptionalDependencies =
142
142
  | boolean
@@ -160,10 +160,10 @@ export type Options<T = MixedOutput> = Readonly<{
160
160
  }>;
161
161
 
162
162
  export type DeltaResult<T = MixedOutput> = {
163
- +added: Map<string, Module<T>>,
164
- +modified: Map<string, Module<T>>,
165
- +deleted: Set<string>,
166
- +reset: boolean,
163
+ readonly added: Map<string, Module<T>>,
164
+ readonly modified: Map<string, Module<T>>,
165
+ readonly deleted: Set<string>,
166
+ readonly reset: boolean,
167
167
  };
168
168
 
169
169
  export type SerializerOptions = Readonly<{
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @noformat
8
8
  * @oncall react_native
9
- * @generated SignedSource<<db564db653a99b07f3ad7585b2bed707>>
9
+ * @generated SignedSource<<4392a52adb92ee60889197cf5c38516d>>
10
10
  *
11
11
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
12
  * Original file: packages/metro/src/DeltaBundler.js
@@ -24,8 +24,6 @@ import type {
24
24
  } from './DeltaBundler/types';
25
25
  import type EventEmitter from 'events';
26
26
 
27
- import DeltaCalculator from './DeltaBundler/DeltaCalculator';
28
-
29
27
  export type {
30
28
  DeltaResult,
31
29
  Graph,
@@ -45,8 +43,6 @@ export type {
45
43
  * `clientId` param (which maps a client to a specific delta transformer).
46
44
  */
47
45
  declare class DeltaBundler<T = MixedOutput> {
48
- _changeEventSource: EventEmitter;
49
- _deltaCalculators: Map<Graph<T>, DeltaCalculator<T>>;
50
46
  constructor(changeEventSource: EventEmitter);
51
47
  end(): void;
52
48
  getDependencies(
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  * @noformat
8
- * @generated SignedSource<<ab4c245134631e14db114a9d49da79d1>>
8
+ * @generated SignedSource<<48bfe42125bd22a8329f95a30fa90b64>>
9
9
  *
10
10
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
11
11
  * Original file: packages/metro/src/HmrServer.js
@@ -18,25 +18,13 @@ import type {
18
18
  RevisionId,
19
19
  default as IncrementalBundler,
20
20
  } from './IncrementalBundler';
21
- import type {GraphOptions} from './shared/types';
22
- import type {ConfigT, RootPerfLogger} from 'metro-config';
23
- import type {
24
- HmrErrorMessage,
25
- HmrUpdateMessage,
26
- } from 'metro-runtime/src/modules/types';
21
+ import type {ConfigT} from 'metro-config';
27
22
 
28
23
  export type Client = {
29
24
  optedIntoHMR: boolean;
30
25
  revisionIds: Array<RevisionId>;
31
26
  readonly sendFn: ($$PARAM_0$$: string) => void;
32
27
  };
33
- type ClientGroup = {
34
- readonly clients: Set<Client>;
35
- clientUrl: URL;
36
- revisionId: RevisionId;
37
- readonly unlisten: () => void;
38
- readonly graphOptions: GraphOptions;
39
- };
40
28
  /**
41
29
  * The HmrServer (Hot Module Reloading) implements a lightweight interface
42
30
  * to communicate easily to the logic in the React Native repository (which
@@ -47,10 +35,6 @@ type ClientGroup = {
47
35
  * `onClientConnect`, `onClientDisconnect` and `onClientError` methods).
48
36
  */
49
37
  declare class HmrServer<TClient extends Client> {
50
- _config: ConfigT;
51
- _bundler: IncrementalBundler;
52
- _createModuleId: (path: string) => number;
53
- _clientGroups: Map<RevisionId, ClientGroup>;
54
38
  constructor(
55
39
  bundler: IncrementalBundler,
56
40
  createModuleId: (path: string) => number,
@@ -60,11 +44,6 @@ declare class HmrServer<TClient extends Client> {
60
44
  requestUrl: string,
61
45
  sendFn: (data: string) => void,
62
46
  ) => Promise<Client>;
63
- _registerEntryPoint(
64
- client: Client,
65
- originalRequestUrl: string,
66
- sendFn: (data: string) => void,
67
- ): Promise<void>;
68
47
  onClientMessage: (
69
48
  client: TClient,
70
49
  message: string | Buffer | ArrayBuffer | Array<Buffer>,
@@ -72,27 +51,5 @@ declare class HmrServer<TClient extends Client> {
72
51
  ) => Promise<void>;
73
52
  onClientError: (client: TClient, e: Error) => void;
74
53
  onClientDisconnect: (client: TClient) => void;
75
- _handleFileChange(
76
- group: ClientGroup,
77
- options: {isInitialUpdate: boolean},
78
- changeEvent:
79
- | null
80
- | undefined
81
- | {
82
- readonly logger: null | undefined | RootPerfLogger;
83
- readonly changeId?: string;
84
- },
85
- ): Promise<void>;
86
- _prepareMessage(
87
- group: ClientGroup,
88
- options: {isInitialUpdate: boolean},
89
- changeEvent:
90
- | null
91
- | undefined
92
- | {
93
- readonly logger: null | undefined | RootPerfLogger;
94
- readonly changeId?: string;
95
- },
96
- ): Promise<HmrUpdateMessage | HmrErrorMessage>;
97
54
  }
98
55
  export default HmrServer;
@@ -41,15 +41,15 @@ const {createActionStartEntry, createActionEndEntry, log} = Logger;
41
41
  export type Client = {
42
42
  optedIntoHMR: boolean,
43
43
  revisionIds: Array<RevisionId>,
44
- +sendFn: string => void,
44
+ readonly sendFn: string => void,
45
45
  };
46
46
 
47
47
  type ClientGroup = {
48
- +clients: Set<Client>,
48
+ readonly clients: Set<Client>,
49
49
  clientUrl: URL,
50
50
  revisionId: RevisionId,
51
- +unlisten: () => void,
52
- +graphOptions: GraphOptions,
51
+ readonly unlisten: () => void,
52
+ readonly graphOptions: GraphOptions,
53
53
  };
54
54
 
55
55
  function send(sendFns: Array<(string) => void>, message: HmrMessage): void {
@@ -181,8 +181,8 @@ export default class HmrServer<TClient extends Client> {
181
181
  this._clientGroups.set(id, clientGroup);
182
182
 
183
183
  let latestChangeEvent: ?{
184
- +logger: ?RootPerfLogger,
185
- +changeId: string,
184
+ readonly logger: ?RootPerfLogger,
185
+ readonly changeId: string,
186
186
  } = null;
187
187
 
188
188
  const debounceCallHandleFileChange = debounceAsyncQueue(async () => {
@@ -278,8 +278,8 @@ export default class HmrServer<TClient extends Client> {
278
278
  group: ClientGroup,
279
279
  options: {isInitialUpdate: boolean},
280
280
  changeEvent: ?{
281
- +logger: ?RootPerfLogger,
282
- +changeId?: string,
281
+ readonly logger: ?RootPerfLogger,
282
+ readonly changeId?: string,
283
283
  },
284
284
  ): Promise<void> {
285
285
  const logger = !options.isInitialUpdate ? changeEvent?.logger : null;
@@ -337,8 +337,8 @@ export default class HmrServer<TClient extends Client> {
337
337
  group: ClientGroup,
338
338
  options: {isInitialUpdate: boolean},
339
339
  changeEvent: ?{
340
- +logger: ?RootPerfLogger,
341
- +changeId?: string,
340
+ readonly logger: ?RootPerfLogger,
341
+ readonly changeId?: string,
342
342
  },
343
343
  ): Promise<HmrUpdateMessage | HmrErrorMessage> {
344
344
  const logger = !options.isInitialUpdate ? changeEvent?.logger : null;
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @noformat
8
8
  * @oncall react_native
9
- * @generated SignedSource<<0ec72971869a882d97b381e3f1baa922>>
9
+ * @generated SignedSource<<7ce634e158aa8f2ac74e32940e9e97c1>>
10
10
  *
11
11
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
12
12
  * Original file: packages/metro/src/IncrementalBundler.js
@@ -47,11 +47,6 @@ export type IncrementalBundlerOptions = Readonly<{
47
47
  watch?: boolean;
48
48
  }>;
49
49
  declare class IncrementalBundler {
50
- _config: ConfigT;
51
- _bundler: Bundler;
52
- _deltaBundler: DeltaBundler;
53
- _revisionsById: Map<RevisionId, Promise<GraphRevision>>;
54
- _revisionsByGraphId: Map<GraphId, Promise<GraphRevision>>;
55
50
  static revisionIdFromString: (str: string) => RevisionId;
56
51
  constructor(config: ConfigT, options?: IncrementalBundlerOptions);
57
52
  end(): Promise<void>;
@@ -95,9 +90,6 @@ declare class IncrementalBundler {
95
90
  reset: boolean,
96
91
  ): Promise<{delta: DeltaResult; revision: GraphRevision}>;
97
92
  endGraph(graphId: GraphId): Promise<void>;
98
- _getAbsoluteEntryFiles(
99
- entryFiles: ReadonlyArray<string>,
100
- ): Promise<ReadonlyArray<string>>;
101
93
  ready(): Promise<void>;
102
94
  }
103
95
  export default IncrementalBundler;
@@ -41,11 +41,11 @@ type OtherOptions = Readonly<{
41
41
 
42
42
  export type GraphRevision = {
43
43
  // Identifies the last computed revision.
44
- +id: RevisionId,
45
- +date: Date,
46
- +graphId: GraphId,
47
- +graph: OutputGraph,
48
- +prepend: ReadonlyArray<Module<>>,
44
+ readonly id: RevisionId,
45
+ readonly date: Date,
46
+ readonly graphId: GraphId,
47
+ readonly graph: OutputGraph,
48
+ readonly prepend: ReadonlyArray<Module<>>,
49
49
  };
50
50
 
51
51
  export type IncrementalBundlerOptions = Readonly<{
@@ -199,7 +199,10 @@ export default class IncrementalBundler {
199
199
  shallow: false,
200
200
  lazy: false,
201
201
  },
202
- ): Promise<{+graph: OutputGraph, +prepend: ReadonlyArray<Module<>>}> {
202
+ ): Promise<{
203
+ readonly graph: OutputGraph,
204
+ readonly prepend: ReadonlyArray<Module<>>,
205
+ }> {
203
206
  const graph = await this.buildGraphForEntries(
204
207
  [entryFile],
205
208
  transformOptions,
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  * @noformat
8
- * @generated SignedSource<<ab2d1203f736c3032c6b9d15cc74680b>>
8
+ * @generated SignedSource<<f072a86187014259ece27c02d9abfd6a>>
9
9
  *
10
10
  * This file was translated from Flow by scripts/generateTypeScriptDefinitions.js
11
11
  * Original file: packages/metro/src/ModuleGraph/worker/collectDependencies.js
@@ -132,7 +132,6 @@ export type ImportQualifier = Readonly<{
132
132
  contextParams?: RequireContextParams;
133
133
  }>;
134
134
  declare class DependencyRegistry {
135
- _dependencies: Map<string, InternalDependency>;
136
135
  registerDependency(qualifier: ImportQualifier): InternalDependency;
137
136
  getDependencies(): Array<InternalDependency>;
138
137
  }
@@ -405,6 +405,9 @@ function isOptionalDependency(name, path, state) {
405
405
  if (!allowOptionalDependencies || isExcluded()) {
406
406
  return false;
407
407
  }
408
+ if (isInPromiseChainWithRejectionHandler(path)) {
409
+ return true;
410
+ }
408
411
  let sCount = 0;
409
412
  let p = path;
410
413
  while (p && sCount < 3) {
@@ -422,6 +425,55 @@ function isOptionalDependency(name, path, state) {
422
425
  }
423
426
  return false;
424
427
  }
428
+ function isInPromiseChainWithRejectionHandler(path) {
429
+ let current = path;
430
+ while (current.parentPath != null) {
431
+ const member = current.parentPath;
432
+ if (
433
+ member.node.type !== "MemberExpression" ||
434
+ member.node.object !== current.node ||
435
+ member.node.computed ||
436
+ member.node.property.type !== "Identifier" ||
437
+ member.parentPath == null
438
+ ) {
439
+ return false;
440
+ }
441
+ const call = member.parentPath;
442
+ if (
443
+ call.node.type !== "CallExpression" ||
444
+ call.node.callee !== member.node
445
+ ) {
446
+ return false;
447
+ }
448
+ const propertyName = member.node.property.name;
449
+ const args = call.node.arguments;
450
+ if (
451
+ propertyName === "catch" &&
452
+ args.length >= 1 &&
453
+ isNonNullishCallbackArg(args[0])
454
+ ) {
455
+ return true;
456
+ }
457
+ if (
458
+ propertyName === "then" &&
459
+ args.length >= 2 &&
460
+ isNonNullishCallbackArg(args[1])
461
+ ) {
462
+ return true;
463
+ }
464
+ current = call;
465
+ }
466
+ return false;
467
+ }
468
+ function isNonNullishCallbackArg(arg) {
469
+ if (arg.type === "NullLiteral") {
470
+ return false;
471
+ }
472
+ if (arg.type === "Identifier" && arg.name === "undefined") {
473
+ return false;
474
+ }
475
+ return true;
476
+ }
425
477
  function getModuleNameFromCallArgs(path) {
426
478
  const args = path.get("arguments");
427
479
  if (!Array.isArray(args) || args.length !== 1) {
@@ -630,6 +630,15 @@ function isOptionalDependency(
630
630
  return false;
631
631
  }
632
632
 
633
+ // Treat dynamic imports as optional when a rejection handler is attached
634
+ // close to the import call, e.g.
635
+ // import('x').catch(handler)
636
+ // import('x').then(handler, onReject)
637
+ // import('x').then(...).catch(handler)
638
+ if (isInPromiseChainWithRejectionHandler(path)) {
639
+ return true;
640
+ }
641
+
633
642
  // Valid statement stack for single-level try-block: expressionStatement -> blockStatement -> tryStatement
634
643
  let sCount = 0;
635
644
  let p: ?(NodePath<> | NodePath<BabelNode>) = path;
@@ -652,6 +661,64 @@ function isOptionalDependency(
652
661
  return false;
653
662
  }
654
663
 
664
+ // Walk up a chain of `.then(...)` / `.catch(...)` member calls starting from
665
+ // `path` (typically an `import()` CallExpression) and return true if any
666
+ // chained call provides a rejection handler — either `.catch(handler)` or
667
+ // `.then(_, handler)`. The chain must be unbroken: as soon as the parent is
668
+ // not a member call applied to the previous expression, we stop. This keeps
669
+ // the heuristic local to the import, matching the behaviour of the
670
+ // try/catch heuristic above.
671
+ function isInPromiseChainWithRejectionHandler(path: NodePath<>): boolean {
672
+ let current: NodePath<> = path;
673
+ while (current.parentPath != null) {
674
+ const member = current.parentPath;
675
+ if (
676
+ member.node.type !== 'MemberExpression' ||
677
+ member.node.object !== current.node ||
678
+ member.node.computed ||
679
+ member.node.property.type !== 'Identifier' ||
680
+ member.parentPath == null
681
+ ) {
682
+ return false;
683
+ }
684
+ const call = member.parentPath;
685
+ if (
686
+ call.node.type !== 'CallExpression' ||
687
+ call.node.callee !== member.node
688
+ ) {
689
+ return false;
690
+ }
691
+ const propertyName = member.node.property.name;
692
+ const args = call.node.arguments;
693
+ if (
694
+ propertyName === 'catch' &&
695
+ args.length >= 1 &&
696
+ isNonNullishCallbackArg(args[0])
697
+ ) {
698
+ return true;
699
+ }
700
+ if (
701
+ propertyName === 'then' &&
702
+ args.length >= 2 &&
703
+ isNonNullishCallbackArg(args[1])
704
+ ) {
705
+ return true;
706
+ }
707
+ current = call;
708
+ }
709
+ return false;
710
+ }
711
+
712
+ function isNonNullishCallbackArg(arg: BabelNode): boolean {
713
+ if (arg.type === 'NullLiteral') {
714
+ return false;
715
+ }
716
+ if (arg.type === 'Identifier' && arg.name === 'undefined') {
717
+ return false;
718
+ }
719
+ return true;
720
+ }
721
+
655
722
  function getModuleNameFromCallArgs(path: NodePath<CallExpression>): ?string {
656
723
  const args = path.get('arguments');
657
724
  if (!Array.isArray(args) || args.length !== 1) {
@@ -20,10 +20,10 @@ import {greatestLowerBound} from 'metro-source-map/private/Consumer/search';
20
20
  import {SourceMetadataMapConsumer} from 'metro-symbolicate/private/Symbolication';
21
21
 
22
22
  export type StackFrameInput = {
23
- +file: ?string,
24
- +lineNumber: ?number,
25
- +column: ?number,
26
- +methodName: ?string,
23
+ readonly file: ?string,
24
+ readonly lineNumber: ?number,
25
+ readonly column: ?number,
26
+ readonly methodName: ?string,
27
27
  ...
28
28
  };
29
29
  export type IntermediateStackFrame = {
@@ -33,7 +33,7 @@ export type IntermediateStackFrame = {
33
33
  };
34
34
  export type StackFrameOutput = Readonly<IntermediateStackFrame>;
35
35
  type ExplodedSourceMapModule = ExplodedSourceMap[number];
36
- type Position = {+line1Based: number, column0Based: number};
36
+ type Position = {readonly line1Based: number, column0Based: number};
37
37
 
38
38
  function createFunctionNameGetter(
39
39
  module: ExplodedSourceMapModule,
@@ -68,10 +68,10 @@ export default async function symbolicate(
68
68
  }
69
69
  const functionNameGetters = new Map<
70
70
  {
71
- +firstLine1Based: number,
72
- +functionMap: ?FBSourceFunctionMap,
73
- +map: Array<MetroSourceMapSegmentTuple>,
74
- +path: string,
71
+ readonly firstLine1Based: number,
72
+ readonly functionMap: ?FBSourceFunctionMap,
73
+ readonly map: Array<MetroSourceMapSegmentTuple>,
74
+ readonly path: string,
75
75
  },
76
76
  (Position) => ?string,
77
77
  >();
@@ -138,10 +138,10 @@ export default async function symbolicate(
138
138
  function findFunctionName(
139
139
  originalPos: Position,
140
140
  module: {
141
- +firstLine1Based: number,
142
- +functionMap: ?FBSourceFunctionMap,
143
- +map: Array<MetroSourceMapSegmentTuple>,
144
- +path: string,
141
+ readonly firstLine1Based: number,
142
+ readonly functionMap: ?FBSourceFunctionMap,
143
+ readonly map: Array<MetroSourceMapSegmentTuple>,
144
+ readonly path: string,
145
145
  },
146
146
  ): ?string {
147
147
  if (module.functionMap) {