Skip to content

Commit 6295899

Browse files
committed
Add filterStackFrame options to FlightServer
This lets you customize the filter, for example allowing node_modules or filter out additional functions that you don't want to include when sending the stack to the client.
1 parent b943feb commit 6295899

File tree

11 files changed

+140
-37
lines changed

11 files changed

+140
-37
lines changed

packages/react-client/src/__tests__/ReactFlight-test.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3006,4 +3006,58 @@ describe('ReactFlight', () => {
30063006
{withoutStack: true},
30073007
);
30083008
});
3009+
3010+
it('can filter out stack frames of a serialized error in dev', async () => {
3011+
async function bar() {
3012+
throw new Error('my-error');
3013+
}
3014+
3015+
async function intermediate() {
3016+
await bar();
3017+
}
3018+
3019+
async function foo() {
3020+
await intermediate();
3021+
}
3022+
3023+
const rejectedPromise = foo();
3024+
const transport = ReactNoopFlightServer.render(
3025+
{model: rejectedPromise},
3026+
{
3027+
onError(x) {
3028+
return `digest("${x.message}")`;
3029+
},
3030+
filterStackFrame(url, functionName) {
3031+
return functionName !== 'intermediate';
3032+
},
3033+
},
3034+
);
3035+
3036+
let originalError;
3037+
try {
3038+
await rejectedPromise;
3039+
} catch (x) {
3040+
originalError = x;
3041+
}
3042+
3043+
const root = await ReactNoopFlightClient.read(transport);
3044+
let caughtError;
3045+
try {
3046+
await root.model;
3047+
} catch (x) {
3048+
caughtError = x;
3049+
}
3050+
if (__DEV__) {
3051+
expect(caughtError.message).toBe(originalError.message);
3052+
expect(normalizeCodeLocInfo(caughtError.stack)).toContain(
3053+
'\n in bar (at **)' + '\n in foo (at **)',
3054+
);
3055+
}
3056+
expect(normalizeCodeLocInfo(originalError.stack)).toContain(
3057+
'\n in bar (at **)' +
3058+
'\n in intermediate (at **)' +
3059+
'\n in foo (at **)',
3060+
);
3061+
expect(caughtError.digest).toBe('digest("my-error")');
3062+
});
30093063
});

packages/react-html/src/ReactHTMLServer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ export function renderToMarkup(
168168
handleFlightError,
169169
options ? options.identifierPrefix : undefined,
170170
undefined,
171+
undefined,
171172
'Markup',
172173
undefined,
173174
);

