Skip to content

Commit dcfadad

Browse files
authored
fix(metro-resolver-symlinks): sync Server.js patch to latest stable (#3923)
1 parent 0a85605 commit dcfadad

File tree

2 files changed

+27
-19
lines changed

2 files changed

+27
-19
lines changed

.changeset/chubby-webs-laugh.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@rnx-kit/metro-resolver-symlinks": patch
3+
---
4+
5+
Synced `Server.js` patch to Metro 0.83

packages/metro-resolver-symlinks/src/utils/metro.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
} from "@rnx-kit/tools-react-native/metro";
66
import * as fs from "node:fs";
77
import * as path from "node:path";
8-
import * as url from "node:url";
8+
import { URL } from "node:url";
99
import type { Options, ResolutionContextCompat } from "../types.ts";
1010

1111
const RETRY_FROM_DISK_FLAG = "experimental_retryResolvingFromDisk";
@@ -187,36 +187,39 @@ export function patchMetro(options: Options): void {
187187
// We need to patch `_processSingleAssetRequest` because it calls
188188
// `Assets.getAsset`, and `Assets.getAsset` checks whether the asset lives
189189
// 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
190192
const Server = importMetroModule("/src/Server");
191193
Server.prototype.orig__processSingleAssetRequest =
192194
Server.prototype._processSingleAssetRequest;
193195
Server.prototype._processSingleAssetRequest = function (
194196
req: { url: string },
195197
res: unknown
196198
): 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+
199206
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];
212218
}
213-
214-
const [, actualPath] = result;
215-
assetPath = actualPath;
216219
}
217220

218221
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");
220223
}
221224

222225
const watchFolders = this.getWatchFolders();

0 commit comments

Comments
 (0)