diff --git a/Libraries/LogBox/Data/LogBoxData.js b/Libraries/LogBox/Data/LogBoxData.js index 9e1a4de3f8..4207d8bf1e 100644 --- a/Libraries/LogBox/Data/LogBoxData.js +++ b/Libraries/LogBox/Data/LogBoxData.js @@ -12,6 +12,7 @@ import LogBoxLog from './LogBoxLog'; import parseLogBoxLog from './parseLogBoxLog'; +import type {LogLevel} from './LogBoxLog'; export type LogBoxLogs = Set; @@ -52,7 +53,7 @@ function handleUpdate(): void { } } -export function add(args: $ReadOnlyArray): void { +export function add(level: LogLevel, args: $ReadOnlyArray): void { // This is carried over from the old YellowBox, but it is not clear why. if (typeof args[0] === 'string' && args[0].startsWith('(ADVICE)')) { return; @@ -75,7 +76,7 @@ export function add(args: $ReadOnlyArray): void { if (lastLog && lastLog.category === category) { lastLog.incrementCount(); } else { - logs.add(new LogBoxLog(message, stack, category, componentStack)); + logs.add(new LogBoxLog(level, message, stack, category, componentStack)); } handleUpdate(); diff --git a/Libraries/LogBox/Data/LogBoxLog.js b/Libraries/LogBox/Data/LogBoxLog.js index 937b80680a..5e3b59c038 100644 --- a/Libraries/LogBox/Data/LogBoxLog.js +++ b/Libraries/LogBox/Data/LogBoxLog.js @@ -15,6 +15,8 @@ import * as LogBoxSymbolication from './LogBoxSymbolication'; import type {Category, Message, ComponentStack} from './parseLogBoxLog'; import type {Stack} from './LogBoxSymbolication'; +export type LogLevel = 'warn' | 'error'; + export type SymbolicationRequest = $ReadOnly<{| abort: () => void, |}>; @@ -25,6 +27,7 @@ class LogBoxLog { componentStack: ComponentStack; stack: Stack; count: number; + level: LogLevel; symbolicated: | $ReadOnly<{|error: null, stack: null, status: 'NONE'|}> | $ReadOnly<{|error: null, stack: null, status: 'PENDING'|}> @@ -36,11 +39,13 @@ class LogBoxLog { }; constructor( + level: LogLevel, message: Message, stack: Stack, category: string, componentStack: ComponentStack, ) { + this.level = level; this.message = message; this.stack = stack; this.category = category; diff --git a/Libraries/LogBox/Data/__tests__/LogBoxData-test.js b/Libraries/LogBox/Data/__tests__/LogBoxData-test.js index 78b221426f..340d8e8cb1 100644 --- a/Libraries/LogBox/Data/__tests__/LogBoxData-test.js +++ b/Libraries/LogBox/Data/__tests__/LogBoxData-test.js @@ -42,7 +42,7 @@ describe('LogBoxData', () => { }); it('adds and dismisses logs', () => { - LogBoxData.add(['A']); + LogBoxData.add('warn', ['A']); expect(registry().length).toBe(1); expect(registry()[0]).toBeDefined(); @@ -53,9 +53,9 @@ describe('LogBoxData', () => { }); it('clears all logs', () => { - LogBoxData.add(['A']); - LogBoxData.add(['B']); - LogBoxData.add(['C']); + LogBoxData.add('warn', ['A']); + LogBoxData.add('warn', ['B']); + LogBoxData.add('warn', ['C']); expect(registry().length).toBe(3); @@ -64,9 +64,9 @@ describe('LogBoxData', () => { }); it('keeps logs in chronological order', () => { - LogBoxData.add(['A']); - LogBoxData.add(['B']); - LogBoxData.add(['C']); + LogBoxData.add('warn', ['A']); + LogBoxData.add('warn', ['B']); + LogBoxData.add('warn', ['C']); let logs = registry(); expect(logs.length).toBe(3); @@ -74,7 +74,7 @@ describe('LogBoxData', () => { expect(logs[1].category).toEqual('B'); expect(logs[2].category).toEqual('C'); - LogBoxData.add(['A']); + LogBoxData.add('warn', ['A']); // Expect `A` to be added to the end of the registry. logs = registry(); @@ -86,8 +86,8 @@ describe('LogBoxData', () => { }); it('increments the count of previous log with matching category', () => { - LogBoxData.add(['A']); - LogBoxData.add(['B']); + LogBoxData.add('warn', ['A']); + LogBoxData.add('warn', ['B']); let logs = registry(); expect(logs.length).toBe(2); @@ -96,7 +96,7 @@ describe('LogBoxData', () => { expect(logs[1].category).toEqual('B'); expect(logs[1].count).toBe(1); - LogBoxData.add(['B']); + LogBoxData.add('warn', ['B']); // Expect `B` to be rolled into the last log. logs = registry(); @@ -108,9 +108,9 @@ describe('LogBoxData', () => { }); it('ignores logs matching patterns', () => { - LogBoxData.add(['A!']); - LogBoxData.add(['B?']); - LogBoxData.add(['C!']); + LogBoxData.add('warn', ['A!']); + LogBoxData.add('warn', ['B?']); + LogBoxData.add('warn', ['C!']); expect(filteredRegistry().length).toBe(3); LogBoxData.addIgnorePatterns(['!']); @@ -121,9 +121,9 @@ describe('LogBoxData', () => { }); it('ignores logs matching regexs or pattern', () => { - LogBoxData.add(['There are 4 dogs']); - LogBoxData.add(['There are 3 cats']); - LogBoxData.add(['There are H cats']); + LogBoxData.add('warn', ['There are 4 dogs']); + LogBoxData.add('warn', ['There are 3 cats']); + LogBoxData.add('warn', ['There are H cats']); expect(filteredRegistry().length).toBe(3); LogBoxData.addIgnorePatterns(['dogs']); @@ -137,9 +137,9 @@ describe('LogBoxData', () => { }); it('ignores all logs when disabled', () => { - LogBoxData.add(['A!']); - LogBoxData.add(['B?']); - LogBoxData.add(['C!']); + LogBoxData.add('warn', ['A!']); + LogBoxData.add('warn', ['B?']); + LogBoxData.add('warn', ['C!']); expect(registry().length).toBe(3); LogBoxData.setDisabled(true); @@ -150,56 +150,56 @@ describe('LogBoxData', () => { }); it('groups consecutive logs by format string categories', () => { - LogBoxData.add(['%s', 'A']); + LogBoxData.add('warn', ['%s', 'A']); expect(registry().length).toBe(1); expect(registry()[0].count).toBe(1); - LogBoxData.add(['%s', 'B']); + LogBoxData.add('warn', ['%s', 'B']); expect(registry().length).toBe(1); expect(registry()[0].count).toBe(2); - LogBoxData.add(['A']); + LogBoxData.add('warn', ['A']); expect(registry().length).toBe(2); expect(registry()[1].count).toBe(1); - LogBoxData.add(['B']); + LogBoxData.add('warn', ['B']); expect(registry().length).toBe(3); expect(registry()[2].count).toBe(1); }); it('groups warnings with consideration for arguments', () => { - LogBoxData.add(['A', 'B']); + LogBoxData.add('warn', ['A', 'B']); expect(registry().length).toBe(1); expect(registry()[0].count).toBe(1); - LogBoxData.add(['A', 'B']); + LogBoxData.add('warn', ['A', 'B']); expect(registry().length).toBe(1); expect(registry()[0].count).toBe(2); - LogBoxData.add(['A', 'C']); + LogBoxData.add('warn', ['A', 'C']); expect(registry().length).toBe(2); expect(registry()[1].count).toBe(1); - LogBoxData.add(['%s', 'A', 'A']); + LogBoxData.add('warn', ['%s', 'A', 'A']); expect(registry().length).toBe(3); expect(registry()[2].count).toBe(1); - LogBoxData.add(['%s', 'B', 'A']); + LogBoxData.add('warn', ['%s', 'B', 'A']); expect(registry().length).toBe(3); expect(registry()[2].count).toBe(2); - LogBoxData.add(['%s', 'B', 'B']); + LogBoxData.add('warn', ['%s', 'B', 'B']); expect(registry().length).toBe(4); expect(registry()[3].count).toBe(1); }); it('ignores logs starting with "(ADVICE)"', () => { - LogBoxData.add(['(ADVICE) ...']); + LogBoxData.add('warn', ['(ADVICE) ...']); expect(registry().length).toBe(0); }); it('does not ignore logs formatted to start with "(ADVICE)"', () => { - LogBoxData.add(['%s ...', '(ADVICE)']); + LogBoxData.add('warn', ['%s ...', '(ADVICE)']); expect(registry().length).toBe(1); }); @@ -218,8 +218,8 @@ describe('LogBoxData', () => { const {observer} = observe(); expect(observer.mock.calls.length).toBe(1); - LogBoxData.add(['A']); - LogBoxData.add(['B']); + LogBoxData.add('warn', ['A']); + LogBoxData.add('warn', ['B']); jest.runAllImmediates(); expect(observer.mock.calls.length).toBe(2); @@ -244,7 +244,7 @@ describe('LogBoxData', () => { const {observer} = observe(); expect(observer.mock.calls.length).toBe(1); - LogBoxData.add(['A']); + LogBoxData.add('warn', ['A']); jest.runAllImmediates(); expect(observer.mock.calls.length).toBe(2); @@ -263,7 +263,7 @@ describe('LogBoxData', () => { const {observer} = observe(); expect(observer.mock.calls.length).toBe(1); - LogBoxData.add(['A']); + LogBoxData.add('warn', ['A']); jest.runAllImmediates(); expect(observer.mock.calls.length).toBe(2); diff --git a/Libraries/LogBox/Data/__tests__/LogBoxLog-test.js b/Libraries/LogBox/Data/__tests__/LogBoxLog-test.js index 25a4fc71c9..482908de3b 100644 --- a/Libraries/LogBox/Data/__tests__/LogBoxLog-test.js +++ b/Libraries/LogBox/Data/__tests__/LogBoxLog-test.js @@ -19,6 +19,7 @@ jest.mock('../LogBoxSymbolication', () => { function getLogBoxLog() { return new (require('../LogBoxLog')).default( + 'warn', {content: '...', substitutions: []}, createStack(['A', 'B', 'C']), 'Message category...', diff --git a/Libraries/LogBox/LogBox.js b/Libraries/LogBox/LogBox.js index 19c907a01b..66f4498fab 100644 --- a/Libraries/LogBox/LogBox.js +++ b/Libraries/LogBox/LogBox.js @@ -59,13 +59,15 @@ if (__DEV__) { error.call(console, ...args); // Show LogBox for the `warning` module. if (typeof args[0] === 'string' && args[0].startsWith('Warning: ')) { - registerLog(...args); + registerWarning(...args); + } else { + registerError(...args); } }; warnImpl = function(...args) { warn.call(console, ...args); - registerLog(...args); + registerWarning(...args); }; if ((console: any).disableLogBox === true) { @@ -82,7 +84,7 @@ if (__DEV__) { } RCTLog.setWarningHandler((...args) => { - registerLog(...args); + registerWarning(...args); }); } @@ -130,8 +132,12 @@ if (__DEV__) { } }; - const registerLog = (...args): void => { - LogBoxData.add(args); + const registerWarning = (...args): void => { + LogBoxData.add('warn', args); + }; + + const registerError = (...args): void => { + LogBoxData.add('error', args); }; } else { LogBoxComponent = class extends React.Component { diff --git a/Libraries/LogBox/UI/__tests__/LogBoxContainer-test.js b/Libraries/LogBox/UI/__tests__/LogBoxContainer-test.js index 385472cf03..c39cc1cfd4 100644 --- a/Libraries/LogBox/UI/__tests__/LogBoxContainer-test.js +++ b/Libraries/LogBox/UI/__tests__/LogBoxContainer-test.js @@ -37,6 +37,7 @@ describe('LogBoxContainer', () => { logs={ new Set([ new LogBoxLog( + 'warn', { content: 'Some kind of message', substitutions: [], @@ -46,6 +47,7 @@ describe('LogBoxContainer', () => { [], ), new LogBoxLog( + 'warn', { content: 'Some kind of message (latest)', substitutions: [], diff --git a/Libraries/LogBox/UI/__tests__/LogBoxInspector-test.js b/Libraries/LogBox/UI/__tests__/LogBoxInspector-test.js index 5351e14713..5cbad8f355 100644 --- a/Libraries/LogBox/UI/__tests__/LogBoxInspector-test.js +++ b/Libraries/LogBox/UI/__tests__/LogBoxInspector-test.js @@ -18,6 +18,7 @@ const render = require('../../../../jest/renderer'); const logs = [ new LogBoxLog( + 'warn', { content: 'Some kind of message (first)', substitutions: [], @@ -27,6 +28,7 @@ const logs = [ [], ), new LogBoxLog( + 'warn', { content: 'Some kind of message (second)', substitutions: [], diff --git a/Libraries/LogBox/UI/__tests__/LogBoxInspectorReactFrames-test.js b/Libraries/LogBox/UI/__tests__/LogBoxInspectorReactFrames-test.js index dc80098112..d79d2ae2b7 100644 --- a/Libraries/LogBox/UI/__tests__/LogBoxInspectorReactFrames-test.js +++ b/Libraries/LogBox/UI/__tests__/LogBoxInspectorReactFrames-test.js @@ -23,6 +23,7 @@ describe('LogBoxInspectorReactFrames', () => { { { LogBox.install(); console.error('...'); - expect(LogBoxData.add).not.toBeCalled(); + expect(LogBoxData.add).toBeCalledWith('error', ['...']); console.error('Warning: ...'); - expect(LogBoxData.add).toBeCalled(); + expect(LogBoxData.add).toBeCalledWith('warn', ['Warning: ...']); }); });