packages/react-noop-renderer/src/ReactNoopFlightServer.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ const ReactNoopFlightServer = ReactFlightServer({
6868

6969
type Options = {
7070
environmentName?: string | (() => string),
71+
filterStackFrame?: (url: string, functionName: string) => boolean,
7172
identifierPrefix?: string,
7273
onError?: (error: mixed) => void,
7374
onPostpone?: (reason: string) => void,
@@ -82,7 +83,9 @@ function render(model: ReactClientValue, options?: Options): Destination {
8283
options ? options.onError : undefined,
8384
options ? options.identifierPrefix : undefined,
8485
options ? options.onPostpone : undefined,
85-
options ? options.environmentName : undefined,
86+
undefined,
87+
__DEV__ && options ? options.environmentName : undefined,
88+
__DEV__ && options ? options.filterStackFrame : undefined,
8689
);
8790
ReactNoopFlightServer.startWork(request);
8891
ReactNoopFlightServer.startFlowing(request, destination);

packages/react-server-dom-esm/src/ReactFlightDOMServerNode.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ function createCancelHandler(request: Request, reason: string) {
6666

6767
type Options = {
6868
environmentName?: string | (() => string),
69+
filterStackFrame?: (url: string, functionName: string) => boolean,
6970
onError?: (error: mixed) => void,
7071
onPostpone?: (reason: string) => void,
7172
identifierPrefix?: string,
@@ -88,8 +89,9 @@ function renderToPipeableStream(
8889
options ? options.onError : undefined,
8990
options ? options.identifierPrefix : undefined,
9091
options ? options.onPostpone : undefined,
91-
options ? options.environmentName : undefined,
9292
options ? options.temporaryReferences : undefined,
93+
__DEV__ && options ? options.environmentName : undefined,
94+
__DEV__ && options ? options.filterStackFrame : undefined,
9395
);
9496
let hasStartedFlowing = false;
9597
startWork(request);

packages/react-server-dom-turbopack/src/ReactFlightDOMServerBrowser.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export type {TemporaryReferenceSet};
4545

4646
type Options = {
4747
environmentName?: string | (() => string),
48+
filterStackFrame?: (url: string, functionName: string) => boolean,
4849
identifierPrefix?: string,
4950
signal?: AbortSignal,
5051
temporaryReferences?: TemporaryReferenceSet,
@@ -63,8 +64,9 @@ function renderToReadableStream(
6364
options ? options.onError : undefined,
6465
options ? options.identifierPrefix : undefined,
6566
options ? options.onPostpone : undefined,
66-
options ? options.environmentName : undefined,
6767
options ? options.temporaryReferences : undefined,
68+
__DEV__ && options ? options.environmentName : undefined,
69+
__DEV__ && options ? options.filterStackFrame : undefined,
6870
);
6971
if (options && options.signal) {
7072
const signal = options.signal;

packages/react-server-dom-turbopack/src/ReactFlightDOMServerEdge.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export type {TemporaryReferenceSet};
4545

4646
type Options = {
4747
environmentName?: string | (() => string),
48+
filterStackFrame?: (url: string, functionName: string) => boolean,
4849
identifierPrefix?: string,
4950
signal?: AbortSignal,
5051
temporaryReferences?: TemporaryReferenceSet,
@@ -63,8 +64,9 @@ function renderToReadableStream(
6364
options ? options.onError : undefined,
6465
options ? options.identifierPrefix : undefined,
6566
options ? options.onPostpone : undefined,
66-
options ? options.environmentName : undefined,
6767
options ? options.temporaryReferences : undefined,
68+
__DEV__ && options ? options.environmentName : undefined,
69+
__DEV__ && options ? options.filterStackFrame : undefined,
6870
);
6971
if (options && options.signal) {
7072
const signal = options.signal;

packages/react-server-dom-turbopack/src/ReactFlightDOMServerNode.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ function createCancelHandler(request: Request, reason: string) {
6767

6868
type Options = {
6969
environmentName?: string | (() => string),
70+
filterStackFrame?: (url: string, functionName: string) => boolean,
7071
onError?: (error: mixed) => void,
7172
onPostpone?: (reason: string) => void,
7273
identifierPrefix?: string,
@@ -89,8 +90,9 @@ function renderToPipeableStream(
8990
options ? options.onError : undefined,
9091
options ? options.identifierPrefix : undefined,
9192
options ? options.onPostpone : undefined,
92-
options ? options.environmentName : undefined,
9393
options ? options.temporaryReferences : undefined,
94+
__DEV__ && options ? options.environmentName : undefined,
95+
__DEV__ && options ? options.filterStackFrame : undefined,
9496
);
9597
let hasStartedFlowing = false;
9698
startWork(request);

packages/react-server-dom-webpack/src/ReactFlightDOMServerBrowser.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export type {TemporaryReferenceSet};
4545

4646
type Options = {
4747
environmentName?: string | (() => string),
48+
filterStackFrame?: (url: string, functionName: string) => boolean,
4849
identifierPrefix?: string,
4950
signal?: AbortSignal,
5051
temporaryReferences?: TemporaryReferenceSet,
@@ -63,8 +64,9 @@ function renderToReadableStream(
6364
options ? options.onError : undefined,
6465
options ? options.identifierPrefix : undefined,
6566
options ? options.onPostpone : undefined,
66-
options ? options.environmentName : undefined,
6767
options ? options.temporaryReferences : undefined,
68+
__DEV__ && options ? options.environmentName : undefined,
69+
__DEV__ && options ? options.filterStackFrame : undefined,
6870
);
6971
if (options && options.signal) {
7072
const signal = options.signal;

packages/react-server-dom-webpack/src/ReactFlightDOMServerEdge.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export type {TemporaryReferenceSet};
4545

4646
type Options = {
4747
environmentName?: string | (() => string),
48+
filterStackFrame?: (url: string, functionName: string) => boolean,
4849
identifierPrefix?: string,
4950
signal?: AbortSignal,
5051
temporaryReferences?: TemporaryReferenceSet,
@@ -63,8 +64,9 @@ function renderToReadableStream(
6364
options ? options.onError : undefined,
6465
options ? options.identifierPrefix : undefined,
6566
options ? options.onPostpone : undefined,
66-
options ? options.environmentName : undefined,
6767
options ? options.temporaryReferences : undefined,
68+
__DEV__ && options ? options.environmentName : undefined,
69+
__DEV__ && options ? options.filterStackFrame : undefined,
6870
);
6971
if (options && options.signal) {
7072
const signal = options.signal;

packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ function createCancelHandler(request: Request, reason: string) {
6767

6868
type Options = {
6969
environmentName?: string | (() => string),
70+
filterStackFrame?: (url: string, functionName: string) => boolean,
7071
onError?: (error: mixed) => void,
7172
onPostpone?: (reason: string) => void,
7273
identifierPrefix?: string,
@@ -89,8 +90,9 @@ function renderToPipeableStream(
8990
options ? options.onError : undefined,
9091
options ? options.identifierPrefix : undefined,
9192
options ? options.onPostpone : undefined,
92-
options ? options.environmentName : undefined,
9393
options ? options.temporaryReferences : undefined,
94+
__DEV__ && options ? options.environmentName : undefined,
95+
__DEV__ && options ? options.filterStackFrame : undefined,
9496
);
9597
let hasStartedFlowing = false;
9698
startWork(request);

0 commit comments

Comments
 (0)