Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions packages/react-native/Libraries/LogBox/Data/LogBoxData.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import type {LogLevel} from './LogBoxLog';
import type {
Category,
ComponentStack,
ComponentStackType,
ExtendedExceptionData,
Message,
} from './parseLogBoxLog';
Expand All @@ -32,7 +31,6 @@ export type LogData = Readonly<{
message: Message,
category: Category,
componentStack: ComponentStack,
componentStackType: ComponentStackType | null,
stack?: string,
}>;

Expand Down Expand Up @@ -238,7 +236,6 @@ export function addLog(log: LogData): void {
stack,
category: log.category,
componentStack: log.componentStack,
componentStackType: log.componentStackType || 'legacy',
}),
);
} catch (error: unknown) {
Expand Down
10 changes: 2 additions & 8 deletions packages/react-native/Libraries/LogBox/Data/LogBoxLog.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import type {
Category,
CodeFrame,
ComponentStack,
ComponentStackType,
Message,
} from './parseLogBoxLog';

Expand Down Expand Up @@ -61,7 +60,6 @@ export type LogBoxLogData = Readonly<{
message: Message,
stack: Stack,
category: string,
componentStackType?: ComponentStackType,
componentStack: ComponentStack,
codeFrame?: ?CodeFrame,
isComponentError: boolean,
Expand All @@ -74,7 +72,6 @@ class LogBoxLog {
type: ?string;
category: Category;
componentStack: ComponentStack;
componentStackType: ComponentStackType;
stack: Stack;
count: number;
level: LogLevel;
Expand Down Expand Up @@ -113,7 +110,6 @@ class LogBoxLog {
this.stack = data.stack;
this.category = data.category;
this.componentStack = data.componentStack;
this.componentStackType = data.componentStackType || 'legacy';
this.codeFrame = data.codeFrame;
this.isComponentError = data.isComponentError;
this.extraData = data.extraData;
Expand All @@ -132,9 +128,6 @@ class LogBoxLog {
}

getAvailableComponentStack(): ComponentStack {
if (this.componentStackType === 'legacy') {
return this.componentStack;
}
return this.symbolicatedComponentStack.status === 'COMPLETE'
? this.symbolicatedComponentStack.componentStack
: this.componentStack;
Expand Down Expand Up @@ -180,7 +173,7 @@ class LogBoxLog {
}
if (
this.componentStack != null &&
this.componentStackType === 'stack' &&
this.componentStack.length > 0 &&
this.symbolicatedComponentStack.status !== 'PENDING' &&
this.symbolicatedComponentStack.status !== 'COMPLETE'
) {
Expand All @@ -192,6 +185,7 @@ class LogBoxLog {
data => {
this.updateComponentStackStatus(
null,
// TODO: we shouldn't need to convert back to ComponentStack any more
convertStackToComponentStack(data.stack),
data?.codeFrame,
callback,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ const addLogs = (logs: Array<string>, options: void | {flush: boolean}) => {
},
category: message,
componentStack: [],
componentStackType: null,
});
if (options == null || options.flush !== false) {
jest.runOnlyPendingTimers();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,37 +40,13 @@ const COMPONENT_CODE_FRAME: CodeCodeFrame = {
content: 'Component',
};

// We can delete this when we delete legacy component stack types.
function getLogBoxLogLegacy() {
return new (require('../LogBoxLog').default)({
level: 'warn',
isComponentError: false,
message: {content: '...', substitutions: []},
stack: createStack(['A', 'B', 'C']),
category: 'Message category...',
componentStack: [
{
content: 'LogBoxLog',
fileName: 'LogBoxLog.js',
location: {column: -1, row: 1},
},
],
codeFrame: {
fileName: '/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js',
location: {row: 199, column: 0},
content: '<code frame>',
},
});
}

function getLogBoxLog() {
return new (require('../LogBoxLog').default)({
level: 'warn',
isComponentError: false,
message: {content: '...', substitutions: []},
stack: createStack(['A', 'B', 'C']),
category: 'Message category...',
componentStackType: 'stack',
componentStack: createComponentStack(['A', 'B', 'C']),
codeFrame: null,
});
Expand Down Expand Up @@ -148,243 +124,6 @@ describe('LogBoxLog', () => {
);
});

describe('symbolicate legacy component stacks (no symbolication)', () => {
it('creates a LogBoxLog object', () => {
const log = getLogBoxLogLegacy();

expect(log.level).toEqual('warn');
expect(log.message).toEqual({content: '...', substitutions: []});
expect(log.stack).toEqual(createStack(['A', 'B', 'C']));
expect(log.category).toEqual('Message category...');
expect(log.componentStack).toEqual([
{
content: 'LogBoxLog',
fileName: 'LogBoxLog.js',
location: {column: -1, row: 1},
},
]);
expect(log.codeFrame).toEqual({
fileName: '/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js',
location: {row: 199, column: 0},
content: '<code frame>',
});
});

it('increments LogBoxLog count', () => {
const log = getLogBoxLogLegacy();

expect(log.count).toEqual(1);

log.incrementCount();

expect(log.count).toEqual(2);
});

it('starts without a symbolicated stack', () => {
const log = getLogBoxLogLegacy();

expect(log.symbolicated).toEqual({
error: null,
stack: null,
status: 'NONE',
});
});

it('updates when symbolication is in progress', () => {
const log = getLogBoxLogLegacy();

const callback = jest.fn();
log.symbolicate(callback);

expect(callback).toBeCalledTimes(1);
expect(callback).toBeCalledWith('PENDING');
expect(getLogBoxSymbolication().symbolicate).toBeCalledTimes(1);
expect(log.symbolicated).toEqual({
error: null,
stack: null,
status: 'PENDING',
});

// Symbolicating while pending should not make more requests.
callback.mockClear();
getLogBoxSymbolication().symbolicate.mockClear();

log.symbolicate(callback);
expect(callback).not.toBeCalled();
expect(getLogBoxSymbolication().symbolicate).not.toBeCalled();
});

it('updates when symbolication finishes', async () => {
const log = getLogBoxLogLegacy();

const callback = jest.fn();
log.symbolicate(callback);
expect(callback).toBeCalledTimes(1);
expect(callback).toBeCalledWith('PENDING');
expect(getLogBoxSymbolication().symbolicate).toBeCalled();

await runMicrotasks();

expect(callback).toBeCalledTimes(2);
expect(callback).toBeCalledWith('COMPLETE');
expect(log.symbolicated).toEqual({
error: null,
stack: createStack(['S(A)', 'S(B)', 'S(C)']),
status: 'COMPLETE',
});

// Do not symbolicate again.
callback.mockClear();
getLogBoxSymbolication().symbolicate.mockClear();

log.symbolicate(callback);

await runMicrotasks();

expect(callback).toBeCalledTimes(0);
expect(getLogBoxSymbolication().symbolicate).not.toBeCalled();
});

it('updates when symbolication fails', async () => {
const error = new Error('...');
getLogBoxSymbolication().symbolicate.mockImplementation(async stack => {
throw error;
});

const log = getLogBoxLogLegacy();

const callback = jest.fn();
log.symbolicate(callback);
expect(callback).toBeCalledTimes(1);
expect(callback).toBeCalledWith('PENDING');
expect(getLogBoxSymbolication().symbolicate).toBeCalled();

await runMicrotasks();

expect(callback).toBeCalledTimes(2);
expect(callback).toBeCalledWith('FAILED');
expect(log.symbolicated).toEqual({
error,
stack: null,
status: 'FAILED',
});

// Do not symbolicate again, retry if needed.
callback.mockClear();
getLogBoxSymbolication().symbolicate.mockClear();

log.symbolicate(callback);

await runMicrotasks();

expect(callback).toBeCalledTimes(0);
expect(getLogBoxSymbolication().symbolicate).not.toBeCalled();
});

it('retry updates when symbolication is in progress', () => {
const log = getLogBoxLogLegacy();

const callback = jest.fn();
log.retrySymbolicate(callback);

expect(callback).toBeCalledTimes(1);
expect(callback).toBeCalledWith('PENDING');
expect(getLogBoxSymbolication().symbolicate).toBeCalledTimes(1);
expect(log.symbolicated).toEqual({
error: null,
stack: null,
status: 'PENDING',
});

// Symbolicating while pending should not make more requests.
callback.mockClear();
getLogBoxSymbolication().symbolicate.mockClear();

log.symbolicate(callback);
expect(callback).not.toBeCalled();
expect(getLogBoxSymbolication().symbolicate).not.toBeCalled();
});

it('retry updates when symbolication finishes', async () => {
const log = getLogBoxLogLegacy();

const callback = jest.fn();
log.retrySymbolicate(callback);
expect(callback).toBeCalledTimes(1);
expect(callback).toBeCalledWith('PENDING');
expect(getLogBoxSymbolication().symbolicate).toBeCalled();

await runMicrotasks();

expect(callback).toBeCalledTimes(2);
expect(callback).toBeCalledWith('COMPLETE');
expect(log.symbolicated).toEqual({
error: null,
stack: createStack(['S(A)', 'S(B)', 'S(C)']),
status: 'COMPLETE',
});

// Do not symbolicate again
callback.mockClear();
getLogBoxSymbolication().symbolicate.mockClear();

log.retrySymbolicate(callback);
jest.runAllTicks();

expect(callback).toBeCalledTimes(0);
expect(getLogBoxSymbolication().symbolicate).not.toBeCalled();
});

it('retry updates when symbolication fails', async () => {
const error = new Error('...');
getLogBoxSymbolication().symbolicate.mockImplementation(async stack => {
throw error;
});

const log = getLogBoxLogLegacy();

const callback = jest.fn();
log.retrySymbolicate(callback);
expect(callback).toBeCalledTimes(1);
expect(callback).toBeCalledWith('PENDING');
expect(getLogBoxSymbolication().symbolicate).toBeCalled();

await runMicrotasks();

expect(callback).toBeCalledTimes(2);
expect(callback).toBeCalledWith('FAILED');
expect(log.symbolicated).toEqual({
error,
stack: null,
status: 'FAILED',
});

// Retry to symbolicate again.
callback.mockClear();
getLogBoxSymbolication().symbolicate.mockClear();
getLogBoxSymbolication().symbolicate.mockImplementation(async stack => ({
stack: createStack(stack.map(frame => `S(${frame.methodName})`)),
codeFrame: null,
}));

log.retrySymbolicate(callback);

expect(callback).toBeCalledTimes(1);
expect(callback).toBeCalledWith('PENDING');
expect(getLogBoxSymbolication().symbolicate).toBeCalled();

await runMicrotasks();

expect(callback).toBeCalledTimes(2);
expect(callback).toBeCalledWith('COMPLETE');
expect(log.symbolicated).toEqual({
error: null,
stack: createStack(['S(A)', 'S(B)', 'S(C)']),
status: 'COMPLETE',
});
});
});

describe('symbolicate component stacks', () => {
it('creates a LogBoxLog object', () => {
const log = getLogBoxLog();
Expand Down
Loading
Loading