Skip to content

Commit 93d50a6

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 a6b7e43 commit 93d50a6

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
@@ -3157,4 +3157,58 @@ describe('ReactFlight', () => {
31573157
{withoutStack: true},
31583158
);
31593159
});
3160+
3161+
it('can filter out stack frames of a serialized error in dev', async () => {
3162+
async function bar() {
3163+
throw new Error('my-error');
3164+
}
3165+
3166+
async function intermediate() {
3167+
await bar();
3168+
}
3169+
3170+
async function foo() {
3171+
await intermediate();
3172+
}
3173+
3174+
const rejectedPromise = foo();
3175+
const transport = ReactNoopFlightServer.render(
3176+
{model: rejectedPromise},
3177+
{
3178+
onError(x) {
3179+
return `digest("${x.message}")`;
3180+
},
3181+
filterStackFrame(url, functionName) {
3182+
return functionName !== 'intermediate';
3183+
},
3184+
},
3185+
);
3186+
3187+
let originalError;
3188+
try {
3189+
await rejectedPromise;
3190+
} catch (x) {
3191+
originalError = x;
3192+
}
3193+
3194+
const root = await ReactNoopFlightClient.read(transport);
3195+
let caughtError;
3196+
try {
3197+
await root.model;
3198+
} catch (x) {
3199+
caughtError = x;
3200+
}
3201+
if (__DEV__) {
3202+
expect(caughtError.message).toBe(originalError.message);
3203+
expect(normalizeCodeLocInfo(caughtError.stack)).toContain(
3204+
'\n in bar (at **)' + '\n in foo (at **)',
3205+
);
3206+
}
3207+
expect(normalizeCodeLocInfo(originalError.stack)).toContain(
3208+
'\n in bar (at **)' +
3209+
'\n in intermediate (at **)' +
3210+
'\n in foo (at **)',
3211+
);
3212+
expect(caughtError.digest).toBe('digest("my-error")');
3213+
});
31603214
});

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)