From 8b08e99efa56b848538768e25265fd3aa24dd8a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Sat, 13 Jul 2024 16:33:48 -0400 Subject: [PATCH] [Flight] Encode the name of a function as an object property (#30325) Unfortunately, Firefox doesn't include the name of a function in stack traces if you set it as either `.name` or `.displayName` at runtime. Only if you include it declarative. We also can't include it into a named function expression because not all possible names are expressible declaratively. E.g. spaces or punctuations. However, we can express any name if it's an object property and since object properties now give their name declarative to the function defined inside of them, we can declaratively express any name this way. --- .../react-client/src/ReactFlightClient.js | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/react-client/src/ReactFlightClient.js b/packages/react-client/src/ReactFlightClient.js index 03a4ab96c0abc..c0d599297858e 100644 --- a/packages/react-client/src/ReactFlightClient.js +++ b/packages/react-client/src/ReactFlightClient.js @@ -1891,19 +1891,33 @@ function createFakeFunction( const comment = '/* This module was rendered by a Server Component. Turn on Source Maps to see the server source. */'; + if (!name) { + // An eval:ed function with no name gets the name "eval". We give it something more descriptive. + name = '(anonymous)'; + } + const encodedName = JSON.stringify(name); // We generate code where the call is at the line and column of the server executed code. // This allows us to use the original source map as the source map of this fake file to // point to the original source. let code; if (line <= 1) { - code = '_=>' + ' '.repeat(col < 4 ? 0 : col - 4) + '_()\n' + comment; + const minSize = encodedName.length + 7; + code = + '({' + + encodedName + + ':_=>' + + ' '.repeat(col < minSize ? 0 : col - minSize) + + '_()})\n' + + comment; } else { code = comment + '\n'.repeat(line - 2) + - '_=>\n' + + '({' + + encodedName + + ':_=>\n' + ' '.repeat(col < 1 ? 0 : col - 1) + - '_()'; + '_()})'; } if (filename.startsWith('/')) { @@ -1931,7 +1945,7 @@ function createFakeFunction( let fn: FakeFunction; try { // eslint-disable-next-line no-eval - fn = (0, eval)(code); + fn = (0, eval)(code)[name]; } catch (x) { // If eval fails, such as if in an environment that doesn't support it, // we fallback to creating a function here. It'll still have the right @@ -1940,10 +1954,6 @@ function createFakeFunction( return _(); }; } - // $FlowFixMe[cannot-write] - Object.defineProperty(fn, 'name', {value: name || '(anonymous)'}); - // $FlowFixMe[prop-missing] - fn.displayName = name; return fn; }