metro 0.76.1 → 0.76.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.
Files changed (62) hide show
  1. package/package.json +21 -23
  2. package/src/DeltaBundler/Graph.js +6 -19
  3. package/src/DeltaBundler/Graph.js.flow +8 -15
  4. package/src/DeltaBundler/Serializers/baseJSBundle.js +1 -0
  5. package/src/DeltaBundler/Serializers/baseJSBundle.js.flow +1 -0
  6. package/src/DeltaBundler/Serializers/helpers/js.js +22 -6
  7. package/src/DeltaBundler/Serializers/helpers/js.js.flow +24 -6
  8. package/src/DeltaBundler/Serializers/helpers/processModules.js +2 -0
  9. package/src/DeltaBundler/Serializers/helpers/processModules.js.flow +3 -0
  10. package/src/DeltaBundler/Serializers/hmrJSBundle.js +1 -0
  11. package/src/DeltaBundler/Serializers/hmrJSBundle.js.flow +1 -0
  12. package/src/DeltaBundler/types.d.ts +5 -3
  13. package/src/DeltaBundler/types.flow.js.flow +1 -1
  14. package/src/HmrServer.js +3 -3
  15. package/src/HmrServer.js.flow +5 -3
  16. package/src/IncrementalBundler.js +7 -6
  17. package/src/IncrementalBundler.js.flow +8 -6
  18. package/src/Server/symbolicate.js +33 -5
  19. package/src/Server/symbolicate.js.flow +40 -9
  20. package/src/Server.js +19 -11
  21. package/src/Server.js.flow +31 -16
  22. package/src/index.d.ts +16 -6
  23. package/src/index.flow.js +15 -2
  24. package/src/index.flow.js.flow +29 -4
  25. package/{types/lib/getGraphId.d.ts → src/integration_tests/basic_bundle/loadBundleAsyncForTest.js} +7 -2
  26. package/src/integration_tests/basic_bundle/loadBundleAsyncForTest.js.flow +20 -0
  27. package/src/integration_tests/execBundle.js +3 -0
  28. package/src/integration_tests/execBundle.js.flow +4 -1
  29. package/src/integration_tests/metro.config.js +5 -0
  30. package/src/lib/getGraphId.js +2 -7
  31. package/src/lib/getGraphId.js.flow +3 -3
  32. package/src/lib/getPrependedScripts.js +1 -2
  33. package/src/lib/getPrependedScripts.js.flow +1 -2
  34. package/src/lib/parseOptionsFromUrl.js +1 -0
  35. package/src/lib/parseOptionsFromUrl.js.flow +1 -0
  36. package/src/lib/splitBundleOptions.js +1 -0
  37. package/src/lib/splitBundleOptions.js.flow +1 -0
  38. package/src/lib/transformHelpers.js +1 -2
  39. package/src/lib/transformHelpers.js.flow +1 -2
  40. package/src/node-haste/DependencyGraph.js +6 -1
  41. package/src/node-haste/DependencyGraph.js.flow +7 -1
  42. package/src/shared/types.d.ts +2 -0
  43. package/src/shared/types.flow.js.flow +2 -1
  44. package/types/Asset.d.ts +0 -25
  45. package/types/Bundler.d.ts +0 -39
  46. package/types/DeltaBundler/Graph.d.ts +0 -40
  47. package/types/DeltaBundler/Serializers/getRamBundleInfo.d.ts +0 -18
  48. package/types/DeltaBundler/Worker.d.ts +0 -47
  49. package/types/DeltaBundler/types.d.ts +0 -167
  50. package/types/DeltaBundler.d.ts +0 -58
  51. package/types/IncrementalBundler.d.ts +0 -97
  52. package/types/ModuleGraph/worker/collectDependencies.d.ts +0 -27
  53. package/types/Server/MultipartResponse.d.ts +0 -31
  54. package/types/Server.d.ts +0 -113
  55. package/types/index.d.ts +0 -151
  56. package/types/lib/CountingSet.d.ts +0 -48
  57. package/types/lib/TerminalReporter.d.ts +0 -27
  58. package/types/lib/contextModule.d.ts +0 -22
  59. package/types/lib/reporting.d.ts +0 -140
  60. package/types/node-haste/DependencyGraph.d.ts +0 -59
  61. package/types/shared/output/bundle.d.ts +0 -31
  62. package/types/shared/types.d.ts +0 -138
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metro",
3
- "version": "0.76.1",
3
+ "version": "0.76.3",
4
4
  "description": "🚇 The JavaScript bundler for React Native.",
