123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- /**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @flow
- * @format
- */
- 'use strict';
- import Platform from '../Utilities/Platform';
- import RCTLog from '../Utilities/RCTLog';
- import * as LogBoxData from './Data/LogBoxData';
- import {parseLogBoxLog, parseInterpolation} from './Data/parseLogBoxLog';
- import type {IgnorePattern} from './Data/LogBoxData';
- let LogBox;
- /**
- * LogBox displays logs in the app.
- */
- if (__DEV__) {
- // LogBox needs to insert itself early,
- // in order to access the component stacks appended by React DevTools.
- const {error, warn} = console;
- let errorImpl = error.bind(console);
- let warnImpl = warn.bind(console);
- (console: any).error = function(...args) {
- errorImpl(...args);
- };
- (console: any).warn = function(...args) {
- warnImpl(...args);
- };
- LogBox = {
- ignoreLogs: (patterns: $ReadOnlyArray<IgnorePattern>): void => {
- LogBoxData.addIgnorePatterns(patterns);
- },
- ignoreAllLogs: (value?: ?boolean): void => {
- LogBoxData.setDisabled(value == null ? true : value);
- },
- uninstall: (): void => {
- errorImpl = error;
- warnImpl = warn;
- delete (console: any).disableLogBox;
- },
- install: (): void => {
- // Trigger lazy initialization of module.
- require('../NativeModules/specs/NativeLogBox');
- errorImpl = function(...args) {
- registerError(...args);
- };
- warnImpl = function(...args) {
- registerWarning(...args);
- };
- if ((console: any).disableYellowBox === true) {
- LogBoxData.setDisabled(true);
- console.warn(
- 'console.disableYellowBox has been deprecated and will be removed in a future release. Please use LogBox.ignoreAllLogs(value) instead.',
- );
- }
- (Object.defineProperty: any)(console, 'disableYellowBox', {
- configurable: true,
- get: () => LogBoxData.isDisabled(),
- set: value => {
- LogBoxData.setDisabled(value);
- console.warn(
- 'console.disableYellowBox has been deprecated and will be removed in a future release. Please use LogBox.ignoreAllLogs(value) instead.',
- );
- },
- });
- if (Platform.isTesting) {
- LogBoxData.setDisabled(true);
- }
- RCTLog.setWarningHandler((...args) => {
- registerWarning(...args);
- });
- },
- };
- const isRCTLogAdviceWarning = (...args) => {
- // RCTLogAdvice is a native logging function designed to show users
- // a message in the console, but not show it to them in Logbox.
- return typeof args[0] === 'string' && args[0].startsWith('(ADVICE)');
- };
- const isWarningModuleWarning = (...args) => {
- return typeof args[0] === 'string' && args[0].startsWith('Warning: ');
- };
- const registerWarning = (...args): void => {
- // Let warnings within LogBox itself fall through.
- if (LogBoxData.isLogBoxErrorMessage(String(args[0]))) {
- error.call(console, ...args);
- return;
- }
- try {
- if (!isRCTLogAdviceWarning(...args)) {
- const {category, message, componentStack} = parseLogBoxLog(args);
- if (!LogBoxData.isMessageIgnored(message.content)) {
- // Be sure to pass LogBox warnings through.
- warn.call(console, ...args);
- LogBoxData.addLog({
- level: 'warn',
- category,
- message,
- componentStack,
- });
- }
- }
- } catch (err) {
- LogBoxData.reportLogBoxError(err);
- }
- };
- const registerError = (...args): void => {
- // Let errors within LogBox itself fall through.
- if (LogBoxData.isLogBoxErrorMessage(args[0])) {
- error.call(console, ...args);
- return;
- }
- try {
- if (!isWarningModuleWarning(...args)) {
- // Only show LogBox for the 'warning' module, otherwise pass through.
- // By passing through, this will get picked up by the React console override,
- // potentially adding the component stack. React then passes it back to the
- // React Native ExceptionsManager, which reports it to LogBox as an error.
- //
- // The 'warning' module needs to be handled here because React internally calls
- // `console.error('Warning: ')` with the component stack already included.
- error.call(console, ...args);
- return;
- }
- const format = args[0].replace('Warning: ', '');
- const filterResult = LogBoxData.checkWarningFilter(format);
- if (filterResult.suppressCompletely) {
- return;
- }
- let level = 'error';
- if (filterResult.suppressDialog_LEGACY === true) {
- level = 'warn';
- } else if (filterResult.forceDialogImmediately === true) {
- level = 'fatal'; // Do not downgrade. These are real bugs with same severity as throws.
- }
- // Unfortunately, we need to add the Warning: prefix back for downstream dependencies.
- args[0] = `Warning: ${filterResult.finalFormat}`;
- const {category, message, componentStack} = parseLogBoxLog(args);
- if (!LogBoxData.isMessageIgnored(message.content)) {
- // Interpolate the message so they are formatted for adb and other CLIs.
- // This is different than the message.content above because it includes component stacks.
- const interpolated = parseInterpolation(args);
- error.call(console, interpolated.message.content);
- LogBoxData.addLog({
- level,
- category,
- message,
- componentStack,
- });
- }
- } catch (err) {
- LogBoxData.reportLogBoxError(err);
- }
- };
- } else {
- LogBox = {
- ignoreLogs: (patterns: $ReadOnlyArray<IgnorePattern>): void => {
- // Do nothing.
- },
- ignoreAllLogs: (value?: ?boolean): void => {
- // Do nothing.
- },
- install: (): void => {
- // Do nothing.
- },
- uninstall: (): void => {
- // Do nothing.
- },
- };
- }
- module.exports = (LogBox: {
- ignoreLogs($ReadOnlyArray<IgnorePattern>): void,
- ignoreAllLogs(?boolean): void,
- install(): void,
- uninstall(): void,
- ...
- });
|