mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Remove console logs from Metro when native debugger console is available
Summary: Changelog: [Internal] Remove console logs from Metro when native Fusebox debugger console is available React Native currently sends all `console.log` messages to Metro, which prints them to the terminal. This feature has been in place since 2019 (D15559151) but is pretty limited when compared to what's available in modern browsers. Most of the limitations can't really be fixed within the constraints of Metro's relatively simple terminal infrastructure. With the new React Native debugger (codenamed "Fusebox") we aim to fundamentally elevate the debugging experience by shipping a well-tested version of Chrome DevTools with React Native. Chrome DevTools has a rich, interactive console, as well as a host of other debugging features we want developers to notice and use. To that end, we plan to **strongly nudge users towards the Fusebox console from day 1**. Specifically, if we detect that Fusebox is available and is using an engine which implements CDP `console` support ( = Hermes only for now), we'll no longer send logs to Metro, and will instead display an explanatory message directing users to Fusebox. Reviewed By: huntie Differential Revision: D54829811 fbshipit-source-id: 2b1cdb666094f901ff4e7f42b123271be4ce7d10
This commit is contained in:
committed by
Facebook GitHub Bot
parent
b79e488cc5
commit
b7c1bd4e89
@@ -42,7 +42,9 @@ if (__DEV__) {
|
||||
if (!Platform.isTesting) {
|
||||
const HMRClient = require('../Utilities/HMRClient');
|
||||
|
||||
if (console._isPolyfilled) {
|
||||
if (global.__FUSEBOX_HAS_FULL_CONSOLE_SUPPORT__) {
|
||||
HMRClient.unstable_notifyFuseboxConsoleEnabled();
|
||||
} else if (console._isPolyfilled) {
|
||||
// We assume full control over the console and send JavaScript logs to Metro.
|
||||
[
|
||||
'trace',
|
||||
|
||||
@@ -26,6 +26,7 @@ let hmrUnavailableReason: string | null = null;
|
||||
let currentCompileErrorMessage: string | null = null;
|
||||
let didConnect: boolean = false;
|
||||
let pendingLogs: Array<[LogLevel, $ReadOnlyArray<mixed>]> = [];
|
||||
let pendingFuseboxConsoleNotification = false;
|
||||
|
||||
type LogLevel =
|
||||
| 'trace'
|
||||
@@ -51,6 +52,7 @@ export type HMRClientNativeInterface = {|
|
||||
isEnabled: boolean,
|
||||
scheme?: string,
|
||||
): void,
|
||||
unstable_notifyFuseboxConsoleEnabled(): void,
|
||||
|};
|
||||
|
||||
/**
|
||||
@@ -140,6 +142,29 @@ const HMRClient: HMRClientNativeInterface = {
|
||||
}
|
||||
},
|
||||
|
||||
unstable_notifyFuseboxConsoleEnabled() {
|
||||
if (!hmrClient) {
|
||||
pendingFuseboxConsoleNotification = true;
|
||||
return;
|
||||
}
|
||||
hmrClient.send(
|
||||
JSON.stringify({
|
||||
type: 'log',
|
||||
level: 'info',
|
||||
data: [
|
||||
'\n' +
|
||||
'\x1b[7m' +
|
||||
' \x1b[1mJavaScript logs have moved!\x1b[22m They will now appear in the debugger console. ' +
|
||||
'Tip: Type \x1b[1mj\x1b[22m in the terminal to open the debugger (requires Google Chrome ' +
|
||||
'or Microsoft Edge).' +
|
||||
'\x1b[27m' +
|
||||
'\n',
|
||||
],
|
||||
}),
|
||||
);
|
||||
pendingFuseboxConsoleNotification = false;
|
||||
},
|
||||
|
||||
// Called once by the bridge on startup, even if Fast Refresh is off.
|
||||
// It creates the HMR client but doesn't actually set up the socket yet.
|
||||
setup(
|
||||
@@ -316,6 +341,9 @@ function flushEarlyLogs(client: MetroHMRClient) {
|
||||
pendingLogs.forEach(([level, data]) => {
|
||||
HMRClient.log(level, data);
|
||||
});
|
||||
if (pendingFuseboxConsoleNotification) {
|
||||
HMRClient.unstable_notifyFuseboxConsoleEnabled();
|
||||
}
|
||||
} finally {
|
||||
pendingLogs.length = 0;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ const HMRClientProdShim: HMRClientNativeInterface = {
|
||||
disable() {},
|
||||
registerBundle() {},
|
||||
log() {},
|
||||
unstable_notifyFuseboxConsoleEnabled() {},
|
||||
};
|
||||
|
||||
module.exports = HMRClientProdShim;
|
||||
|
||||
@@ -8417,6 +8417,7 @@ export type HMRClientNativeInterface = {|
|
||||
isEnabled: boolean,
|
||||
scheme?: string
|
||||
): void,
|
||||
unstable_notifyFuseboxConsoleEnabled(): void,
|
||||
|};
|
||||
declare const HMRClient: HMRClientNativeInterface;
|
||||
declare module.exports: HMRClient;
|
||||
|
||||
+8
@@ -122,6 +122,10 @@ class HermesRuntimeTargetDelegate::Impl final : public RuntimeTargetDelegate {
|
||||
HermesConsoleMessage{message.timestamp, type, std::move(message.args)});
|
||||
}
|
||||
|
||||
bool supportsConsole() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
HermesRuntimeTargetDelegate& delegate_;
|
||||
std::shared_ptr<HermesRuntime> runtime_;
|
||||
@@ -173,6 +177,10 @@ void HermesRuntimeTargetDelegate::addConsoleMessage(
|
||||
impl_->addConsoleMessage(runtime, std::move(message));
|
||||
}
|
||||
|
||||
bool HermesRuntimeTargetDelegate::supportsConsole() const {
|
||||
return impl_->supportsConsole();
|
||||
}
|
||||
|
||||
#ifdef HERMES_ENABLE_DEBUGGER
|
||||
CDPDebugAPI& HermesRuntimeTargetDelegate::getCDPDebugAPI() {
|
||||
return impl_->getCDPDebugAPI();
|
||||
|
||||
+2
@@ -48,6 +48,8 @@ class HermesRuntimeTargetDelegate : public RuntimeTargetDelegate {
|
||||
void addConsoleMessage(jsi::Runtime& runtime, ConsoleMessage message)
|
||||
override;
|
||||
|
||||
bool supportsConsole() const override;
|
||||
|
||||
private:
|
||||
// We use the private implementation idiom to ensure this class has the same
|
||||
// layout regardless of whether HERMES_ENABLE_DEBUGGER is defined. The net
|
||||
|
||||
@@ -32,4 +32,8 @@ void FallbackRuntimeTargetDelegate::addConsoleMessage(
|
||||
// TODO: Best-effort printing (without RemoteObjects)
|
||||
}
|
||||
|
||||
bool FallbackRuntimeTargetDelegate::supportsConsole() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
|
||||
@@ -34,6 +34,8 @@ class FallbackRuntimeTargetDelegate : public RuntimeTargetDelegate {
|
||||
void addConsoleMessage(jsi::Runtime& runtime, ConsoleMessage message)
|
||||
override;
|
||||
|
||||
bool supportsConsole() const override;
|
||||
|
||||
private:
|
||||
std::string engineDescription_;
|
||||
};
|
||||
|
||||
@@ -67,6 +67,12 @@ class RuntimeTargetDelegate {
|
||||
virtual void addConsoleMessage(
|
||||
jsi::Runtime& runtime,
|
||||
ConsoleMessage message) = 0;
|
||||
|
||||
/**
|
||||
* \returns true if the runtime supports reporting console API calls over CDP.
|
||||
* \c addConsoleMessage MAY be called even if this method returns false.
|
||||
*/
|
||||
virtual bool supportsConsole() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -102,8 +102,10 @@ double getTimestampMs() {
|
||||
} // namespace
|
||||
|
||||
void RuntimeTarget::installConsoleHandler() {
|
||||
auto delegateSupportsConsole = delegate_.supportsConsole();
|
||||
jsExecutor_([selfWeak = weak_from_this(),
|
||||
selfExecutor = executorFromThis()](jsi::Runtime& runtime) {
|
||||
selfExecutor = executorFromThis(),
|
||||
delegateSupportsConsole](jsi::Runtime& runtime) {
|
||||
jsi::Value consolePrototype = jsi::Value::null();
|
||||
auto originalConsoleVal = runtime.global().getProperty(runtime, "console");
|
||||
std::shared_ptr<jsi::Object> originalConsole;
|
||||
@@ -441,6 +443,13 @@ void RuntimeTarget::installConsoleHandler() {
|
||||
}
|
||||
|
||||
runtime.global().setProperty(runtime, "console", console);
|
||||
if (delegateSupportsConsole) {
|
||||
// NOTE: If the delegate doesn't report console support, we'll still
|
||||
// install the console handler for consistency of the runtime environment,
|
||||
// but not claim that it has full console support.
|
||||
runtime.global().setProperty(
|
||||
runtime, "__FUSEBOX_HAS_FULL_CONSOLE_SUPPORT__", true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ class MockRuntimeTargetDelegate : public RuntimeTargetDelegate {
|
||||
addConsoleMessage,
|
||||
(jsi::Runtime & runtime, ConsoleMessage message),
|
||||
(override));
|
||||
MOCK_METHOD(bool, supportsConsole, (), (override, const));
|
||||
};
|
||||
|
||||
class MockRuntimeAgentDelegate : public RuntimeAgentDelegate {
|
||||
|
||||
Reference in New Issue
Block a user