5
5
  "main": "src/index.js",
6
6
  "bin": "src/cli.js",
@@ -34,22 +34,22 @@
34
34
  "invariant": "^2.2.4",
35
35
  "jest-worker": "^27.2.0",
36
36
  "lodash.throttle": "^4.1.1",
37
- "metro-babel-transformer": "0.76.1",
38
- "metro-cache": "0.76.1",
39
- "metro-cache-key": "0.76.1",
40
- "metro-config": "0.76.1",
41
- "metro-core": "0.76.1",
42
- "metro-file-map": "0.76.1",
43
- "metro-inspector-proxy": "0.76.1",
44
- "metro-minify-terser": "0.76.1",
45
- "metro-minify-uglify": "0.76.1",
46
- "metro-react-native-babel-preset": "0.76.1",
47
- "metro-resolver": "0.76.1",
48
- "metro-runtime": "0.76.1",
49
- "metro-source-map": "0.76.1",
50
- "metro-symbolicate": "0.76.1",
51
- "metro-transform-plugins": "0.76.1",
52
- "metro-transform-worker": "0.76.1",
37
+ "metro-babel-transformer": "0.76.3",
38
+ "metro-cache": "0.76.3",
39
+ "metro-cache-key": "0.76.3",
40
+ "metro-config": "0.76.3",
41
+ "metro-core": "0.76.3",
42
+ "metro-file-map": "0.76.3",
43
+ "metro-inspector-proxy": "0.76.3",
44
+ "metro-minify-terser": "0.76.3",
45
+ "metro-minify-uglify": "0.76.3",
46
+ "metro-react-native-babel-preset": "0.76.3",
47
+ "metro-resolver": "0.76.3",
48
+ "metro-runtime": "0.76.3",
49
+ "metro-source-map": "0.76.3",
50
+ "metro-symbolicate": "0.76.3",
51
+ "metro-transform-plugins": "0.76.3",
52
+ "metro-transform-worker": "0.76.3",
53
53
  "mime-types": "^2.1.27",
54
54
  "node-fetch": "^2.2.0",
55
55
  "nullthrows": "^1.1.1",
@@ -63,16 +63,14 @@
63
63
  },
