Repository: vercel/next.js
Pull request: Make params and searchParams new Promises

The problem is that without a new Promise, when all the awaits are in third party, we'd keep searching down to the inner most which shows `internal params`. We could maybe make the real value of those include all params. But we can also just not dedupe to show the real value.

Changed files:
filename: packages/next/src/server/request/params.ts
patch: @@ -456,15 +456,17 @@ function makeDynamicallyTrackedParamsWithDevWarnings(
   requestStore: RequestStore
 ): Promise<Params> {
   if (requestStore.asyncApiPromises && hasFallbackParams) {
-    // Deliberately don't wrap each instance of params in a `new Promise()`.
-    // We want React Devtools to consider all the separate `params` promises
-    // that we create for each segment to be triggered by one IO operation --
-    // the resolving of the underlying `sharedParamsParent` promise.
-    // It's created above any userspace code and has a `displayName`,
-    // so it should show up in "suspended by".
-    const promise = requestStore.asyncApiPromises.sharedParamsParent.then(
-      () => underlyingParams
-    )
+    // We wrap each instance of params in a `new Promise()`, because deduping
+    // them across requests doesn't work anyway and this let us show each
+    // await a different set of values. This is important when all awaits
+    // are in third party which would otherwise track all the way to the
+    // internal params.
+    const sharedParamsParent = requestStore.asyncApiPromises.sharedParamsParent
+    const promise: Promise<Params> = new Promise((resolve, reject) => {
+      sharedParamsParent.then(() => resolve(underlyingParams), reject)
+    })
+    // @ts-expect-error
+    promise.displayName = 'params'
     return instrumentParamsPromiseWithDevWarnings(
       underlyingParams,
       promise,

filename: packages/next/src/server/request/search-params.ts
patch: @@ -423,15 +423,16 @@ function makeUntrackedSearchParamsWithDevWarningsImpl(
 
   let promise: Promise<SearchParams>
   if (requestStore.asyncApiPromises) {
-    // Deliberately don't wrap each instance of params in a `new Promise()`.
-    // We want React Devtools to consider all the separate `searchParams` promises
-    // that we create for each segment to be triggered by one IO operation --
-    // the resolving of the underlying `sharedParamsParent` promise.
-    // It's created above any userspace code and has a `displayName`,
-    // so it should show up in "suspended by".
-    promise = requestStore.asyncApiPromises.sharedSearchParamsParent.then(
-      () => proxiedUnderlying
-    )
+    // We wrap each instance of searchParams in a `new Promise()`.
+    // This is important when all awaits are in third party which would otherwise
+    // track all the way to the internal params.
+    const sharedSearchParamsParent =
+      requestStore.asyncApiPromises.sharedSearchParamsParent
+    promise = new Promise((resolve, reject) => {
+      sharedSearchParamsParent.then(() => resolve(proxiedUnderlying), reject)
+    })
+    // @ts-expect-error
+    promise.displayName = 'searchParams'
   } else {
     promise = makeDevtoolsIOAwarePromise(
       proxiedUnderlying,