@samitouri / QOS-React-1 / commits / 3039f5d3f6

[Flight] Recognize Node 22+ V8 frames for Promise statics in debug info (#36969)

## Summary Newer V8 versions (Node.js ≥ ~22) name the stack frames of static methods on the `Promise` constructor `Promise.all`, `Promise.race`, etc., where older versions named them `Function.all`, `Function.race`, etc. The `isPromiseCreationInternal` and `isPromiseAwaitInternal` allowlists in `ReactFlightServer` only matched the old spellings. ## How did you test this change? - `yarn test --no-watchman ReactFlightAsyncDebugInfo` — 18/18 pass on both Node 20.19.0 and Node 24.16.0 (previously, "can track async information when awaited" failed on Node 24) - `yarn test --silent --no-watchman packages/react-server/src/__tests__ packages/react-server-dom-webpack` — 243/243 pass on both Node versions, default and `-r=experimental` channels - `yarn test-www --silent --no-watchman packages/react-server/src/__tests__` with `__VARIANT__` true and false — pass - `yarn flow dom-node`, `yarn prettier`, `yarn linc` — pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

dan committed Jul 8, 2026 at 13:02 UTC 3039f5d3f660471a222393e84bc9d3a74691f8df
1 file changed +19
packages/react-server/src/ReactFlightServer.js
+19
@@ -204,15 +204,24 @@ function isPromiseCreationInternal(url: string, functionName: string): boolean {
204 if (url !== '') {
205 return false;
206 }
207 + // V8 used to name the frames of static methods on the Promise constructor
208 + // "Function.x" but newer versions name them "Promise.x". We match both.
209 switch (functionName) {
210 case 'new Promise':
211 case 'Function.withResolvers':
212 + case 'Promise.withResolvers':
213 case 'Function.reject':
214 + case 'Promise.reject':
215 case 'Function.resolve':
216 + case 'Promise.resolve':
217 case 'Function.all':
218 + case 'Promise.all':
219 case 'Function.allSettled':
220 + case 'Promise.allSettled':
221 case 'Function.race':
222 + case 'Promise.race':
223 case 'Function.try':
224 + case 'Promise.try':
225 return true;
226 default:
227 return false;
@@ -333,18 +342,28 @@ function isPromiseAwaitInternal(url: string, functionName: string): boolean {
342 if (url !== '') {
343 return false;
344 }
345 + // V8 used to name the frames of static methods on the Promise constructor
346 + // "Function.x" but newer versions name them "Promise.x". We match both.
347 switch (functionName) {
348 case 'Promise.then':
349 case 'Promise.catch':
350 case 'Promise.finally':
351 case 'Function.reject':
352 + case 'Promise.reject':
353 case 'Function.resolve':
354 + case 'Promise.resolve':
355 case 'Function.all':
356 + case 'Promise.all':
357 case 'Function.allSettled':
358 + case 'Promise.allSettled':
359 case 'Function.any':
360 + case 'Promise.any':
361 case 'Function.race':
362 + case 'Promise.race':
363 case 'Function.try':
364 + case 'Promise.try':
365 case 'Function.withResolvers':
366 + case 'Promise.withResolvers':
367 return true;
368 default:
369 return false;