metro 0.83.2 → 0.83.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/package.json +25 -23
  2. package/src/Assets.js +50 -30
  3. package/src/Assets.js.flow +26 -15
  4. package/src/Bundler/util.js +33 -22
  5. package/src/Bundler/util.js.flow +2 -2
  6. package/src/Bundler.js +5 -1
  7. package/src/Bundler.js.flow +1 -1
  8. package/src/DeltaBundler/DeltaCalculator.js +9 -5
  9. package/src/DeltaBundler/DeltaCalculator.js.flow +8 -8
  10. package/src/DeltaBundler/Graph.js +21 -17
  11. package/src/DeltaBundler/Graph.js.flow +30 -30
  12. package/src/DeltaBundler/Serializers/baseJSBundle.js +5 -1
  13. package/src/DeltaBundler/Serializers/baseJSBundle.js.flow +1 -1
  14. package/src/DeltaBundler/Serializers/getAllFiles.js.flow +2 -2
  15. package/src/DeltaBundler/Serializers/getAssets.js +5 -1
  16. package/src/DeltaBundler/Serializers/getAssets.js.flow +2 -2
  17. package/src/DeltaBundler/Serializers/getExplodedSourceMap.js.flow +2 -2
  18. package/src/DeltaBundler/Serializers/getRamBundleInfo.js +5 -1
  19. package/src/DeltaBundler/Serializers/getRamBundleInfo.js.flow +8 -8
  20. package/src/DeltaBundler/Serializers/helpers/js.js +33 -22
  21. package/src/DeltaBundler/Serializers/helpers/js.js.flow +6 -6
  22. package/src/DeltaBundler/Serializers/helpers/processModules.js.flow +3 -3
  23. package/src/DeltaBundler/Serializers/hmrJSBundle.js +33 -22
  24. package/src/DeltaBundler/Serializers/hmrJSBundle.js.flow +5 -5
  25. package/src/DeltaBundler/Serializers/sourceMapGenerator.js +5 -1
  26. package/src/DeltaBundler/Serializers/sourceMapGenerator.js.flow +6 -6
  27. package/src/DeltaBundler/Serializers/sourceMapObject.js.flow +2 -2
  28. package/src/DeltaBundler/Serializers/sourceMapString.js.flow +2 -2
  29. package/src/DeltaBundler/Transformer.js +5 -1
  30. package/src/DeltaBundler/Transformer.js.flow +3 -3
  31. package/src/DeltaBundler/Worker.flow.js +5 -1
  32. package/src/DeltaBundler/Worker.flow.js.flow +1 -1
  33. package/src/DeltaBundler/WorkerFarm.js +1 -1
  34. package/src/DeltaBundler/WorkerFarm.js.flow +26 -13
  35. package/src/DeltaBundler/buildSubgraph.js +9 -5
  36. package/src/DeltaBundler/buildSubgraph.js.flow +8 -8
  37. package/src/DeltaBundler/getTransformCacheKey.js +5 -1
  38. package/src/DeltaBundler/types.js +5 -1
  39. package/src/DeltaBundler/types.js.flow +36 -34
  40. package/src/DeltaBundler.js +5 -1
  41. package/src/DeltaBundler.js.flow +2 -2
  42. package/src/HmrServer.js +42 -30
  43. package/src/HmrServer.js.flow +17 -12
  44. package/src/IncrementalBundler.js +37 -22
  45. package/src/IncrementalBundler.js.flow +13 -9
  46. package/src/ModuleGraph/worker/JsFileWrapping.js +33 -22
  47. package/src/ModuleGraph/worker/JsFileWrapping.js.flow +10 -5
  48. package/src/ModuleGraph/worker/collectDependencies.js +33 -22
  49. package/src/ModuleGraph/worker/collectDependencies.js.flow +27 -21
  50. package/src/ModuleGraph/worker/generateImportNames.js +5 -1
  51. package/src/ModuleGraph/worker/generateImportNames.js.flow +4 -2
  52. package/src/ModuleGraph/worker/importLocationsPlugin.js.flow +7 -3
  53. package/src/Server/MultipartResponse.js +5 -1
  54. package/src/Server/MultipartResponse.js.flow +1 -1
  55. package/src/Server/symbolicate.js.flow +4 -4
  56. package/src/Server.js +112 -40
  57. package/src/Server.js.flow +110 -47
  58. package/src/cli/parseKeyValueParamArray.js.flow +1 -1
  59. package/src/cli-utils.js +5 -1
  60. package/src/cli-utils.js.flow +2 -2
  61. package/src/commands/build.js +5 -1
  62. package/src/commands/build.js.flow +11 -10
  63. package/src/commands/dependencies.js +5 -1
  64. package/src/commands/dependencies.js.flow +8 -4
  65. package/src/commands/serve.js +2 -0
  66. package/src/commands/serve.js.flow +14 -9
  67. package/src/index.flow.js +38 -27
  68. package/src/index.flow.js.flow +25 -20
  69. package/src/integration_tests/basic_bundle/AssetRegistry.js.flow +1 -1
  70. package/src/integration_tests/basic_bundle/ErrorBundle.js.flow +1 -1
  71. package/src/integration_tests/basic_bundle/build-errors/cannot-resolve-import.js +5 -1
  72. package/src/integration_tests/basic_bundle/build-errors/cannot-resolve-import.js.flow +1 -1
  73. package/src/integration_tests/basic_bundle/build-errors/cannot-resolve-multi-line-import-with-escapes.js.flow +1 -1
  74. package/src/integration_tests/basic_bundle/build-errors/cannot-resolve-multi-line-import.js.flow +1 -1
  75. package/src/integration_tests/basic_bundle/build-errors/cannot-resolve-require-with-embedded-comment.js.flow +1 -1
  76. package/src/integration_tests/basic_bundle/build-errors/cannot-resolve-require.js.flow +1 -1
  77. package/src/integration_tests/basic_bundle/build-errors/cannot-resolve-specifier-with-escapes.js.flow +1 -1
  78. package/src/integration_tests/basic_bundle/build-errors/inline-requires-cannot-resolve-import.js +5 -1
  79. package/src/integration_tests/basic_bundle/build-errors/inline-requires-cannot-resolve-import.js.flow +1 -1
  80. package/src/integration_tests/basic_bundle/build-errors/inline-requires-cannot-resolve-require.js.flow +1 -1
  81. package/src/integration_tests/basic_bundle/import-export/index.js +33 -22
  82. package/src/integration_tests/basic_bundle/import-export/index.js.flow +3 -3
  83. package/src/integration_tests/basic_bundle/import-export/utils.js.flow +2 -2
  84. package/src/integration_tests/basic_bundle/loadBundleAsyncForTest.js.flow +1 -1
  85. package/src/integration_tests/basic_bundle/optional-dependencies/index.js.flow +1 -1
  86. package/src/integration_tests/basic_bundle/require-context/conflict.js.flow +1 -1
  87. package/src/integration_tests/basic_bundle/require-context/empty.js.flow +1 -1
  88. package/src/integration_tests/basic_bundle/require-context/matching.js.flow +1 -1
  89. package/src/integration_tests/basic_bundle/require-context/mode-eager.js.flow +1 -1
  90. package/src/integration_tests/basic_bundle/require-context/mode-lazy-once.js.flow +1 -1
  91. package/src/integration_tests/basic_bundle/require-context/mode-lazy.js.flow +1 -1
  92. package/src/integration_tests/basic_bundle/require-context/mode-sync.js.flow +2 -2
  93. package/src/integration_tests/basic_bundle/require-context/utils.js.flow +1 -1
  94. package/src/integration_tests/basic_bundle/require-resolveWeak/import-and-resolveWeak.js.flow +1 -1
  95. package/src/integration_tests/basic_bundle/require-resolveWeak/multiple.js.flow +1 -1
  96. package/src/integration_tests/basic_bundle/require-resolveWeak/never-required.js.flow +1 -1
  97. package/src/integration_tests/basic_bundle/require-resolveWeak/require-and-resolveWeak.js.flow +1 -1
  98. package/src/integration_tests/execBundle.js +5 -1
  99. package/src/integration_tests/execBundle.js.flow +1 -1
  100. package/src/lib/BatchProcessor.js +10 -3
  101. package/src/lib/BatchProcessor.js.flow +10 -7
  102. package/src/lib/CountingSet.js.flow +4 -4
  103. package/src/lib/JsonReporter.js +5 -3
  104. package/src/lib/JsonReporter.js.flow +19 -17
  105. package/src/lib/RamBundleParser.js +5 -1
  106. package/src/lib/RamBundleParser.js.flow +1 -1
  107. package/src/lib/TerminalReporter.js +39 -28
  108. package/src/lib/TerminalReporter.js.flow +15 -15
  109. package/src/lib/contextModule.js +5 -1
  110. package/src/lib/contextModule.js.flow +1 -1
  111. package/src/lib/contextModuleTemplates.js +28 -21
  112. package/src/lib/countLines.js +4 -3
  113. package/src/lib/countLines.js.flow +3 -4
  114. package/src/lib/createWebsocketServer.js +14 -3
  115. package/src/lib/createWebsocketServer.js.flow +16 -9
  116. package/src/lib/debounceAsyncQueue.js.flow +1 -1
  117. package/src/lib/formatBundlingError.js +5 -1
  118. package/src/lib/formatBundlingError.js.flow +1 -1
  119. package/src/lib/getAppendScripts.js +5 -1
  120. package/src/lib/getAppendScripts.js.flow +4 -4
  121. package/src/lib/getGraphId.js +5 -1
  122. package/src/lib/getGraphId.js.flow +1 -1
  123. package/src/lib/getPreludeCode.js +4 -0
  124. package/src/lib/getPreludeCode.js.flow +10 -3
  125. package/src/lib/getPrependedScripts.js +44 -23
  126. package/src/lib/getPrependedScripts.js.flow +10 -3
  127. package/src/lib/logToConsole.js +5 -1
  128. package/src/lib/logToConsole.js.flow +2 -2
  129. package/src/lib/parseBundleOptionsFromBundleRequestUrl.js +33 -22
  130. package/src/lib/parseCustomResolverOptions.js.flow +2 -2
  131. package/src/lib/parseCustomTransformOptions.js.flow +1 -1
  132. package/src/lib/parseJsonBody.js.flow +11 -1
  133. package/src/lib/pathUtils.js +28 -21
  134. package/src/lib/pathUtils.js.flow +1 -1
  135. package/src/lib/relativizeSourceMap.js +5 -1
  136. package/src/lib/reporting.js +5 -1
  137. package/src/lib/reporting.js.flow +4 -4
  138. package/src/lib/transformHelpers.js +16 -10
  139. package/src/lib/transformHelpers.js.flow +17 -15
  140. package/src/node-haste/DependencyGraph/ModuleResolution.js +56 -43
  141. package/src/node-haste/DependencyGraph/ModuleResolution.js.flow +35 -32
  142. package/src/node-haste/DependencyGraph/createFileMap.js +64 -39
  143. package/src/node-haste/DependencyGraph/createFileMap.js.flow +44 -18
  144. package/src/node-haste/DependencyGraph.js +45 -32
  145. package/src/node-haste/DependencyGraph.js.flow +35 -37
  146. package/src/node-haste/Package.js +5 -1
  147. package/src/node-haste/PackageCache.js +5 -1
  148. package/src/node-haste/lib/AssetPaths.js +7 -3
  149. package/src/node-haste/lib/AssetPaths.js.flow +4 -4
  150. package/src/node-haste/lib/parsePlatformFilePath.js +11 -7
  151. package/src/node-haste/lib/parsePlatformFilePath.js.flow +4 -4
  152. package/src/shared/output/RamBundle/as-assets.js +5 -1
  153. package/src/shared/output/RamBundle/as-assets.js.flow +6 -6
  154. package/src/shared/output/RamBundle/as-indexed-file.js +5 -1
  155. package/src/shared/output/RamBundle/as-indexed-file.js.flow +5 -5
  156. package/src/shared/output/RamBundle/buildSourcemapWithMetadata.js.flow +5 -5
  157. package/src/shared/output/RamBundle/util.js +5 -1
  158. package/src/shared/output/RamBundle/util.js.flow +5 -5
  159. package/src/shared/output/RamBundle/write-sourcemap.js +5 -1
  160. package/src/shared/output/RamBundle/write-sourcemap.js.flow +1 -1
  161. package/src/shared/output/RamBundle.js +5 -1
  162. package/src/shared/output/RamBundle.js.flow +1 -1
  163. package/src/shared/output/bundle.flow.js +5 -1
  164. package/src/shared/output/bundle.flow.js.flow +3 -3
  165. package/src/shared/output/meta.js +7 -3
  166. package/src/shared/output/meta.js.flow +1 -1
  167. package/src/shared/output/writeFile.js +13 -4
  168. package/src/shared/output/writeFile.js.flow +8 -2
  169. package/src/shared/types.js.flow +20 -5
  170. package/src/Asset.d.ts +0 -25
  171. package/src/Bundler.d.ts +0 -39
  172. package/src/DeltaBundler/Graph.d.ts +0 -40
  173. package/src/DeltaBundler/Serializers/getExplodedSourceMap.d.ts +0 -26
  174. package/src/DeltaBundler/Serializers/getRamBundleInfo.d.ts +0 -18
  175. package/src/DeltaBundler/Worker.d.ts +0 -45
  176. package/src/DeltaBundler/types.d.ts +0 -166
  177. package/src/DeltaBundler.d.ts +0 -58
  178. package/src/IncrementalBundler.d.ts +0 -98
  179. package/src/ModuleGraph/test-helpers.js +0 -75
  180. package/src/ModuleGraph/worker/collectDependencies.d.ts +0 -27
  181. package/src/Server/MultipartResponse.d.ts +0 -31
  182. package/src/Server/symbolicate.d.ts +0 -31
  183. package/src/Server.d.ts +0 -118
  184. package/src/index.d.ts +0 -193
  185. package/src/lib/CountingSet.d.ts +0 -48
  186. package/src/lib/TerminalReporter.d.ts +0 -27
  187. package/src/lib/contextModule.d.ts +0 -22
  188. package/src/lib/getGraphId.d.ts +0 -11
  189. package/src/lib/reporting.d.ts +0 -144
  190. package/src/node-haste/DependencyGraph.d.ts +0 -62
  191. package/src/shared/output/bundle.d.ts +0 -35
  192. package/src/shared/types.d.ts +0 -130
