|
5 | 5 | } from "@rnx-kit/tools-react-native/metro"; |
6 | 6 | import * as fs from "node:fs"; |
7 | 7 | import * as path from "node:path"; |
8 | | -import * as url from "node:url"; |
| 8 | +import { URL } from "node:url"; |
9 | 9 | import type { Options, ResolutionContextCompat } from "../types.ts"; |
10 | 10 |
|
11 | 11 | const RETRY_FROM_DISK_FLAG = "experimental_retryResolvingFromDisk"; |
@@ -187,36 +187,39 @@ export function patchMetro(options: Options): void { |
187 | 187 | // We need to patch `_processSingleAssetRequest` because it calls |
188 | 188 | // `Assets.getAsset`, and `Assets.getAsset` checks whether the asset lives |
189 | 189 | // under one of `projectRoot` or `watchFolders`. |
| 190 | + // |
| 191 | + // Last synced to: https://github.com/facebook/metro/blob/v0.83.3/packages/metro/src/Server.js#L502 |
190 | 192 | const Server = importMetroModule("/src/Server"); |
191 | 193 | Server.prototype.orig__processSingleAssetRequest = |
192 | 194 | Server.prototype._processSingleAssetRequest; |
193 | 195 | Server.prototype._processSingleAssetRequest = function ( |
194 | 196 | req: { url: string }, |
195 | 197 | res: unknown |
196 | 198 | ): Promise<void> { |
197 | | - // eslint-disable-next-line n/no-deprecated-api |
198 | | - const urlObj = url.parse(decodeURI(req.url), true); |
| 199 | + if (!URL.canParse(req.url, "resolve://")) { |
| 200 | + // @ts-expect-error The second parameter to Error is not yet typed |
| 201 | + throw new Error("Could not parse URL", { cause: req.url }); |
| 202 | + } |
| 203 | + |
| 204 | + const urlObj = new URL(req.url, "resolve://"); |
| 205 | + |
199 | 206 | let [, assetPath] = |
200 | | - (urlObj && |
201 | | - urlObj.pathname && |
202 | | - urlObj.pathname.match(/^\/assets\/(.+)$/)) || |
203 | | - []; |
204 | | - |
205 | | - if (!assetPath && urlObj && urlObj.query && urlObj.query.unstable_path) { |
206 | | - const unstable_path = Array.isArray(urlObj.query.unstable_path) |
207 | | - ? urlObj.query.unstable_path[0] |
208 | | - : urlObj.query.unstable_path; |
209 | | - const result = unstable_path.match(/^([^?]*)\??(.*)$/); |
210 | | - if (result == null) { |
211 | | - throw new Error(`Unable to parse URL: ${unstable_path}`); |
| 207 | + urlObj.pathname |
| 208 | + .split("/") |
| 209 | + .map((segment) => decodeURIComponent(segment)) |
| 210 | + .join("/") |
| 211 | + .match(/^\/assets\/(.+)$/) || []; |
| 212 | + const unstable_path = |
| 213 | + !assetPath && urlObj.searchParams.get("unstable_path"); |
| 214 | + if (unstable_path) { |
| 215 | + const m = unstable_path.match(/^([^?]*)\??(.*)$/); |
| 216 | + if (m) { |
| 217 | + assetPath = m[1]; |
212 | 218 | } |
213 | | - |
214 | | - const [, actualPath] = result; |
215 | | - assetPath = actualPath; |
216 | 219 | } |
217 | 220 |
|
218 | 221 | if (!assetPath) { |
219 | | - throw new Error(`Could not extract asset path from URL: ${req.url}`); |
| 222 | + throw new Error("Could not extract asset path from URL"); |
220 | 223 | } |
221 | 224 |
|
222 | 225 | const watchFolders = this.getWatchFolders(); |
|
0 commit comments