Skip to content

Commit cb9ef09

Browse files
apply requested changes / add sample staccktrace / new test for console sandbox
1 parent 1b1f86f commit cb9ef09

File tree

3 files changed

+109
-73
lines changed

3 files changed

+109
-73
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
Sample stack trace when calling `symbolicateStackTrace` from debugsymbolicator, with console integration enabled, with assert filter.
2+
3+
LOG Assertion called: true message 'this' is expected an Event object, but got [{"isTrusted":false}] stack : Error
4+
at getCurrentStackTrace (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:125938:26)
5+
at anonymous (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:125950:57)
6+
at apply (native)
7+
at anonymous (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:154465:27)
8+
at pd (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:36235:19)
9+
at setPassiveListener (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:36640:7)
10+
at dispatchEvent (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:36939:27)
11+
at setReadyState (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:36129:27)
12+
at open (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:36041:27)
13+
at apply (native)
14+
at anonymous (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:155583:34)
15+
at anonymous (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:29261:17)
16+
at tryCallTwo (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204678:9)
17+
at doResolve (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204817:25)
18+
at Promise (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204697:14)
19+
at fetch (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:29218:25)
20+
at ?anon_0_ (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28649:33)
21+
at next (native)
22+
at asyncGeneratorStep (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28665:26)
23+
at _next (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28684:29)
24+
at anonymous (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28689:14)
25+
at tryCallTwo (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204678:9)
26+
at doResolve (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204817:25)
27+
at Promise (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:204697:14)
28+
at anonymous (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28681:25)
29+
at apply (native)
30+
at _symbolicateStackTrace (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28658:40)
31+
at apply (native)
32+
at symbolicateStackTrace (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28637:40)
33+
at symbolicate (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28616:52)
34+
at handleSymbolicate (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28516:42)
35+
at symbolicate (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28507:33)
36+
at appendNewLog (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28152:25)
37+
at anonymous (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:28196:21)
38+
at apply (native)
39+
at anonymous (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:35288:26)
40+
at _callTimer (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:35167:17)
41+
at _callReactNativeMicrotasksPass (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:35212:17)
42+
at callReactNativeMicrotasks (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:35418:44)
43+
at __callReactNativeMicrotasks (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:3569:48)
44+
at anonymous (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:3342:45)
45+
at __guard (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:3541:15)
46+
at flushedQueue (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:3341:21)
47+
at callFunctionReturnFlushedQueue (http://IP/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=io.sentry.reactnative.sample&modulesOnly=false&runModule=true:3326:33)

packages/core/src/js/integrations/debugsymbolicator.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,6 @@ export const debugSymbolicatorIntegration = (): Integration => {
3333
};
3434

3535
async function processEvent(event: Event, hint: EventHint): Promise<Event> {
36-
return consoleSandbox(async () => {
37-
// event created by consoleIntegration, symbolicator can trigger those events.
38-
// so we drop the event to avoid an infinite loop.
39-
// @ts-ignore lets ignore for now
40-
console.assert(false, ' deadlock test');
41-
if (
42-
event.extra?.['arguments'] &&
43-
event.message?.startsWith("Assertion failed: 'this' is expected an Event object, but got")
44-
) {
45-
return event;
46-
}
4736
if (event.exception?.values && isErrorLike(hint.originalException)) {
4837
// originalException is ErrorLike object
4938
const errorGroup = getExceptionGroup(hint.originalException);
@@ -69,8 +58,7 @@ async function processEvent(event: Event, hint: EventHint): Promise<Event> {
6958
}
7059
}
7160

72-
return event;
73-
});
61+
return event;
7462
}
7563

7664
/**
@@ -81,7 +69,9 @@ async function symbolicate(rawStack: string, skipFirstFrames: number = 0): Promi
8169
try {
8270
const parsedStack = parseErrorStack(rawStack);
8371

84-
const prettyStack = await symbolicateStackTrace(parsedStack);
72+
// Avoid capturing console logs as events when calling symbolicateStackTrace to avoid infinite loops.
73+
// See file `debugsymbolicator.consoleissue.txt` for a sample stack-trace with this problem.
74+
const prettyStack = await consoleSandbox(async () => symbolicateStackTrace(parsedStack));
8575
if (!prettyStack) {
8676
logger.error('React Native DevServer could not symbolicate the stack trace.');
8777
return null;

packages/core/test/integrations/debugsymbolicator.test.ts

Lines changed: 58 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
jest.mock('../../src/js/integrations/debugsymbolicatorutils');
22

3-
import type { Client, Event, EventHint, StackFrame } from '@sentry/core';
3+
import {
4+
type Client,
5+
type Event,
6+
type EventHint,
7+
type StackFrame,
8+
captureConsoleIntegration,
9+
setCurrentClient,
10+
} from '@sentry/core';
411

512
import { debugSymbolicatorIntegration } from '../../src/js/integrations/debugsymbolicator';
613
import {
@@ -9,8 +16,8 @@ import {
916
parseErrorStack,
1017
symbolicateStackTrace,
1118
} from '../../src/js/integrations/debugsymbolicatorutils';
12-
import * as ErrorUtils from '../../src/js/utils/error';
1319
import type * as ReactNative from '../../src/js/vendor/react-native';
20+
import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
1421

1522
async function processEvent(mockedEvent: Event, mockedHint: EventHint): Promise<Event | null> {
1623
return debugSymbolicatorIntegration().processEvent!(mockedEvent, mockedHint, {} as Client);
@@ -366,63 +373,6 @@ describe('Debug Symbolicator Integration', () => {
366373
});
367374
});
368375

369-
it('skips metro events created by Sentry console integration', async () => {
370-
const spy = jest.spyOn(ErrorUtils, 'isErrorLike').mockImplementation(() => {
371-
throw new Error('only first if condition should be called');
372-
});
373-
374-
const symbolicatedEvent = await processEvent(
375-
{
376-
exception: {
377-
values: [],
378-
},
379-
extra: {
380-
arguments: [false, "'this' is expected an Event object, but got", '<object>'],
381-
},
382-
message: "Assertion failed: 'this' is expected an Event object, but got",
383-
},
384-
{},
385-
);
386-
387-
expect(symbolicatedEvent).toStrictEqual(<Event>{
388-
exception: {
389-
values: [],
390-
},
391-
extra: {
392-
arguments: [false, "'this' is expected an Event object, but got", '<object>'],
393-
},
394-
message: "Assertion failed: 'this' is expected an Event object, but got",
395-
});
396-
397-
// This is the second if condition after the tested element, it is here to make sure the returned code
398-
// came from the console filter.
399-
expect(spy).not.toHaveBeenCalled();
400-
spy.mockRestore();
401-
});
402-
403-
it('do not skip events similar to metro events created by Sentry console integration', async () => {
404-
const spy = jest.spyOn(ErrorUtils, 'isErrorLike').mockImplementation(() => {
405-
throw new Error('second if condition called.');
406-
});
407-
408-
try {
409-
await processEvent(
410-
{
411-
exception: {
412-
values: [],
413-
},
414-
message: "Assertion failed: 'this' is expected an Event object, but got",
415-
},
416-
{},
417-
);
418-
} catch (err: Error | unknown) {
419-
expect((err as Error).message).toBe('second if condition called.');
420-
} finally {
421-
expect(spy).toHaveBeenCalled();
422-
spy.mockRestore();
423-
}
424-
});
425-
426376
it('should symbolicate error with cause ', async () => {
427377
(parseErrorStack as jest.Mock)
428378
.mockReturnValueOnce(<Array<ReactNative.StackFrame>>[
@@ -902,5 +852,54 @@ describe('Debug Symbolicator Integration', () => {
902852
},
903853
});
904854
});
855+
856+
it('should not capture console events when symbolicating the stack trace', async () => {
857+
(symbolicateStackTrace as jest.Mock).mockImplementation(() => {
858+
// eslint-disable-next-line no-console
859+
console.assert(false, 'should not be logged as an event', '<object>');
860+
return Promise.resolve({
861+
stack: [],
862+
} as ReactNative.SymbolicatedStackTrace);
863+
});
864+
865+
const client = new TestClient(getDefaultTestClientOptions());
866+
setCurrentClient(client);
867+
client.addIntegration(captureConsoleIntegration({ levels: ['assert'] }));
868+
client.init();
869+
870+
const symbolicatedEvent = await processEvent(
871+
{
872+
threads: {
873+
values: [
874+
{
875+
stacktrace: {
876+
frames: mockSentryParsedFrames,
877+
},
878+
},
879+
],
880+
},
881+
},
882+
{
883+
syntheticException: {
884+
stack: mockRawStack,
885+
framesToPop: 2,
886+
} as unknown as Error,
887+
},
888+
);
889+
890+
// An event with the console log will be captured here if failed
891+
expect(client.event).toBeUndefined();
892+
expect(symbolicatedEvent).toStrictEqual(<Event>{
893+
threads: {
894+
values: [
895+
{
896+
stacktrace: {
897+
frames: [],
898+
},
899+
},
900+
],
901+
},
902+
});
903+
});
905904
});
906905
});

0 commit comments

Comments
 (0)