diff --git a/config/gni/devtools_grd_files.gni b/config/gni/devtools_grd_files.gni index 19d4084b012..b730919b256 100644 --- a/config/gni/devtools_grd_files.gni +++ b/config/gni/devtools_grd_files.gni @@ -304,6 +304,7 @@ grd_files_release_sources = [ "front_end/entrypoints/main/main.js", "front_end/entrypoints/ndb_app/ndb_app.js", "front_end/entrypoints/node_app/node_app.js", + "front_end/entrypoints/rn_fusebox/rn_fusebox.js", "front_end/entrypoints/rn_inspector/rn_inspector.js", "front_end/entrypoints/shell/shell.js", "front_end/entrypoints/wasmparser_worker/wasmparser_worker-entrypoint.js", @@ -570,6 +571,7 @@ grd_files_release_sources = [ "front_end/panels/web_audio/web_audio.js", "front_end/panels/webauthn/webauthn-meta.js", "front_end/panels/webauthn/webauthn.js", + "front_end/rn_fusebox.html", "front_end/rn_inspector.html", "front_end/services/puppeteer/puppeteer.js", "front_end/services/tracing/tracing.js", diff --git a/front_end/BUILD.gn b/front_end/BUILD.gn index cbdf7fe76fc..f9e20ea3f91 100644 --- a/front_end/BUILD.gn +++ b/front_end/BUILD.gn @@ -26,6 +26,7 @@ group("front_end") { "entrypoints/lighthouse_worker:bundle", "entrypoints/ndb_app:entrypoint", "entrypoints/node_app:entrypoint", + "entrypoints/rn_fusebox:entrypoint", "entrypoints/rn_inspector:entrypoint", "entrypoints/shell", "entrypoints/wasmparser_worker:worker_entrypoint", @@ -112,6 +113,7 @@ node_action("html_entrypoints") { "js_app", "ndb_app", "node_app", + "rn_fusebox", "rn_inspector", "worker_app", "device_mode_emulation_frame", diff --git a/front_end/entrypoints/inspector_main/BUILD.gn b/front_end/entrypoints/inspector_main/BUILD.gn index bd9ce25d567..54ff5ce341e 100644 --- a/front_end/entrypoints/inspector_main/BUILD.gn +++ b/front_end/entrypoints/inspector_main/BUILD.gn @@ -62,6 +62,7 @@ devtools_entrypoint("meta") { visibility = [ "../../../test/unittests/front_end/helpers/*", "../devtools_app/*", + "../rn_fusebox:*", "../rn_inspector:*", ] } diff --git a/front_end/entrypoints/main/BUILD.gn b/front_end/entrypoints/main/BUILD.gn index ed0a9448a71..f73292b3422 100644 --- a/front_end/entrypoints/main/BUILD.gn +++ b/front_end/entrypoints/main/BUILD.gn @@ -49,6 +49,7 @@ devtools_entrypoint("bundle") { "../js_app:*", "../ndb_app:*", "../node_app:*", + "../rn_fusebox:*", "../rn_inspector:*", "../worker_app:*", ] diff --git a/front_end/entrypoints/rn_fusebox/BUILD.gn b/front_end/entrypoints/rn_fusebox/BUILD.gn new file mode 100644 index 00000000000..556d62a1e90 --- /dev/null +++ b/front_end/entrypoints/rn_fusebox/BUILD.gn @@ -0,0 +1,43 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# Copyright 2021 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +import("../../../scripts/build/ninja/devtools_entrypoint.gni") +import("../visibility.gni") + +devtools_entrypoint("entrypoint") { + entrypoint = "rn_fusebox.ts" + + deps = [ + "../../entrypoints/inspector_main:meta", + "../../panels/accessibility:meta", + "../../panels/animation:meta", + "../../panels/application:meta", + "../../panels/browser_debugger:meta", + "../../panels/css_overview:meta", + "../../panels/developer_resources:meta", + "../../panels/elements:meta", + "../../panels/emulation:meta", + "../../panels/issues:meta", + "../../panels/js_profiler:meta", + "../../panels/layer_viewer:meta", + "../../panels/layers:meta", + "../../panels/lighthouse:meta", + "../../panels/media:meta", + "../../panels/mobile_throttling:meta", + "../../panels/network:meta", + "../../panels/performance_monitor:meta", + "../../panels/recorder:meta", + "../../panels/rn_welcome:meta", + "../../panels/security:meta", + "../../panels/sensors:meta", + "../../panels/web_audio:meta", + "../../panels/webauthn:meta", + "../main:bundle", + "../shell", + ] + + visibility = [ "../../:*" ] + + visibility += devtools_entrypoints_visibility +} diff --git a/front_end/entrypoints/rn_fusebox/README.md b/front_end/entrypoints/rn_fusebox/README.md new file mode 100644 index 00000000000..738d8ccb7c5 --- /dev/null +++ b/front_end/entrypoints/rn_fusebox/README.md @@ -0,0 +1,7 @@ +# `rn_fusebox.html` + +`rn_fusebox.html` is a customized entry point designed to work well with React Native targets. This entry point is designed to work with all features of the next-gen debugging stack (codename: React Fusebox ⚡). + +## Notes on embedding + +* Adding `&sources.hide_add_folder=true` to the inspector frontend URL hides UI related to Filesystem / Workspaces that does not work in hosted mode. diff --git a/front_end/entrypoints/rn_fusebox/rn_fusebox.ts b/front_end/entrypoints/rn_fusebox/rn_fusebox.ts new file mode 100644 index 00000000000..0be55d3f962 --- /dev/null +++ b/front_end/entrypoints/rn_fusebox/rn_fusebox.ts @@ -0,0 +1,166 @@ +// Copyright (c) Meta Platforms, Inc. and affiliates. +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../shell/shell.js'; +import '../../panels/emulation/emulation-meta.js'; +import '../../panels/sensors/sensors-meta.js'; +import '../../panels/developer_resources/developer_resources-meta.js'; +import '../inspector_main/inspector_main-meta.js'; +import '../../panels/issues/issues-meta.js'; +import '../../panels/mobile_throttling/mobile_throttling-meta.js'; +import '../../panels/network/network-meta.js'; +import '../../panels/js_profiler/js_profiler-meta.js'; +import '../../panels/rn_welcome/rn_welcome-meta.js'; + +import * as i18n from '../../core/i18n/i18n.js'; +import * as Host from '../../core/host/host.js'; +import * as Root from '../../core/root/root.js'; +import * as SDK from '../../core/sdk/sdk.js'; +import * as Main from '../main/main.js'; +import * as UI from '../../ui/legacy/legacy.js'; +import type * as InspectorBackend from '../../core/protocol_client/InspectorBackend.js'; +import type * as Platform from '../../core/platform/platform.js'; +import type * as Sources from '../../panels/sources/sources.js'; + +Host.RNPerfMetrics.registerPerfMetricsGlobalPostMessageHandler(); + +Host.rnPerfMetrics.setLaunchId(Root.Runtime.Runtime.queryParam('launchId')); +Host.rnPerfMetrics.entryPointLoadingStarted(); + +SDK.TargetManager.TargetManager.instance().addModelListener( + SDK.DebuggerModel.DebuggerModel, + SDK.DebuggerModel.Events.DebuggerIsReadyToPause, + () => Host.rnPerfMetrics.debuggerReadyToPause(), +); + +// Legacy JavaScript Profiler - we support this until Hermes can support the +// modern Performance panel. +Root.Runtime.experiments.register( + Root.Runtime.ExperimentName.JS_PROFILER_TEMP_ENABLE, + 'Enable JavaScript Profiler (legacy)', + /* unstable */ false, +); + +Root.Runtime.experiments.register( + Root.Runtime.ExperimentName.REACT_NATIVE_SPECIFIC_UI, + 'Show React Native-specific UI', + /* unstable */ false, + /* docLink */ globalThis.reactNativeDocLink ?? 'https://reactnative.dev/docs/debugging', +); + +Root.Runtime.experiments.register( + Root.Runtime.ExperimentName.ENABLE_REACT_DEVTOOLS_PANEL, + 'Enable React DevTools panel', + /* unstable */ true, +); + +Root.Runtime.experiments.enableExperimentsByDefault([ + Root.Runtime.ExperimentName.REACT_NATIVE_SPECIFIC_UI, +]); + +class FuseboxClientMetadataModel extends SDK.SDKModel.SDKModel { + constructor(target: SDK.Target.Target) { + super(target); + target.router()?.sendMessage( + target.sessionId, + 'FuseboxClient', + 'FuseboxClient.setClientMetadata' as InspectorBackend.QualifiedName, + {}, + () => {}, + ); + } +} + +SDK.SDKModel.SDKModel.register( + FuseboxClientMetadataModel, + { + capabilities: SDK.Target.Capability.None, + autostart: true, + // Ensure FuseboxClient.setClientMetadata is sent before most other CDP domains + // are initialised. This allows the backend to confidently detect non-Fusebox + // clients by the fact that they send e.g. Runtime.enable without sending any + // Fusebox-specific messages first. + // TODO: Explicitly depend on this model in RuntimeModel and LogModel, and + // remove the `early` and `autostart` flags. + early: true, + }, +); + +const UIStrings = { + /** + *@description Title of the 'React Native' tool in the Network Navigator View, which is part of the Sources tool + */ + networkTitle: 'React Native', + /** + *@description Command for showing the 'React Native' tool in the Network Navigator View, which is part of the Sources tool + */ + showReactNative: 'Show React Native', + /** + *@description Label of the FB-only 'send feedback' action button in the toolbar + */ + sendFeedback: '[FB-only] Send feedback', +}; + +const str_ = i18n.i18n.registerUIStrings('entrypoints/rn_fusebox/rn_fusebox.ts', UIStrings); +const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_); + +let loadedSourcesModule: (typeof Sources|undefined); + +async function loadSourcesModule(): Promise { + if (!loadedSourcesModule) { + loadedSourcesModule = await import('../../panels/sources/sources.js'); + } + return loadedSourcesModule; +} + +UI.ViewManager.registerViewExtension({ + location: UI.ViewManager.ViewLocationValues.NAVIGATOR_VIEW, + id: 'navigator-network', + title: i18nLazyString(UIStrings.networkTitle), + commandPrompt: i18nLazyString(UIStrings.showReactNative), + order: 2, + persistence: UI.ViewManager.ViewPersistence.PERMANENT, + async loadView() { + const Sources = await loadSourcesModule(); + return Sources.SourcesNavigator.NetworkNavigatorView.instance(); + }, +}); + +// @ts-ignore Exposed for legacy layout tests +self.runtime = Root.Runtime.Runtime.instance({forceNew: true}); +new Main.MainImpl.MainImpl(); + +if (globalThis.FB_ONLY__reactNativeFeedbackLink) { + const feedbackLink = globalThis.FB_ONLY__reactNativeFeedbackLink as Platform.DevToolsPath.UrlString; + const actionId = 'react-native-send-feedback'; + const sendFeedbackActionDelegate: UI.ActionRegistration.ActionDelegate = { + handleAction(_context, incomingActionId): boolean { + if (incomingActionId !== actionId) { + return false; + } + + Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab( + feedbackLink, + ); + return true; + }, + }; + + UI.ActionRegistration.registerActionExtension({ + category: UI.ActionRegistration.ActionCategory.GLOBAL, + actionId, + title: i18nLazyString(UIStrings.sendFeedback), + async loadActionDelegate() { + return sendFeedbackActionDelegate; + }, + iconClass: UI.ActionRegistration.IconClass.BUG, + }); + + UI.Toolbar.registerToolbarItem({ + location: UI.Toolbar.ToolbarItemLocation.MAIN_TOOLBAR_RIGHT, + actionId, + showLabel: true, + }); +} diff --git a/front_end/entrypoints/rn_inspector/rn_inspector.ts b/front_end/entrypoints/rn_inspector/rn_inspector.ts index 029b45b816a..a750fa005d7 100644 --- a/front_end/entrypoints/rn_inspector/rn_inspector.ts +++ b/front_end/entrypoints/rn_inspector/rn_inspector.ts @@ -15,26 +15,11 @@ import '../../panels/js_profiler/js_profiler-meta.js'; import '../../panels/rn_welcome/rn_welcome-meta.js'; import * as i18n from '../../core/i18n/i18n.js'; -import * as Host from '../../core/host/host.js'; import * as Root from '../../core/root/root.js'; -import * as SDK from '../../core/sdk/sdk.js'; import * as Main from '../main/main.js'; import * as UI from '../../ui/legacy/legacy.js'; -import type * as Platform from '../../core/platform/platform.js'; -import type * as InspectorBackend from '../../core/protocol_client/InspectorBackend.js'; import type * as Sources from '../../panels/sources/sources.js'; -Host.RNPerfMetrics.registerPerfMetricsGlobalPostMessageHandler(); - -Host.rnPerfMetrics.setLaunchId(Root.Runtime.Runtime.queryParam('launchId')); -Host.rnPerfMetrics.entryPointLoadingStarted(); - -SDK.TargetManager.TargetManager.instance().addModelListener( - SDK.DebuggerModel.DebuggerModel, - SDK.DebuggerModel.Events.DebuggerIsReadyToPause, - () => Host.rnPerfMetrics.debuggerReadyToPause(), -); - // Legacy JavaScript Profiler - we support this until Hermes can support the // modern Performance panel. Root.Runtime.experiments.register( @@ -51,45 +36,11 @@ Root.Runtime.experiments.register( /* feedbackLink */ globalThis.FB_ONLY__reactNativeFeedbackLink, ); -Root.Runtime.experiments.register( - Root.Runtime.ExperimentName.ENABLE_REACT_DEVTOOLS_PANEL, - 'Enable React DevTools panel', - /* unstable */ true, -); - Root.Runtime.experiments.enableExperimentsByDefault([ Root.Runtime.ExperimentName.JS_PROFILER_TEMP_ENABLE, Root.Runtime.ExperimentName.REACT_NATIVE_SPECIFIC_UI, ]); -class FuseboxClientMetadataModel extends SDK.SDKModel.SDKModel { - constructor(target: SDK.Target.Target) { - super(target); - target.router()?.sendMessage( - target.sessionId, - 'FuseboxClient', - 'FuseboxClient.setClientMetadata' as InspectorBackend.QualifiedName, - {}, - () => {}, - ); - } -} - -SDK.SDKModel.SDKModel.register( - FuseboxClientMetadataModel, - { - capabilities: SDK.Target.Capability.None, - autostart: true, - // Ensure FuseboxClient.setClientMetadata is sent before most other CDP domains - // are initialised. This allows the backend to confidently detect non-Fusebox - // clients by the fact that they send e.g. Runtime.enable without sending any - // Fusebox-specific messages first. - // TODO: Explicitly depend on this model in RuntimeModel and LogModel, and - // remove the `early` and `autostart` flags. - early: true, - }, -); - const UIStrings = { /** *@description Title of the 'React Native' tool in the Network Navigator View, which is part of the Sources tool @@ -99,10 +50,6 @@ const UIStrings = { *@description Command for showing the 'React Native' tool in the Network Navigator View, which is part of the Sources tool */ showReactNative: 'Show React Native', - /** - *@description Label of the FB-only 'send feedback' action button in the toolbar - */ - sendFeedback: '[FB-only] Send feedback', }; const str_ = i18n.i18n.registerUIStrings('entrypoints/rn_inspector/rn_inspector.ts', UIStrings); @@ -134,35 +81,3 @@ UI.ViewManager.registerViewExtension({ self.runtime = Root.Runtime.Runtime.instance({forceNew: true}); new Main.MainImpl.MainImpl(); -if (globalThis.FB_ONLY__reactNativeFeedbackLink) { - const feedbackLink = globalThis.FB_ONLY__reactNativeFeedbackLink as Platform.DevToolsPath.UrlString; - const actionId = 'react-native-send-feedback'; - const sendFeedbackActionDelegate: UI.ActionRegistration.ActionDelegate = { - handleAction(_context, incomingActionId): boolean { - if (incomingActionId !== actionId) { - return false; - } - - Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab( - feedbackLink, - ); - return true; - }, - }; - - UI.ActionRegistration.registerActionExtension({ - category: UI.ActionRegistration.ActionCategory.GLOBAL, - actionId, - title: i18nLazyString(UIStrings.sendFeedback), - async loadActionDelegate() { - return sendFeedbackActionDelegate; - }, - iconClass: UI.ActionRegistration.IconClass.BUG, - }); - - UI.Toolbar.registerToolbarItem({ - location: UI.Toolbar.ToolbarItemLocation.MAIN_TOOLBAR_RIGHT, - actionId, - showLabel: true, - }); -} diff --git a/front_end/entrypoints/shell/BUILD.gn b/front_end/entrypoints/shell/BUILD.gn index f54935dba4a..9b629e2addd 100644 --- a/front_end/entrypoints/shell/BUILD.gn +++ b/front_end/entrypoints/shell/BUILD.gn @@ -39,6 +39,7 @@ devtools_entrypoint("shell") { "../js_app:*", "../ndb_app:*", "../node_app:*", + "../rn_fusebox:*", "../rn_inspector:*", "../worker_app:*", ] diff --git a/front_end/index.html b/front_end/index.html index caa1860a671..efffb3e28f7 100644 --- a/front_end/index.html +++ b/front_end/index.html @@ -19,6 +19,9 @@
  • rn_inspector.html ⚛️
  • +
  • + rn_fusebox.html ⚛️ +
  • inspector.html
  • @@ -35,4 +38,4 @@ worker_app.html - \ No newline at end of file + diff --git a/front_end/panels/recorder/BUILD.gn b/front_end/panels/recorder/BUILD.gn index 9f0638037b0..784768e8172 100644 --- a/front_end/panels/recorder/BUILD.gn +++ b/front_end/panels/recorder/BUILD.gn @@ -74,6 +74,7 @@ devtools_entrypoint("meta") { "../..:*", "../../entrypoints/devtools_app:*", "../../entrypoints/inspector:*", + "../../entrypoints/rn_fusebox:*", "../../entrypoints/rn_inspector:*", ] }