mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/51416 Deletes `oncall` annotations from the `facebook/react-native` repository. Changelog: [Internal] Reviewed By: javache Differential Revision: D74902524 fbshipit-source-id: 32a6a5b2ff27281792d572f151e2b094d9a79029
175 lines
4.5 KiB
JavaScript
175 lines
4.5 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow strict-local
|
|
* @format
|
|
*/
|
|
|
|
import type {TerminalReporter} from 'metro';
|
|
|
|
import chalk from 'chalk';
|
|
|
|
type PageDescription = $ReadOnly<{
|
|
id: string,
|
|
title: string,
|
|
description: string,
|
|
...
|
|
}>;
|
|
|
|
export default class OpenDebuggerKeyboardHandler {
|
|
#devServerUrl: string;
|
|
#reporter: TerminalReporter;
|
|
#targetsShownForSelection: ?$ReadOnlyArray<PageDescription> = null;
|
|
|
|
constructor({
|
|
devServerUrl,
|
|
reporter,
|
|
}: {
|
|
devServerUrl: string,
|
|
reporter: TerminalReporter,
|
|
}) {
|
|
this.#devServerUrl = devServerUrl;
|
|
this.#reporter = reporter;
|
|
}
|
|
|
|
async #tryOpenDebuggerForTarget(target: PageDescription): Promise<void> {
|
|
this.#targetsShownForSelection = null;
|
|
this.#clearTerminalMenu();
|
|
|
|
try {
|
|
await fetch(
|
|
new URL(
|
|
'/open-debugger?target=' + encodeURIComponent(target.id),
|
|
this.#devServerUrl,
|
|
).href,
|
|
{method: 'POST'},
|
|
);
|
|
} catch (e) {
|
|
this.#log(
|
|
'error',
|
|
'Failed to open debugger for %s (%s): %s',
|
|
target.title,
|
|
target.description,
|
|
'Network error',
|
|
);
|
|
if (e.cause != null) {
|
|
this.#log('error', 'Cause: %s', e.cause);
|
|
}
|
|
this.#clearTerminalMenu();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Used in response to 'j' to debug - fetch the available debug targets and:
|
|
* - If no targets, warn
|
|
* - If one target, open it
|
|
* - If more, show a list. The keyboard listener should run subsequent key
|
|
* presses through maybeHandleTargetSelection, which will launch the
|
|
* debugger if a match is made.
|
|
*/
|
|
async handleOpenDebugger(): Promise<void> {
|
|
this.#setTerminalMenu('Fetching available debugging targets...');
|
|
this.#targetsShownForSelection = null;
|
|
|
|
try {
|
|
const res = await fetch(this.#devServerUrl + '/json/list', {
|
|
method: 'POST',
|
|
});
|
|
|
|
if (res.status !== 200) {
|
|
throw new Error(`Unexpected status code: ${res.status}`);
|
|
}
|
|
const targets = (await res.json()) as $ReadOnlyArray<PageDescription>;
|
|
if (!Array.isArray(targets)) {
|
|
throw new Error('Expected array.');
|
|
}
|
|
|
|
if (targets.length === 0) {
|
|
this.#log('warn', 'No connected targets');
|
|
this.#clearTerminalMenu();
|
|
} else if (targets.length === 1) {
|
|
const target = targets[0];
|
|
// eslint-disable-next-line no-void
|
|
void this.#tryOpenDebuggerForTarget(target);
|
|
} else {
|
|
this.#targetsShownForSelection = targets;
|
|
|
|
if (targets.length > 9) {
|
|
this.#log(
|
|
'warn',
|
|
'10 or more debug targets available, showing the first 9.',
|
|
);
|
|
}
|
|
|
|
this.#setTerminalMenu(
|
|
`Multiple debug targets available, please select:\n ${targets
|
|
.slice(0, 9)
|
|
.map(
|
|
({title}, i) =>
|
|
`${chalk.white.inverse(` ${i + 1} `)} - "${title}"`,
|
|
)
|
|
.join('\n ')}`,
|
|
);
|
|
}
|
|
} catch (e) {
|
|
this.#log('error', `Failed to fetch debug targets: ${e.message}`);
|
|
this.#clearTerminalMenu();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle key presses that correspond to a valid selection from a visible
|
|
* selection list.
|
|
*
|
|
* @return true if we've handled the key as a target selection, false if the
|
|
* caller should handle the key.
|
|
*/
|
|
maybeHandleTargetSelection(keyName: string): boolean {
|
|
if (keyName >= '1' && keyName <= '9') {
|
|
const targetIndex = Number(keyName) - 1;
|
|
if (
|
|
this.#targetsShownForSelection != null &&
|
|
targetIndex < this.#targetsShownForSelection.length
|
|
) {
|
|
const target = this.#targetsShownForSelection[targetIndex];
|
|
// eslint-disable-next-line no-void
|
|
void this.#tryOpenDebuggerForTarget(target);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Dismiss any target selection UI, if shown.
|
|
*/
|
|
dismiss() {
|
|
this.#clearTerminalMenu();
|
|
this.#targetsShownForSelection = null;
|
|
}
|
|
|
|
#log(level: 'info' | 'warn' | 'error', ...data: Array<mixed>): void {
|
|
this.#reporter.update({
|
|
type: 'unstable_server_log',
|
|
level,
|
|
data,
|
|
});
|
|
}
|
|
|
|
#setTerminalMenu(message: string) {
|
|
this.#reporter.update({
|
|
type: 'unstable_server_menu_updated',
|
|
message,
|
|
});
|
|
}
|
|
|
|
#clearTerminalMenu() {
|
|
this.#reporter.update({
|
|
type: 'unstable_server_menu_cleared',
|
|
});
|
|
}
|
|
}
|