64
64
  "devDependencies": {
65
65
  "@babel/plugin-transform-flow-strip-types": "^7.0.0",
66
- "@types/babel__code-frame": "^7.0.3",
67
- "@types/ws": "^8.5.4",
68
66
  "babel-jest": "^29.2.1",
69
67
  "dedent": "^0.7.0",
70
68
  "jest-snapshot": "^26.5.2",
71
69
  "jest-snapshot-serializer-raw": "^1.2.0",
72
- "metro-babel-register": "0.76.1",
73
- "metro-memory-fs": "0.76.1",
74
- "metro-react-native-babel-preset": "0.76.1",
75
- "metro-react-native-babel-transformer": "0.76.1",
70
+ "metro-babel-register": "0.76.3",
71
+ "metro-memory-fs": "0.76.3",
72
+ "metro-react-native-babel-preset": "0.76.3",
73
+ "metro-react-native-babel-transformer": "0.76.3",
76
74
  "mock-req": "^0.2.0",
77
75
  "mock-res": "^0.6.0",
78
76
  "stack-trace": "^0.0.10"
@@ -86,17 +86,11 @@ const nullthrows = require("nullthrows");
86
86
 
87
87
  // TODO: Convert to a Flow enum
88
88
 
89
- function getInternalOptions({
90
- transform,
91
- resolve,
92
- onProgress,
93
- experimentalImportBundleSupport,
94
- shallow,
95
- }) {
89
+ function getInternalOptions({ transform, resolve, onProgress, lazy, shallow }) {
96
90
  let numProcessed = 0;
97
91
  let total = 0;
98
92
  return {
99
- experimentalImportBundleSupport,
93
+ lazy,
100
94
  transform,
101
95
  resolve,
102
96
  onDependencyAdd: () => onProgress && onProgress(numProcessed, ++total),
@@ -286,10 +280,7 @@ class Graph {
286
280
  // Don't add a node for the module if the graph is shallow (single-module).
287
281
  } else if (dependency.data.data.asyncType === "weak") {
288
282
  // Exclude weak dependencies from the bundle.
289
- } else if (
290
- options.experimentalImportBundleSupport &&
291
- dependency.data.data.asyncType != null
292
- ) {
283
+ } else if (options.lazy && dependency.data.data.asyncType != null) {
293
284
  // Don't add a node for the module if we are traversing async dependencies
294
285
  // lazily (and this is an async dependency). Instead, record it in
295
286
  // importBundleNodes.
@@ -338,10 +329,7 @@ class Graph {
338
329
  // Weak dependencies are excluded from the bundle.
339
330
  return;
340
331
  }
341
- if (
342
- options.experimentalImportBundleSupport &&
343
- dependency.data.data.asyncType != null
344
- ) {
332
+ if (options.lazy && dependency.data.data.asyncType != null) {
345
333
  this._decrementImportBundleReference(dependency, parentModule);
346
334
  }
347
335
  const module = this.dependencies.get(absolutePath);
@@ -515,7 +503,7 @@ class Graph {
515
503
  );
516
504
  invariant(
517
505
  importBundleNode.inverseDependencies.has(parentModule.path),
518
- "experimentalImportBundleSupport: import bundle inverse references"
506
+ "lazy: import bundle inverse references"
519
507
  );
520
508
  importBundleNode.inverseDependencies.delete(parentModule.path);
521
509
  if (importBundleNode.inverseDependencies.size === 0) {
@@ -667,8 +655,7 @@ function dependenciesEqual(a, b, options) {
667
655
  return (
668
656
  a === b ||
669
657
  (a.absolutePath === b.absolutePath &&
670
- (!options.experimentalImportBundleSupport ||
671
- a.data.data.asyncType === b.data.data.asyncType) &&
658
+ (!options.lazy || a.data.data.asyncType === b.data.data.asyncType) &&
672
659
  contextParamsEqual(a.data.data.contextParams, b.data.data.contextParams))
673
660
  );
674
661
  }
@@ -94,7 +94,7 @@ type Delta = $ReadOnly<{
94
94
  }>;
95
95
 
96
96
  type InternalOptions<T> = $ReadOnly<{
97
- experimentalImportBundleSupport: boolean,
97
+ lazy: boolean,
98
98
  onDependencyAdd: () => mixed,
99
99
  onDependencyAdded: () => mixed,
100
100
  resolve: Options<T>['resolve'],
@@ -106,14 +106,14 @@ function getInternalOptions<T>({
106
106
  transform,
107
107
  resolve,
108
108
  onProgress,
109
- experimentalImportBundleSupport,
109
+ lazy,
110
110
  shallow,
111
111
  }: Options<T>): InternalOptions<T> {
112
112
  let numProcessed = 0;
113
113
  let total = 0;
114
114
 
115
115
  return {
116
- experimentalImportBundleSupport,
116
+ lazy,
117
117
  transform,
118
118
  resolve,
119
119
  onDependencyAdd: () => onProgress && onProgress(numProcessed, ++total),
@@ -357,10 +357,7 @@ export class Graph<T = MixedOutput> {
357
357
  // Don't add a node for the module if the graph is shallow (single-module).
358
358
  } else if (dependency.data.data.asyncType === 'weak') {
359
359
  // Exclude weak dependencies from the bundle.
360
- } else if (
361
- options.experimentalImportBundleSupport &&
362
- dependency.data.data.asyncType != null
363
- ) {
360
+ } else if (options.lazy && dependency.data.data.asyncType != null) {
364
361
  // Don't add a node for the module if we are traversing async dependencies
365
362
  // lazily (and this is an async dependency). Instead, record it in
366
363
  // importBundleNodes.
@@ -421,10 +418,7 @@ export class Graph<T = MixedOutput> {
421
418
  return;
422
419
  }
423
420
 
424
- if (
425
- options.experimentalImportBundleSupport &&
426
- dependency.data.data.asyncType != null
427
- ) {
421
+ if (options.lazy && dependency.data.data.asyncType != null) {
428
422
  this._decrementImportBundleReference(dependency, parentModule);
429
423
  }
430
424
 
@@ -629,7 +623,7 @@ export class Graph<T = MixedOutput> {
629
623
  );
630
624
  invariant(
631
625
  importBundleNode.inverseDependencies.has(parentModule.path),
632
- 'experimentalImportBundleSupport: import bundle inverse references',
626
+ 'lazy: import bundle inverse references',
633
627
  );
634
628
  importBundleNode.inverseDependencies.delete(parentModule.path);
635
629
  if (importBundleNode.inverseDependencies.size === 0) {
@@ -784,13 +778,12 @@ export class Graph<T = MixedOutput> {
784
778
  function dependenciesEqual(
785
779
  a: Dependency,
786
780
  b: Dependency,
787
- options: $ReadOnly<{experimentalImportBundleSupport: boolean, ...}>,
781
+ options: $ReadOnly<{lazy: boolean, ...}>,
788
782
  ): boolean {
789
783
  return (
790
784
  a === b ||
791
785
  (a.absolutePath === b.absolutePath &&
792
- (!options.experimentalImportBundleSupport ||
793
- a.data.data.asyncType === b.data.data.asyncType) &&
786
+ (!options.lazy || a.data.data.asyncType === b.data.data.asyncType) &&
794
787
  contextParamsEqual(a.data.data.contextParams, b.data.data.contextParams))
795
788
  );
796
789
  }
@@ -24,6 +24,7 @@ function baseJSBundle(entryPoint, preModules, graph, options) {
24
24
  includeAsyncPaths: options.includeAsyncPaths,
25
25
  projectRoot: options.projectRoot,
26
26
  serverRoot: options.serverRoot,
27
+ sourceUrl: options.sourceUrl,
27
28
  };
28
29
 
29
30
  // Do not prepend polyfills or the require runtime when only modules are requested
@@ -39,6 +39,7 @@ function baseJSBundle(
39
39
  includeAsyncPaths: options.includeAsyncPaths,
40
40
  projectRoot: options.projectRoot,
41
41
  serverRoot: options.serverRoot,
42
+ sourceUrl: options.sourceUrl,
42
43
  };
43
44
 
44
45
  // Do not prepend polyfills or the require runtime when only modules are requested
@@ -31,16 +31,32 @@ function getModuleParams(module, options) {
31
31
  const id = options.createModuleId(dependency.absolutePath);
32
32
  if (options.includeAsyncPaths && dependency.data.data.asyncType != null) {
33
33
  hasPaths = true;
34
+ invariant(
35
+ options.sourceUrl != null,
36
+ "sourceUrl is required when includeAsyncPaths is true"
37
+ );
38
+
39
+ // TODO: Only include path if the target is not in the bundle
40
+
41
+ // Construct a server-relative URL for the split bundle, propagating
42
+ // most parameters from the main bundle's URL.
43
+
44
+ const { searchParams } = new URL(options.sourceUrl);
45
+ searchParams.set("modulesOnly", "true");
46
+ searchParams.set("runModule", "false");
34
47
  const bundlePath = path.relative(
35
48
  options.serverRoot,
36
49
  dependency.absolutePath
37
50
  );
38
- // TODO: Eventually this slicing should be asyncRequire's responsibility
39
- // Strip the file extension
40
- paths[id] = path.join(
41
- path.dirname(bundlePath),
42
- path.basename(bundlePath, path.extname(bundlePath))
43
- );
51
+ paths[id] =
52
+ "/" +
53
+ path.join(
54
+ path.dirname(bundlePath),
55
+ // Strip the file extension
56
+ path.basename(bundlePath, path.extname(bundlePath))
57
+ ) +
58
+ ".bundle?" +
59
+ searchParams.toString();
44
60
  }
45
61
  return id;
46
62
  }
@@ -24,6 +24,7 @@ export type Options = $ReadOnly<{
24
24
  includeAsyncPaths: boolean,
25
25
  projectRoot: string,
26
26
  serverRoot: string,
27
+ sourceUrl: ?string,
27
28
  ...
28
29
  }>;
29
30
 
@@ -48,16 +49,33 @@ function getModuleParams(module: Module<>, options: Options): Array<mixed> {
48
49
  const id = options.createModuleId(dependency.absolutePath);
49
50
  if (options.includeAsyncPaths && dependency.data.data.asyncType != null) {
50
51
  hasPaths = true;
52
+ invariant(
53
+ options.sourceUrl != null,
54
+ 'sourceUrl is required when includeAsyncPaths is true',
55
+ );
56
+
57
+ // TODO: Only include path if the target is not in the bundle
58
+
59
+ // Construct a server-relative URL for the split bundle, propagating
60
+ // most parameters from the main bundle's URL.
61
+
62
+ const {searchParams} = new URL(options.sourceUrl);
63
+ searchParams.set('modulesOnly', 'true');
64
+ searchParams.set('runModule', 'false');
65
+
51
66
  const bundlePath = path.relative(
52
67
  options.serverRoot,
53
68
  dependency.absolutePath,
54
69
  );
55
- // TODO: Eventually this slicing should be asyncRequire's responsibility
56
- // Strip the file extension
57
- paths[id] = path.join(
58
- path.dirname(bundlePath),
59
- path.basename(bundlePath, path.extname(bundlePath)),
60
- );
70
+ paths[id] =
71
+ '/' +
72
+ path.join(
73
+ path.dirname(bundlePath),
74
+ // Strip the file extension
75
+ path.basename(bundlePath, path.extname(bundlePath)),
76
+ ) +
77
+ '.bundle?' +
78
+ searchParams.toString();
61
79
  }
62
80
  return id;
63
81
  },
@@ -21,6 +21,7 @@ function processModules(
21
21
  includeAsyncPaths,
22
22
  projectRoot,
23
23
  serverRoot,
24
+ sourceUrl,
24
25
  }
25
26
  ) {
26
27
  return [...modules]
@@ -34,6 +35,7 @@ function processModules(
34
35
  includeAsyncPaths,
35
36
  projectRoot,
36
37
  serverRoot,
38
+ sourceUrl,
37
39
  }),
38
40
  ]);
39
41
  }
@@ -24,6 +24,7 @@ function processModules(
24
24
  includeAsyncPaths,
25
25
  projectRoot,
26
26
  serverRoot,
27
+ sourceUrl,
27
28
  }: $ReadOnly<{
28
29
  filter?: (module: Module<>) => boolean,
29
30
  createModuleId: string => number,
@@ -31,6 +32,7 @@ function processModules(
31
32
  includeAsyncPaths: boolean,
32
33
  projectRoot: string,
33
34
  serverRoot: string,
35
+ sourceUrl: ?string,
34
36
  }>,
35
37
  ): $ReadOnlyArray<[Module<>, string]> {
36
38
  return [...modules]
@@ -44,6 +46,7 @@ function processModules(
44
46
  includeAsyncPaths,
45
47
  projectRoot,
46
48
  serverRoot,
49
+ sourceUrl,
47
50
  }),
48
51
  ]);
49
52
  }
@@ -50,6 +50,7 @@ function generateModules(sourceModules, graph, options) {
50
50
  function prepareModule(module, graph, options) {
51
51
  const code = wrapModule(module, {
52
52
  ...options,
53
+ sourceUrl: url.format(options.clientUrl),
53
54
  dev: true,
54
55
  });
55
56
  const inverseDependencies = getInverseDependencies(module.path, graph);
@@ -77,6 +77,7 @@ function prepareModule(
77
77
  ): string {
78
78
  const code = wrapModule(module, {
79
79
  ...options,
80
+ sourceUrl: url.format(options.clientUrl),
80
81
  dev: true,
81
82
  });
82
83
 
@@ -8,7 +8,6 @@
8
8
  * @oncall react_native
9
9
  */
10
10
 
11
- import type {SourceLocation} from '@babel/code-frame';
12
11
  import type {JsTransformOptions} from 'metro-transform-worker';
13
12
  import type {RequireContextParams} from '../ModuleGraph/worker/collectDependencies';
14
13
  import type {RequireContext} from '../lib/contextModule';
@@ -55,7 +54,10 @@ export interface TransformResultDependency {
55
54
  */
56
55
  readonly isOptional?: boolean;
57
56
 
58
- readonly locs: ReadonlyArray<SourceLocation>;
57
+ readonly locs: ReadonlyArray<{
58
+ readonly start: {readonly line: number; readonly column: number};
59
+ readonly end: {readonly line: number; readonly column: number};
60
+ }>;
59
61
 
60
62
  /** Context for requiring a collection of modules. */
61
63
  readonly contextParams?: RequireContextParams;
@@ -137,7 +139,7 @@ export interface Options<T = MixedOutput> {
137
139
  readonly onProgress:
138
140
  | ((numProcessed: number, total: number) => unknown)
139
141
  | null;
140
- readonly experimentalImportBundleSupport: boolean;
142
+ readonly lazy: boolean;
141
143
  readonly unstable_allowRequireContext: boolean;
142
144
  readonly shallow: boolean;
143
145
  }
@@ -130,7 +130,7 @@ export type Options<T = MixedOutput> = {
130
130
  +transform: TransformFn<T>,
131
131
  +transformOptions: TransformInputOptions,
132
132
  +onProgress: ?(numProcessed: number, total: number) => mixed,
133
- +experimentalImportBundleSupport: boolean,
133
+ +lazy: boolean,
134
134
  +unstable_allowRequireContext: boolean,
135
135
  +unstable_enablePackageExports: boolean,
136
136
  +shallow: boolean,
package/src/HmrServer.js CHANGED
@@ -79,8 +79,7 @@ class HmrServer {
79
79
  const graphId = getGraphId(resolvedEntryFilePath, transformOptions, {
80
80
  resolverOptions,
81
81
  shallow: graphOptions.shallow,
82
- experimentalImportBundleSupport:
83
- this._config.server.experimentalImportBundleSupport,
82
+ lazy: graphOptions.lazy,
84
83
  unstable_allowRequireContext:
85
84
  this._config.transformer.unstable_allowRequireContext,
86
85
  });
@@ -120,6 +119,7 @@ class HmrServer {
120
119
  clients: new Set([client]),
121
120
  clientUrl,
122
121
  revisionId: id,
122
+ graphOptions,
123
123
  unlisten: () => unlisten(),
124
124
  };
125
125
  this._clientGroups.set(id, clientGroup);
@@ -279,7 +279,7 @@ class HmrServer {
279
279
  const hmrUpdate = hmrJSBundle(delta, revision.graph, {
280
280
  clientUrl: group.clientUrl,
281
281
  createModuleId: this._createModuleId,
282
- includeAsyncPaths: this._config.server.experimentalImportBundleSupport,
282
+ includeAsyncPaths: group.graphOptions.lazy,
283
283
  projectRoot: this._config.projectRoot,
284
284
  serverRoot:
285
285
  this._config.server.unstable_serverRoot ?? this._config.projectRoot,
@@ -11,6 +11,7 @@
11
11
  'use strict';
12
12
 
13
13
  import type IncrementalBundler, {RevisionId} from './IncrementalBundler';
14
+ import type {GraphOptions} from './shared/types.flow';
14
15
  import type {ConfigT, RootPerfLogger} from 'metro-config';
15
16
  import type {
16
17
  HmrClientMessage,
@@ -48,6 +49,7 @@ type ClientGroup = {
48
49
  clientUrl: EntryPointURL,
49
50
  revisionId: RevisionId,
50
51
  +unlisten: () => void,
52
+ +graphOptions: GraphOptions,
51
53
  };
52
54
 
53
55
  function send(sendFns: Array<(string) => void>, message: HmrMessage): void {
@@ -123,8 +125,7 @@ class HmrServer<TClient: Client> {
123
125
  const graphId = getGraphId(resolvedEntryFilePath, transformOptions, {
124
126
  resolverOptions,
125
127
  shallow: graphOptions.shallow,
126
- experimentalImportBundleSupport:
127
- this._config.server.experimentalImportBundleSupport,
128
+ lazy: graphOptions.lazy,
128
129
  unstable_allowRequireContext:
129
130
  this._config.transformer.unstable_allowRequireContext,
130
131
  });
@@ -167,6 +168,7 @@ class HmrServer<TClient: Client> {
167
168
  clients: new Set([client]),
168
169
  clientUrl,
169
170
  revisionId: id,
171
+ graphOptions,
170
172
  unlisten: (): void => unlisten(),
171
173
  };
172
174
 
@@ -356,7 +358,7 @@ class HmrServer<TClient: Client> {
356
358
  const hmrUpdate = hmrJSBundle(delta, revision.graph, {
357
359
  clientUrl: group.clientUrl,
358
360
  createModuleId: this._createModuleId,
359
- includeAsyncPaths: this._config.server.experimentalImportBundleSupport,
361
+ includeAsyncPaths: group.graphOptions.lazy,
360
362
  projectRoot: this._config.projectRoot,
361
363
  serverRoot:
362
364
  this._config.server.unstable_serverRoot ?? this._config.projectRoot,
@@ -59,6 +59,7 @@ class IncrementalBundler {
59
59
  otherOptions = {
60
60
  onProgress: null,
61
61
  shallow: false,
62
+ lazy: false,
62
63
  }
63
64
  ) {
64
65
  const absoluteEntryFiles = await this._getAbsoluteEntryFiles(entryFiles);
@@ -78,8 +79,7 @@ class IncrementalBundler {
78
79
  ),
79
80
  transformOptions,
80
81
  onProgress: otherOptions.onProgress,
81
- experimentalImportBundleSupport:
82
- this._config.server.experimentalImportBundleSupport,
82
+ lazy: otherOptions.lazy,
83
83
  unstable_allowRequireContext:
84
84
  this._config.transformer.unstable_allowRequireContext,
85
85
  unstable_enablePackageExports:
@@ -101,6 +101,7 @@ class IncrementalBundler {
101
101
  otherOptions = {
102
102
  onProgress: null,
103
103
  shallow: false,
104
+ lazy: false,
104
105
  }
105
106
  ) {
106
107
  const absoluteEntryFiles = await this._getAbsoluteEntryFiles(entryFiles);
@@ -122,8 +123,7 @@ class IncrementalBundler {
122
123
  ),
123
124
  transformOptions,
124
125
  onProgress: otherOptions.onProgress,
125
- experimentalImportBundleSupport:
126
- this._config.server.experimentalImportBundleSupport,
126
+ lazy: otherOptions.lazy,
127
127
  unstable_allowRequireContext:
128
128
  this._config.transformer.unstable_allowRequireContext,
129
129
  unstable_enablePackageExports:
@@ -140,6 +140,7 @@ class IncrementalBundler {
140
140
  otherOptions = {
141
141
  onProgress: null,
142
142
  shallow: false,
143
+ lazy: false,
143
144
  }
144
145
  ) {
145
146
  const graph = await this.buildGraphForEntries(
@@ -171,13 +172,13 @@ class IncrementalBundler {
171
172
  otherOptions = {
172
173
  onProgress: null,
173
174
  shallow: false,
175
+ lazy: false,
174
176
  }
175
177
  ) {
176
178
  const graphId = getGraphId(entryFile, transformOptions, {
177
179
  resolverOptions,
178
180
  shallow: otherOptions.shallow,
179
- experimentalImportBundleSupport:
180
- this._config.server.experimentalImportBundleSupport,
181
+ lazy: otherOptions.lazy,
181
182
  unstable_allowRequireContext:
182
183
  this._config.transformer.unstable_allowRequireContext,
183
184
  });
@@ -38,6 +38,7 @@ export type OutputGraph = Graph<>;
38
38
  type OtherOptions = $ReadOnly<{
39
39
  onProgress: $PropertyType<DeltaBundlerOptions<>, 'onProgress'>,
40
40
  shallow: boolean,
41
+ lazy: boolean,
41
42
  }>;
42
43
 
43
44
  export type GraphRevision = {
@@ -107,6 +108,7 @@ class IncrementalBundler {
107
108
  otherOptions?: OtherOptions = {
108
109
  onProgress: null,
109
110
  shallow: false,
111
+ lazy: false,
110
112
  },
111
113
  ): Promise<OutputGraph> {
112
114
  const absoluteEntryFiles = await this._getAbsoluteEntryFiles(entryFiles);
@@ -127,8 +129,7 @@ class IncrementalBundler {
127
129
  ),
128
130
  transformOptions,
129
131
  onProgress: otherOptions.onProgress,
130
- experimentalImportBundleSupport:
131
- this._config.server.experimentalImportBundleSupport,
132
+ lazy: otherOptions.lazy,
132
133
  unstable_allowRequireContext:
133
134
  this._config.transformer.unstable_allowRequireContext,
134
135
  unstable_enablePackageExports:
@@ -153,6 +154,7 @@ class IncrementalBundler {
153
154
  otherOptions?: OtherOptions = {
154
155
  onProgress: null,
155
156
  shallow: false,
157
+ lazy: false,
156
158
  },
157
159
  ): Promise<ReadOnlyDependencies<>> {
158
160
  const absoluteEntryFiles = await this._getAbsoluteEntryFiles(entryFiles);
@@ -175,8 +177,7 @@ class IncrementalBundler {
175
177
  ),
176
178
  transformOptions,
177
179
  onProgress: otherOptions.onProgress,
178
- experimentalImportBundleSupport:
179
- this._config.server.experimentalImportBundleSupport,
180
+ lazy: otherOptions.lazy,
180
181
  unstable_allowRequireContext:
181
182
  this._config.transformer.unstable_allowRequireContext,
182
183
  unstable_enablePackageExports:
@@ -195,6 +196,7 @@ class IncrementalBundler {
195
196
  otherOptions?: OtherOptions = {
196
197
  onProgress: null,
197
198
  shallow: false,
199
+ lazy: false,
198
200
  },
199
201
  ): Promise<{+graph: OutputGraph, +prepend: $ReadOnlyArray<Module<>>}> {
200
202
  const graph = await this.buildGraphForEntries(
@@ -229,6 +231,7 @@ class IncrementalBundler {
229
231
  otherOptions?: OtherOptions = {
230
232
  onProgress: null,
231
233
  shallow: false,
234
+ lazy: false,
232
235
  },
233
236
  ): Promise<{
234
237
  delta: DeltaResult<>,
@@ -238,8 +241,7 @@ class IncrementalBundler {
238
241
  const graphId = getGraphId(entryFile, transformOptions, {
239
242
  resolverOptions,
240
243
  shallow: otherOptions.shallow,
241
- experimentalImportBundleSupport:
242
- this._config.server.experimentalImportBundleSupport,
244
+ lazy: otherOptions.lazy,
243
245
  unstable_allowRequireContext:
244
246
  this._config.transformer.unstable_allowRequireContext,
245
247
  });
@@ -34,7 +34,7 @@ function createFunctionNameGetter(module) {
34
34
  source: "dummy",
35
35
  });
36
36
  }
37
- async function symbolicate(stack, maps, config) {
37
+ async function symbolicate(stack, maps, config, extraData) {
38
38
  const mapsByUrl = new Map();
39
39
  for (const [url, map] of maps) {
40
40
  mapsByUrl.set(url, map);
@@ -108,7 +108,9 @@ async function symbolicate(stack, maps, config) {
108
108
  function symbolicateFrame(frame) {
109
109
  const module = findModule(frame);
110
110
  if (!module) {
111
- return frame;
111
+ return {
112
+ ...frame,
113
+ };
112
114
  }
113
115
  if (!Array.isArray(module.map)) {
114
116
  throw new Error(
@@ -117,7 +119,9 @@ async function symbolicate(stack, maps, config) {
117
119
  }
118
120
  const originalPos = findOriginalPos(frame, module);
119
121
  if (!originalPos) {
120
- return frame;
122
+ return {
123
+ ...frame,
124
+ };
121
125
  }
122
126
  const methodName =
123
127
  findFunctionName(originalPos, module) ?? frame.methodName;
@@ -129,15 +133,39 @@ async function symbolicate(stack, maps, config) {
129
133
  column: originalPos.column0Based,
130
134
  };
131
135
  }
136
+
137
+ /**
138
+ * `customizeFrame` allows for custom modifications of the symbolicated frame in a stack.
139
+ * It can be used to collapse stack frames that are not relevant to users, pointing them
140
+ * to more relevant product code instead.
141
+ *
142
+ * An example usecase is a library throwing an error while sanitizing inputs from product code.
143
+ * In some cases, it's more useful to point the developer looking at the error towards the product code directly.
144
+ */
132
145
  async function customizeFrame(frame) {
133
146
  const customizations =
134
147
  (await config.symbolicator.customizeFrame(frame)) || {};
135
148
  return {
136
149
  ...frame,
137
- collapse: false,
138
150
  ...customizations,
139
151
  };
140
152
  }
141
- return Promise.all(stack.map(symbolicateFrame).map(customizeFrame));
153
+
154
+ /**
155
+ * `customizeStack` allows for custom modifications of a symbolicated stack.
156
+ * Where `customizeFrame` operates on individual frames, this hook can process the entire stack in context.
157
+ *
158
+ * Note: `customizeStack` has access to an `extraData` object which can be used to attach metadata
159
+ * to the error coming in, to be used by the customizeStack hook.
160
+ */
161
+ async function customizeStack(symbolicatedStack) {
162
+ return await config.symbolicator.customizeStack(
163
+ symbolicatedStack,
164
+ extraData
165
+ );
166
+ }
167
+ return Promise.all(stack.map(symbolicateFrame).map(customizeFrame)).then(
168
+ customizeStack
169
+ );
142
170
  }
143
171
  module.exports = symbolicate;