package/src/Server.js CHANGED
@@ -51,7 +51,6 @@ var _symbolicate = _interopRequireDefault(require("./Server/symbolicate"));
51
51
  var _types = require("./shared/types");
52
52
  var _codeFrame = require("@babel/code-frame");
53
53
  var fs = _interopRequireWildcard(require("graceful-fs"));
54
- var _invariant = _interopRequireDefault(require("invariant"));
55
54
  var jscSafeUrl = _interopRequireWildcard(require("jsc-safe-url"));
56
55
  var _metroCore = require("metro-core");
57
56
  var _mimeTypes = _interopRequireDefault(require("mime-types"));
@@ -59,31 +58,42 @@ var _nullthrows = _interopRequireDefault(require("nullthrows"));
59
58
  var _path = _interopRequireDefault(require("path"));
60
59
  var _perf_hooks = require("perf_hooks");
61
60
  var _querystring = _interopRequireDefault(require("querystring"));
62
- function _getRequireWildcardCache(e) {
63
- if ("function" != typeof WeakMap) return null;
64
- var r = new WeakMap(),
65
- t = new WeakMap();
66
- return (_getRequireWildcardCache = function (e) {
67
- return e ? t : r;
68
- })(e);
69
- }
70
- function _interopRequireWildcard(e, r) {
71
- if (!r && e && e.__esModule) return e;
72
- if (null === e || ("object" != typeof e && "function" != typeof e))
73
- return { default: e };
74
- var t = _getRequireWildcardCache(r);
75
- if (t && t.has(e)) return t.get(e);
76
- var n = { __proto__: null },
77
- a = Object.defineProperty && Object.getOwnPropertyDescriptor;
78
- for (var u in e)
79
- if ("default" !== u && {}.hasOwnProperty.call(e, u)) {
80
- var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;
81
- i && (i.get || i.set) ? Object.defineProperty(n, u, i) : (n[u] = e[u]);
61
+ function _interopRequireWildcard(e, t) {
62
+ if ("function" == typeof WeakMap)
63
+ var r = new WeakMap(),
64
+ n = new WeakMap();
65
+ return (_interopRequireWildcard = function (e, t) {
66
+ if (!t && e && e.__esModule) return e;
67
+ var o,
68
+ i,
69
+ f = {
70
+ __proto__: null,
71
+ default: e,
72
+ };
73
+ if (null === e || ("object" != typeof e && "function" != typeof e))
74
+ return f;
75
+ if ((o = t ? n : r)) {
76
+ if (o.has(e)) return o.get(e);
77
+ o.set(e, f);
82
78
  }
83
- return ((n.default = e), t && t.set(e, n), n);
79
+ for (const t in e)
80
+ "default" !== t &&
81
+ {}.hasOwnProperty.call(e, t) &&
82
+ ((i =
83
+ (o = Object.defineProperty) &&
84
+ Object.getOwnPropertyDescriptor(e, t)) &&
85
+ (i.get || i.set)
86
+ ? o(f, t, i)
87
+ : (f[t] = e[t]));
88
+ return f;
89
+ })(e, t);
84
90
  }
85
91
  function _interopRequireDefault(e) {
86
- return e && e.__esModule ? e : { default: e };
92
+ return e && e.__esModule
93
+ ? e
94
+ : {
95
+ default: e,
96
+ };
87
97
  }
88
98
  const debug = require("debug")("Metro:Server");
89
99
  const { createActionStartEntry, createActionEndEntry, log } = _metroCore.Logger;
@@ -433,12 +443,14 @@ class Server {
433
443
  }),
434
444
  );
