Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import type {
JsonPagesListResponse,
JsonVersionResponse,
} from '../inspector-proxy/types';
import type {AppLauncher} from '../types/AppLauncher';

import DefaultBrowserLauncher from '../utils/DefaultBrowserLauncher';
import {fetchJson, requestLocal} from './FetchUtils';
import {createDeviceMock} from './InspectorDeviceUtils';
import {withAbortSignalForEachTest} from './ResourceUtils';
Expand All @@ -24,12 +24,19 @@ const PAGES_POLLING_DELAY = 2100;

jest.useFakeTimers();

const mockAppLauncher: AppLauncher = {
launchDebuggerAppWindow: jest
.fn<[string], Promise<void>>()
.mockResolvedValue(),
};

describe('inspector proxy HTTP API', () => {
const serverRef = withServerForEachTest({
logger: undefined,
unstable_experiments: {
enableStandaloneFuseboxShell: false,
},
unstable_appLauncher: mockAppLauncher,
});
const autoCleanup = withAbortSignalForEachTest();
afterEach(() => {
Expand Down Expand Up @@ -397,11 +404,6 @@ describe('inspector proxy HTTP API', () => {
]);
jest.advanceTimersByTime(PAGES_POLLING_DELAY);

// Hook into `DefaultBrowserLauncher.launchDebuggerAppWindow` to ensure debugger was launched
const launchDebuggerSpy = jest
.spyOn(DefaultBrowserLauncher, 'launchDebuggerAppWindow')
.mockResolvedValueOnce();

try {
// Fetch the target information for the device
const pageListResponse = await fetchJson<JsonPagesListResponse>(
Expand All @@ -426,7 +428,9 @@ describe('inspector proxy HTTP API', () => {
// Ensure the request was handled properly
expect(response.statusCode).toBe(200);
// Ensure the debugger was launched
expect(launchDebuggerSpy).toHaveBeenCalledWith(expect.any(String));
expect(mockAppLauncher.launchDebuggerAppWindow).toHaveBeenCalledWith(
expect.any(String),
);
} finally {
device.close();
}
Expand Down
2 changes: 2 additions & 0 deletions packages/dev-middleware/src/__tests__/ServerUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type CreateServerOptions = {
};
type ConnectApp = ReturnType<typeof connect>;

jest.mock('../utils/DefaultAppLauncher');

export function withServerForEachTest(options: CreateServerOptions): Readonly<{
serverBaseUrl: string,
serverBaseWsUrl: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
*/

import type {JsonPagesListResponse} from '../inspector-proxy/types';
import type {BrowserLauncher} from '../types/BrowserLauncher';
import type {AppLauncher} from '../types/AppLauncher';

import DefaultBrowserLauncher from '../utils/DefaultBrowserLauncher';
import DefaultAppLauncher from '../utils/DefaultAppLauncher';
import {fetchJson, requestLocal} from './FetchUtils';
import {createDeviceMock} from './InspectorDeviceUtils';
import {withAbortSignalForEachTest} from './ResourceUtils';
Expand All @@ -23,18 +23,18 @@ const PAGES_POLLING_DELAY = 2100;
jest.useFakeTimers();

describe('enableStandaloneFuseboxShell experiment', () => {
const BrowserLauncherWithFuseboxShell: BrowserLauncher = {
...DefaultBrowserLauncher,
unstable_showFuseboxShell: () => {
const AppLauncherWithFuseboxShell: AppLauncher = {
...DefaultAppLauncher,
launchDebuggerShell: () => {
throw new Error('Not implemented');
},
unstable_prepareFuseboxShell: async () => {
prepareDebuggerShell: async () => {
return {code: 'not_implemented'};
},
};
const serverRef = withServerForEachTest({
logger: undefined,
unstable_browserLauncher: BrowserLauncherWithFuseboxShell,
unstable_appLauncher: AppLauncherWithFuseboxShell,
unstable_experiments: {
enableStandaloneFuseboxShell: true,
},
Expand Down Expand Up @@ -66,10 +66,10 @@ describe('enableStandaloneFuseboxShell experiment', () => {
jest.advanceTimersByTime(PAGES_POLLING_DELAY);

const launchDebuggerAppWindowSpy = jest
.spyOn(BrowserLauncherWithFuseboxShell, 'launchDebuggerAppWindow')
.spyOn(AppLauncherWithFuseboxShell, 'launchDebuggerAppWindow')
.mockResolvedValue();
const showFuseboxShellSpy = jest
.spyOn(BrowserLauncherWithFuseboxShell, 'unstable_showFuseboxShell')
.spyOn(AppLauncherWithFuseboxShell, 'launchDebuggerShell')
.mockResolvedValue();

try {
Expand Down Expand Up @@ -128,6 +128,6 @@ describe('enableStandaloneFuseboxShell experiment', () => {
}
});

// TODO(moti): Add tests around unstable_prepareFuseboxShell
// TODO(moti): Add tests around prepareDebuggerShell
});
});
17 changes: 9 additions & 8 deletions packages/dev-middleware/src/createDevMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

import type {CreateCustomMessageHandlerFn} from './inspector-proxy/CustomMessageHandler';
import type {BrowserLauncher} from './types/BrowserLauncher';
import type {AppLauncher} from './types/AppLauncher';
import type {EventReporter, ReportableEvent} from './types/EventReporter';
import type {Experiments, ExperimentsConfig} from './types/Experiments';
import type {Logger} from './types/Logger';
Expand All @@ -18,7 +18,7 @@ import type {NextHandleFunction} from 'connect';

import InspectorProxy from './inspector-proxy/InspectorProxy';
import openDebuggerMiddleware from './middleware/openDebuggerMiddleware';
import DefaultBrowserLauncher from './utils/DefaultBrowserLauncher';
import DefaultAppLauncher from './utils/DefaultAppLauncher';
import reactNativeDebuggerFrontendPath from '@react-native/debugger-frontend';
import connect from 'connect';
import path from 'path';
Expand All @@ -35,11 +35,12 @@ type Options = Readonly<{

/**
* An interface for integrators to provide a custom implementation for
* opening URLs in a web browser.
* launching external applications (the debugger frontend) on the host
* machine (or target dev machine).
*
* This is an unstable API with no semver guarantees.
*/
unstable_browserLauncher?: BrowserLauncher,
unstable_appLauncher?: AppLauncher,

/**
* An interface for logging events.
Expand All @@ -64,7 +65,8 @@ type Options = Readonly<{
unstable_customInspectorMessageHandler?: CreateCustomMessageHandlerFn,

/**
* Whether to measure the event loop performance of inspector proxy and log report it via the event reporter.
* Whether to measure the event loop performance of inspector proxy and
* report it via the event reporter.
*
* This is an unstable API with no semver guarantees.
*/
Expand All @@ -79,8 +81,7 @@ type DevMiddlewareAPI = Readonly<{
export default function createDevMiddleware({
serverBaseUrl,
logger,
// $FlowFixMe[incompatible-type]
unstable_browserLauncher = DefaultBrowserLauncher,
unstable_appLauncher = DefaultAppLauncher,
unstable_eventReporter,
unstable_experiments: experimentConfig = {},
unstable_customInspectorMessageHandler,
Expand Down Expand Up @@ -110,7 +111,7 @@ export default function createDevMiddleware({
openDebuggerMiddleware({
serverBaseUrl: normalizedServerBaseUrl,
inspectorProxy,
browserLauncher: unstable_browserLauncher,
appLauncher: unstable_appLauncher,
eventReporter,
experiments,
logger,
Expand Down
6 changes: 3 additions & 3 deletions packages/dev-middleware/src/index.flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
*/

export type {
BrowserLauncher,
AppLauncher,
DebuggerShellPreparationResult,
} from './types/BrowserLauncher';
} from './types/AppLauncher';
export type {EventReporter, ReportableEvent} from './types/EventReporter';
export type {
CustomMessageHandler,
Expand All @@ -21,5 +21,5 @@ export type {
export type {Logger} from './types/Logger';
export type {ReadonlyURL} from './types/ReadonlyURL';

export {default as unstable_DefaultBrowserLauncher} from './utils/DefaultBrowserLauncher';
export {default as unstable_DefaultAppLauncher} from './utils/DefaultAppLauncher';
export {default as createDevMiddleware} from './createDevMiddleware';
21 changes: 9 additions & 12 deletions packages/dev-middleware/src/middleware/openDebuggerMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
import type {InspectorProxyQueries} from '../inspector-proxy/InspectorProxy';
import type {PageDescription} from '../inspector-proxy/types';
import type {
BrowserLauncher,
AppLauncher,
DebuggerShellPreparationResult,
} from '../types/BrowserLauncher';
} from '../types/AppLauncher';
import type {EventReporter} from '../types/EventReporter';
import type {Experiments} from '../types/Experiments';
import type {Logger} from '../types/Logger';
Expand All @@ -30,7 +30,7 @@ const LEGACY_SYNTHETIC_PAGE_TITLE =
type Options = Readonly<{
serverBaseUrl: ReadonlyURL,
logger?: Logger,
browserLauncher: BrowserLauncher,
appLauncher: AppLauncher,
eventReporter?: EventReporter,
experiments: Experiments,
inspectorProxy: InspectorProxyQueries,
Expand All @@ -44,15 +44,15 @@ type Options = Readonly<{
export default function openDebuggerMiddleware({
serverBaseUrl,
logger,
browserLauncher,
appLauncher,
eventReporter,
experiments,
inspectorProxy,
}: Options): NextHandleFunction {
let shellPreparationPromise: Promise<DebuggerShellPreparationResult>;
if (experiments.enableStandaloneFuseboxShell) {
shellPreparationPromise =
browserLauncher?.unstable_prepareFuseboxShell?.() ??
appLauncher?.prepareDebuggerShell?.() ??
Promise.resolve({code: 'not_implemented'});
shellPreparationPromise = shellPreparationPromise.then(result => {
eventReporter?.logEvent({
Expand Down Expand Up @@ -196,17 +196,14 @@ export default function openDebuggerMiddleware({
].join('-'),
)
.digest('hex');
if (!browserLauncher.unstable_showFuseboxShell) {
if (!appLauncher.launchDebuggerShell) {
throw new Error(
'Fusebox shell is not supported by the current browser launcher',
'Fusebox shell is not supported by the current app launcher',
);
}
await browserLauncher.unstable_showFuseboxShell(
frontendUrl,
windowKey,
);
await appLauncher.launchDebuggerShell(frontendUrl, windowKey);
} else {
await browserLauncher.launchDebuggerAppWindow(frontendUrl);
await appLauncher.launchDebuggerAppWindow(frontendUrl);
}
res.writeHead(200);
res.end();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,20 @@ export type {DebuggerShellPreparationResult};

/**
* An interface for integrators to provide a custom implementation for
* opening URLs in a web browser.
* launching external applications on the host machine (or target dev machine).
*
* This is an unstable API with no semver guarantees.
*/
export interface BrowserLauncher {
export interface AppLauncher {
/**
* Attempt to open a debugger frontend URL in a browser app window,
* optionally returning an object to control the launched browser instance.
* The browser used should be capable of running Chrome DevTools.
* Attempt to open a debugger frontend URL in a browser app window. The
* browser used should be capable of running Chrome DevTools.
*
* The provided URL is based on serverBaseUrl, and therefore reachable from
* the host of dev-middleware. Implementations are responsible for rewriting
* this as necessary where the server is remote.
*/
launchDebuggerAppWindow: (url: string) => Promise<void>;
+launchDebuggerAppWindow: (url: string) => Promise<void>;

/**
* Attempt to open a debugger frontend URL in a standalone shell window
Expand All @@ -46,10 +47,7 @@ export interface BrowserLauncher {
* the host of dev-middleware. Implementations are responsible for rewriting
* this as necessary where the server is remote.
*/
+unstable_showFuseboxShell?: (
url: string,
windowKey: string,
) => Promise<void>;
+launchDebuggerShell?: (url: string, windowKey: string) => Promise<void>;

/**
* Attempt to prepare the debugger shell for use and returns a coded result
Expand All @@ -62,5 +60,5 @@ export interface BrowserLauncher {
* SHOULD NOT return a rejecting promise in any case, and instead SHOULD report
* errors via the returned result object.
*/
+unstable_prepareFuseboxShell?: () => Promise<DebuggerShellPreparationResult>;
+prepareDebuggerShell?: () => Promise<DebuggerShellPreparationResult>;
}
2 changes: 1 addition & 1 deletion packages/dev-middleware/src/types/EventReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* @format
*/

import type {DebuggerShellPreparationResult} from './BrowserLauncher';
import type {DebuggerShellPreparationResult} from './AppLauncher';

type SuccessResult<Props: {...} | void = {}> = {
status: 'success',
Expand Down
6 changes: 3 additions & 3 deletions packages/dev-middleware/src/types/Experiments.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type Experiments = Readonly<{
/**
* Enables the handling of GET requests in the /open-debugger endpoint,
* in addition to POST requests. GET requests respond by redirecting to
* the debugger frontend, instead of opening it using the BrowserLauncher
* the debugger frontend, instead of opening it using the AppLauncher
* interface.
*/
enableOpenDebuggerRedirect: boolean,
Expand All @@ -25,8 +25,8 @@ export type Experiments = Readonly<{

/**
* Launch the debugger frontend in a standalone shell instead of a browser.
* When this is enabled, we will use the optional unstable_showFuseboxShell
* method on the BrowserLauncher, or throw an error if the method is missing.
* When this is enabled, we will use the optional launchDebuggerShell
* method on the AppLauncher, or throw an error if the method is missing.
*
* NOTE: Disabling this also disables support for concurrent sessions in the
* inspector proxy. Without the standalone shell, the proxy remains responsible
Expand Down
Loading
Loading