435
445
  try {
446
+ const depGraph = await this._bundler.getBundler().getDependencyGraph();
436
447
  const data = await (0, _Assets.getAsset)(
437
448
  assetPath,
438
449
  this._config.projectRoot,
439
450
  this._config.watchFolders,
440
451
  urlObj.searchParams.get("platform"),
441
452
  this._config.resolver.assetExts,
453
+ (filePath) => depGraph.doesFileExist(filePath),
442
454
  );
443
455
  if (process.env.REACT_NATIVE_ENABLE_ASSET_CACHING === true) {
444
456
  res.setHeader("Cache-Control", "max-age=31536000");
@@ -481,6 +493,13 @@ class Server {
481
493
  debug("Rewritten to: %s", req.url);
482
494
  }
483
495
  const reqHost = req.headers["x-forwarded-host"] || req.headers["host"];
496
+ debug("Request host is: %s", req.headers["host"]);
497
+ if (req.headers["x-forwarded-host"]) {
498
+ debug(
499
+ "Request x-forwarded-host is: %s",
500
+ req.headers["x-forwarded-host"],
501
+ );
502
+ }
484
503
  if (!reqHost) {
485
504
  throw new Error("No host header was found.");
486
505
  }
@@ -784,6 +803,7 @@ class Server {
784
803
  return {
785
804
  action_name: "Requesting bundle",
786
805
  bundle_url: context.req.url,
806
+ bundle_original_url: context.req.originalUrl ?? "unknown",
787
807
  entry_point: context.entryFile,
788
808
  bundler: "delta",
789
809
  build_id: getBuildID(context.buildNumber),
@@ -1068,6 +1088,7 @@ class Server {
1068
1088
  },
1069
1089
  });
1070
1090
  async _symbolicate(req, res) {
1091
+ const depGraph = await this._bundler.getBundler().getDependencyGraph();
1071
1092
  const getCodeFrame = (urls, symbolicatedStack) => {
1072
1093
  const allFramesCollapsed = symbolicatedStack.every(
1073
1094
  ({ collapse }) => collapse,
@@ -1085,6 +1106,13 @@ class Server {
1085
1106
  this._config.projectRoot,
1086
1107
  file ?? "",
1087
1108
  );
1109
+ if (!depGraph.doesFileExist(fileAbsolute)) {
1110
+ debug(
1111
+ "Skipping code frame for file not in dependency graph.",
1112
+ fileAbsolute,
1113
+ );
1114
+ continue;
1115
+ }
1088
1116
  try {
1089
1117
  return {
1090
1118
  content: (0, _codeFrame.codeFrameColumns)(
@@ -1115,6 +1143,7 @@ class Server {
1115
1143
  }
1116
1144
  return null;
1117
1145
  };
1146
+ let inputValidated = false;
1118
1147
  try {
1119
1148
  const symbolicatingLogEntry = log(
1120
1149
  createActionStartEntry("Symbolicating"),
@@ -1125,25 +1154,68 @@ class Server {
1125
1154
  const body = await req.rawBody;
1126
1155
  parsedBody = JSON.parse(body);
1127
1156
  } else {
1128
- parsedBody = await (0, _parseJsonBody.default)(req);
1157
+ parsedBody = await (0, _parseJsonBody.default)(req, {
1158
+ strict: false,
1159
+ });
1129
1160
  }
1130
- const rewriteAndNormalizeStackFrame = (frame, lineNumber) => {
1131
- (0, _invariant.default)(
1132
- frame != null && typeof frame === "object",
1133
- "Bad stack frame at line %d, expected object, received: %s",
1134
- lineNumber,
1135
- typeof frame,
1161
+ let validatedBody;
1162
+ if (
1163
+ parsedBody != null &&
1164
+ typeof parsedBody === "object" &&
1165
+ !Array.isArray(parsedBody) &&
1166
+ Array.isArray(parsedBody["stack"])
1167
+ ) {
1168
+ const maybeStack = parsedBody["stack"];
1169
+ const extraData = parsedBody["extraData"];
1170
+ validatedBody = {
1171
+ stack: maybeStack,
1172
+ extraData,
1173
+ };
1174
+ } else {
1175
+ throw new Error(
1176
+ `Bad symbolication input, expected object with stack array, got: ${JSON.stringify(parsedBody)}`,
1136
1177
  );
1137
- const frameFile = frame.file;
1138
- if (typeof frameFile === "string" && frameFile.includes("://")) {
1139
- return {
1140
- ...frame,
1141
- file: this._rewriteAndNormalizeUrl(frameFile),
1142
- };
1178
+ }
1179
+ const validateAndNormalizeStackFrame = (frame) => {
1180
+ if (
1181
+ frame == null ||
1182
+ typeof frame !== "object" ||
1183
+ Array.isArray(frame)
1184
+ ) {
1185
+ throw new Error("Expected frame to be a JSON object");
1186
+ }
1187
+ if (frame.file != null && typeof frame.file !== "string") {
1188
+ throw new Error("Expected file to be string or nullish");
1189
+ }
1190
+ let frameFile = frame.file;
1191
+ if (frameFile != null && frameFile.includes("://")) {
1192
+ frameFile = this._rewriteAndNormalizeUrl(frameFile);
1143
1193
  }
1144
- return frame;
1194
+ if (frame.methodName != null && typeof frame.methodName !== "string") {
1195
+ throw new Error("Expected methodName to be string or nullish");
1196
+ }
1197
+ if (frame.lineNumber != null && typeof frame.lineNumber !== "number") {
1198
+ throw new Error("Expected lineNumber to be number or nullish");
1199
+ }
1200
+ if (frame.column != null && typeof frame.column !== "number") {
1201
+ throw new Error("Expected column to be number or nullish");
1202
+ }
1203
+ return {
1204
+ ...frame,
1205
+ file: frameFile,
1206
+ lineNumber: frame.lineNumber,
1207
+ column: frame.column,
1208
+ methodName: frame.methodName,
1209
+ };
1145
1210
  };
1146
- const stack = parsedBody.stack.map(rewriteAndNormalizeStackFrame);
1211
+ const stack = validatedBody.stack.map((frame, lineNumber) => {
1212
+ try {
1213
+ return validateAndNormalizeStackFrame(frame);
1214
+ } catch (e) {
1215
+ throw new Error(`Bad frame at line ${lineNumber}: ${e.message}`);
1216
+ }
1217
+ });
1218
+ inputValidated = true;
1147
1219
  const urls = new Set();
1148
1220
  stack.forEach((frame) => {
1149
1221
  const sourceUrl = frame.file;
@@ -1169,7 +1241,7 @@ class Server {
1169
1241
  stack,
1170
1242
  zip(urls.values(), sourceMaps),
1171
1243
  this._config,
1172
- parsedBody.extraData ?? {},
1244
+ validatedBody.extraData ?? {},
1173
1245
  );
1174
1246
  debug("Symbolication done");
1175
1247
  res.end(
@@ -1183,7 +1255,7 @@ class Server {
1183
1255
  });
1184
1256
  } catch (error) {
1185
1257
  debug("Symbolication failed", error.stack || error);
1186
- res.statusCode = 500;
1258
+ res.statusCode = inputValidated ? 500 : 400;
1187
1259
  res.end(
1188
1260
  JSON.stringify({
1189
1261
  error: error.message,
@@ -22,6 +22,7 @@ import type {
22
22
  } from './DeltaBundler/types';
23
23
  import type {RevisionId} from './IncrementalBundler';
24
24
  import type {GraphId} from './lib/getGraphId';
25
+ import type {JsonData} from './lib/parseJsonBody';
25
26
  import type {Reporter} from './lib/reporting';
26
27
  import type {StackFrameInput, StackFrameOutput} from './Server/symbolicate';
27
28
  import type {
@@ -65,7 +66,6 @@ import symbolicate from './Server/symbolicate';
65
66
  import {SourcePathsMode} from './shared/types';
66
67
  import {codeFrameColumns} from '@babel/code-frame';
67
68
  import * as fs from 'graceful-fs';
68
- import invariant from 'invariant';
69
69
  import * as jscSafeUrl from 'jsc-safe-url';
70
70
  import {Logger} from 'metro-core';
71
71
  import mime from 'mime-types';
@@ -98,6 +98,7 @@ export type BundleMetadata = {
98
98
  };
99
99
 
100
100
  type ProcessStartContext = {
101
+ ...SplitBundleOptions,
101
102
  +buildNumber: number,
102
103
  +bundleOptions: BundleOptions,
103
104
  +graphId: GraphId,
@@ -107,7 +108,6 @@ type ProcessStartContext = {
107
108
  +revisionId?: ?RevisionId,
108
109
  +bundlePerfLogger: RootPerfLogger,
109
110
  +requestStartTimestamp: number,
110
- ...SplitBundleOptions,
111
111
  };
112
112
 
113
113
  type ProcessDeleteContext = {
@@ -121,7 +121,7 @@ type ProcessEndContext<T> = {
121
121
  +result: T,
122
122
  };
123
123
 
124
- export type ServerOptions = $ReadOnly<{
124
+ export type ServerOptions = Readonly<{
125
125
  hasReducedPerformance?: boolean,
126
126
  onBundleBuilt?: (bundlePath: string) => void,
127
127
  watch?: boolean,
@@ -140,8 +140,8 @@ export default class Server {
140
140
  _platforms: Set<string>;
141
141
  _reporter: Reporter;
142
142
  _serverOptions: ServerOptions | void;
143
- _allowedSuffixesForSourceRequests: $ReadOnlyArray<string>;
144
- _sourceRequestRoutingMap: $ReadOnlyArray<
143
+ _allowedSuffixesForSourceRequests: ReadonlyArray<string>;
144
+ _sourceRequestRoutingMap: ReadonlyArray<
145
145
  [pathnamePrefix: string, normalizedRootDir: string],
146
146
  >;
147
147
 
@@ -208,9 +208,9 @@ export default class Server {
208
208
  splitOptions,
209
209
  prepend,
210
210
  graph,
211
- }: $ReadOnly<{
211
+ }: Readonly<{
212
212
  splitOptions: SplitBundleOptions,
213
- prepend: $ReadOnlyArray<Module<>>,
213
+ prepend: ReadonlyArray<Module<>>,
214
214
  graph: ReadOnlyGraph<>,
215
215
  }>): Promise<{code: string, map: string}> {
216
216
  const {
@@ -299,7 +299,7 @@ export default class Server {
299
299
  ): Promise<{
300
300
  code: string,
301
301
  map: string,
302
- assets?: $ReadOnlyArray<AssetData>,
302
+ assets?: ReadonlyArray<AssetData>,
303
303
  ...
304
304
  }> {
305
305
  const splitOptions = splitBundleOptions(bundleOptions);
@@ -403,7 +403,7 @@ export default class Server {
403
403
  });
404
404
  }
405
405
 
406
- async getAssets(options: BundleOptions): Promise<$ReadOnlyArray<AssetData>> {
406
+ async getAssets(options: BundleOptions): Promise<ReadonlyArray<AssetData>> {
407
407
  const {entryFile, onProgress, resolverOptions, transformOptions} =
408
408
  splitBundleOptions(options);
409
409
 
@@ -423,7 +423,7 @@ export default class Server {
423
423
  async _getAssetsFromDependencies(
424
424
  dependencies: ReadOnlyDependencies<>,
425
425
  platform: ?string,
426
- ): Promise<$ReadOnlyArray<AssetData>> {
426
+ ): Promise<ReadonlyArray<AssetData>> {
427
427
  return await getAssets(dependencies, {
428
428
  processModuleFilter: this._config.serializer.processModuleFilter,
429
429
  assetPlugins: this._config.transformer.assetPlugins,
@@ -549,12 +549,14 @@ export default class Server {
549
549
  );
550
550
 
551
551
  try {
552
+ const depGraph = await this._bundler.getBundler().getDependencyGraph();
552
553
  const data = await getAsset(
553
554
  assetPath,
554
555
  this._config.projectRoot,
555
556
  this._config.watchFolders,
556
557
  urlObj.searchParams.get('platform'),
557
558
  this._config.resolver.assetExts,
559
+ filePath => depGraph.doesFileExist(filePath),
558
560
  );
559
561
  // Tell clients to cache this for 1 year.
560
562
  // This is safe as the asset url contains a hash of the asset.
@@ -615,6 +617,13 @@ export default class Server {
615
617
  debug('Rewritten to: %s', req.url);
616
618
  }
617
619
  const reqHost = req.headers['x-forwarded-host'] || req.headers['host'];
620
+ debug('Request host is: %s', req.headers['host']);
621
+ if (req.headers['x-forwarded-host']) {
622
+ debug(
623
+ 'Request x-forwarded-host is: %s',
624
+ req.headers['x-forwarded-host'],
625
+ );
626
+ }
618
627
  if (!reqHost) {
619
628
  throw new Error('No host header was found.');
620
629
  }
@@ -759,7 +768,7 @@ export default class Server {
759
768
  req: IncomingMessage,
760
769
  res: ServerResponse,
761
770
  bundleOptions: BundleOptions,
762
- buildContext: $ReadOnly<{
771
+ buildContext: Readonly<{
763
772
  buildNumber: number,
764
773
  bundlePerfLogger: RootPerfLogger,
765
774
  }>,
@@ -769,7 +778,7 @@ export default class Server {
769
778
  req: IncomingMessage,
770
779
  res: ServerResponse,
771
780
  bundleOptions: BundleOptions,
772
- buildContext: $ReadOnly<{
781
+ buildContext: Readonly<{
773
782
  buildNumber: number,
774
783
  bundlePerfLogger: RootPerfLogger,
775
784
  }>,
@@ -980,7 +989,7 @@ export default class Server {
980
989
  req: IncomingMessage,
981
990
  res: ServerResponse,
982
991
  bundleOptions: BundleOptions,
983
- buildContext: $ReadOnly<{
992
+ buildContext: Readonly<{
984
993
  buildNumber: number,
985
994
  bundlePerfLogger: RootPerfLogger,
986
995
  }>,
@@ -990,6 +999,7 @@ export default class Server {
990
999
  return {
991
1000
  action_name: 'Requesting bundle',
992
1001
  bundle_url: context.req.url,
1002
+ bundle_original_url: context.req.originalUrl ?? 'unknown',
993
1003
  entry_point: context.entryFile,
994
1004
  bundler: 'delta',
995
1005
  build_id: getBuildID(context.buildNumber),
@@ -1174,7 +1184,7 @@ export default class Server {
1174
1184
 
1175
1185
  // This function ensures that modules in source maps are sorted in the same
1176
1186
  // order as in a plain JS bundle.
1177
- _getSortedModules(graph: ReadOnlyGraph<>): $ReadOnlyArray<Module<>> {
1187
+ _getSortedModules(graph: ReadOnlyGraph<>): ReadonlyArray<Module<>> {
1178
1188
  const modules = [...graph.dependencies.values()];
1179
1189
  // Assign IDs to modules in a consistent order
1180
1190
  for (const module of modules) {
@@ -1191,7 +1201,7 @@ export default class Server {
1191
1201
  req: IncomingMessage,
1192
1202
  res: ServerResponse,
1193
1203
  bundleOptions: BundleOptions,
1194
- buildContext: $ReadOnly<{
1204
+ buildContext: Readonly<{
1195
1205
  buildNumber: number,
1196
1206
  bundlePerfLogger: RootPerfLogger,
1197
1207
  }>,
@@ -1263,7 +1273,7 @@ export default class Server {
1263
1273
  req: IncomingMessage,
1264
1274
  res: ServerResponse,
1265
1275
  bundleOptions: BundleOptions,
1266
- buildContext: $ReadOnly<{
1276
+ buildContext: Readonly<{
1267
1277
  buildNumber: number,
1268
1278
  bundlePerfLogger: RootPerfLogger,
1269
1279
  }>,
@@ -1277,7 +1287,7 @@ export default class Server {
1277
1287
  bundler: 'delta',
1278
1288
  };
1279
1289
  },
1280
- createEndEntry(context: ProcessEndContext<$ReadOnlyArray<AssetData>>) {
1290
+ createEndEntry(context: ProcessEndContext<ReadonlyArray<AssetData>>) {
1281
1291
  return {
1282
1292
  bundler: 'delta',
1283
1293
  };
@@ -1309,10 +1319,12 @@ export default class Server {
1309
1319
  },
1310
1320
  });
1311
1321
 
1312
- async _symbolicate(req: IncomingMessage, res: ServerResponse) {
1322
+ async _symbolicate(req: IncomingMessage, res: ServerResponse): Promise<void> {
1323
+ const depGraph = await this._bundler.getBundler().getDependencyGraph();
1324
+
1313
1325
  const getCodeFrame = (
1314
1326
  urls: Set<string>,
1315
- symbolicatedStack: $ReadOnlyArray<StackFrameOutput>,
1327
+ symbolicatedStack: ReadonlyArray<StackFrameOutput>,
1316
1328
  ) => {
1317
1329
  const allFramesCollapsed = symbolicatedStack.every(
1318
1330
  ({collapse}) => collapse,
@@ -1332,6 +1344,13 @@ export default class Server {
1332
1344
  }
1333
1345
 
1334
1346
  const fileAbsolute = path.resolve(this._config.projectRoot, file ?? '');
1347
+ if (!depGraph.doesFileExist(fileAbsolute)) {
1348
+ debug(
1349
+ 'Skipping code frame for file not in dependency graph.',
1350
+ fileAbsolute,
1351
+ );
1352
+ continue;
1353
+ }
1335
1354
  try {
1336
1355
  return {
1337
1356
  content: codeFrameColumns(
@@ -1361,6 +1380,7 @@ export default class Server {
1361
1380
  return null;
1362
1381
  };
1363
1382
 
1383
+ let inputValidated = false;
1364
1384
  try {
1365
1385
  const symbolicatingLogEntry = log(
1366
1386
  createActionStartEntry('Symbolicating'),
@@ -1373,35 +1393,78 @@ export default class Server {
1373
1393
  // < 0.80 and Expo SDK < 53
1374
1394
  // $FlowFixMe[prop-missing] - rawBody assigned by legacy CLI integrations
1375
1395
  const body = await req.rawBody;
1376
- parsedBody = JSON.parse(body);
1396
+ parsedBody = JSON.parse(body) as JsonData;
1377
1397
  } else {
1378
- parsedBody = (await parseJsonBody(req)) as {
1379
- stack: $ReadOnlyArray<StackFrameInput>,
1380
- extraData: {[string]: mixed},
1381
- };
1398
+ parsedBody = await parseJsonBody(req, {strict: false});
1382
1399
  }
1383
1400
 
1384
- const rewriteAndNormalizeStackFrame = <T>(
1385
- frame: T,
1386
- lineNumber: number,
1387
- ): T => {
1388
- invariant(
1389
- frame != null && typeof frame === 'object',
1390
- 'Bad stack frame at line %d, expected object, received: %s',
1391
- lineNumber,
1392
- typeof frame,
1401
+ let validatedBody: {
1402
+ stack: ReadonlyArray<JsonData>,
1403
+ extraData?: JsonData,
1404
+ };
1405
+
1406
+ if (
1407
+ parsedBody != null &&
1408
+ typeof parsedBody === 'object' &&
1409
+ !Array.isArray(parsedBody) &&
1410
+ Array.isArray(parsedBody['stack'])
1411
+ ) {
1412
+ const maybeStack: Array<JsonData> = parsedBody['stack'];
1413
+ const extraData = parsedBody['extraData'];
1414
+ validatedBody = {
1415
+ stack: maybeStack,
1416
+ extraData,
1417
+ };
1418
+ } else {
1419
+ throw new Error(
1420
+ `Bad symbolication input, expected object with stack array, got: ${JSON.stringify(parsedBody)}`,
1393
1421
  );
1394
- const frameFile = frame.file;
1395
- if (typeof frameFile === 'string' && frameFile.includes('://')) {
1396
- return {
1397
- ...frame,
1398
- file: this._rewriteAndNormalizeUrl(frameFile),
1399
- };
1422
+ }
1423
+
1424
+ const validateAndNormalizeStackFrame = (
1425
+ frame: JsonData,
1426
+ ): StackFrameInput => {
1427
+ if (
1428
+ frame == null ||
1429
+ typeof frame !== 'object' ||
1430
+ Array.isArray(frame)
1431
+ ) {
1432
+ throw new Error('Expected frame to be a JSON object');
1433
+ }
1434
+ if (frame.file != null && typeof frame.file !== 'string') {
1435
+ throw new Error('Expected file to be string or nullish');
1436
+ }
1437
+ let frameFile = frame.file;
1438
+ if (frameFile != null && frameFile.includes('://')) {
1439
+ frameFile = this._rewriteAndNormalizeUrl(frameFile);
1400
1440
  }
1401
- return frame;
1441
+ if (frame.methodName != null && typeof frame.methodName !== 'string') {
1442
+ throw new Error('Expected methodName to be string or nullish');
1443
+ }
1444
+ if (frame.lineNumber != null && typeof frame.lineNumber !== 'number') {
1445
+ throw new Error('Expected lineNumber to be number or nullish');
1446
+ }
1447
+ if (frame.column != null && typeof frame.column !== 'number') {
1448
+ throw new Error('Expected column to be number or nullish');
1449
+ }
1450
+ return {
1451
+ ...frame,
1452
+ file: frameFile,
1453
+ lineNumber: frame.lineNumber,
1454
+ column: frame.column,
1455
+ methodName: frame.methodName,
1456
+ };
1402
1457
  };
1403
1458
 
1404
- const stack = parsedBody.stack.map(rewriteAndNormalizeStackFrame);
1459
+ const stack = validatedBody.stack.map((frame, lineNumber) => {
1460
+ try {
1461
+ return validateAndNormalizeStackFrame(frame);
1462
+ } catch (e) {
1463
+ throw new Error(`Bad frame at line ${lineNumber}: ${e.message}`);
1464
+ }
1465
+ });
1466
+
1467
+ inputValidated = true;
1405
1468
  // In case of multiple bundles / HMR, some stack frames can have different URLs from others
1406
1469
  const urls = new Set<string>();
1407
1470
 
@@ -1433,7 +1496,7 @@ export default class Server {
1433
1496
  stack,
1434
1497
  zip(urls.values(), sourceMaps),
1435
1498
  this._config,
1436
- parsedBody.extraData ?? {},
1499
+ validatedBody.extraData ?? {},
1437
1500
  );
1438
1501
 
1439
1502
  debug('Symbolication done');
@@ -1448,7 +1511,7 @@ export default class Server {
1448
1511
  });
1449
1512
  } catch (error) {
1450
1513
  debug('Symbolication failed', error.stack || error);
1451
- res.statusCode = 500;
1514
+ res.statusCode = inputValidated ? 500 : 400;
1452
1515
  res.end(JSON.stringify({error: error.message}));
1453
1516
  }
1454
1517
  }
@@ -1518,7 +1581,7 @@ export default class Server {
1518
1581
  relativeTo,
1519
1582
  resolverOptions,
1520
1583
  transformOptions,
1521
- }: $ReadOnly<{
1584
+ }: Readonly<{
1522
1585
  relativeTo: 'project' | 'server',
1523
1586
  resolverOptions: ResolverInputOptions,
1524
1587
  transformOptions: TransformInputOptions,
@@ -1543,15 +1606,15 @@ export default class Server {
1543
1606
  return this._nextBundleBuildNumber++;
1544
1607
  }
1545
1608
 
1546
- getPlatforms(): $ReadOnlyArray<string> {
1609
+ getPlatforms(): ReadonlyArray<string> {
1547
1610
  return this._config.resolver.platforms;
1548
1611
  }
1549
1612
 
1550
- getWatchFolders(): $ReadOnlyArray<string> {
1613
+ getWatchFolders(): ReadonlyArray<string> {
1551
1614
  return this._config.watchFolders;
1552
1615
  }
1553
1616
 
1554
- static DEFAULT_GRAPH_OPTIONS: $ReadOnly<{
1617
+ static DEFAULT_GRAPH_OPTIONS: Readonly<{
1555
1618
  customResolverOptions: CustomResolverOptions,
1556
1619
  customTransformOptions: CustomTransformOptions,
1557
1620
  dev: boolean,
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  export default function coerceKeyValueArray(
13
- keyValueArray: $ReadOnlyArray<string>,
13
+ keyValueArray: ReadonlyArray<string>,
14
14
  ): {
15
15
  [key: string]: string,
16
16
  __proto__: null,
package/src/cli-utils.js CHANGED
@@ -6,7 +6,11 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.watchFile = exports.makeAsyncCommand = void 0;
7
7
  var _fs = _interopRequireDefault(require("fs"));
8
8
  function _interopRequireDefault(e) {
9
- return e && e.__esModule ? e : { default: e };
9
+ return e && e.__esModule
10
+ ? e
11
+ : {
12
+ default: e,
13
+ };
10
14
  }
11
15
  const watchFile = async function (filename, callback) {
12
16
  _fs.default.watchFile(filename, () => {
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @flow
7
+ * @flow strict
8
8
  * @format
9
9
  * @oncall react_native
10
10
  */
@@ -13,7 +13,7 @@ import fs from 'fs';
13
13
 
14
14
  export const watchFile = async function (
15
15
  filename: string,
16
- callback: () => any,
16
+ callback: () => unknown,
17
17
  ): Promise<void> {
18
18
  fs.watchFile(filename, () => {
19
19
  callback();
@@ -14,7 +14,11 @@ var _TerminalReporter = _interopRequireDefault(
14
14
  var _metroConfig = require("metro-config");
15
15
  var _metroCore = require("metro-core");
16
16
  function _interopRequireDefault(e) {
17
- return e && e.__esModule ? e : { default: e };
17
+ return e && e.__esModule
18
+ ? e
19
+ : {
20
+ default: e,
21
+ };
18
22
  }
19
23
  const term = new _metroCore.Terminal(process.stdout);
20
24
  const updateReporter = new _TerminalReporter.default(term);