Files
react-native/packages/react-native/Libraries/Core/Devtools/loadBundleFromServer.js
T
Iwo Plaza e5818d92a8 Migrate files in Libraries/Core to export syntax (#48889)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/48889

## Motivation
Modernising the react-native codebase to allow for ingestion by modern Flow tooling.

## This diff
- Updates files in `Libraries/Core` to use `export` syntax
  - `export default` for qualified objects, many `export` statements for collections
- Appends `.default` to requires of the changed files.
- Changed `* as ExceptionsManager` to `ExceptionsManager` in import statements throughout product code.
- Updates test files.
- Updates the public API snapshot (intented breaking change)

Changelog:
[General][Breaking] - Files inside `Libraries/Core` use `export` syntax, which requires the addition of `.default` when imported with the CJS `require` syntax.
[General][Breaking] - `Libraries/Core/ExceptionsManager` now exports a default `ExceptionsManager` object, and `SyntheticError` as a secondary export.

Reviewed By: huntie

Differential Revision: D68553694

fbshipit-source-id: 51c9a404b2762cb1cdb5f56cae3a683ccdfffc7f
2025-01-24 05:43:28 -08:00

155 lines
4.1 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
* @oncall react_native
*/
import Networking from '../../Network/RCTNetworking';
import DevLoadingView from '../../Utilities/DevLoadingView';
import HMRClient from '../../Utilities/HMRClient';
import getDevServer from './getDevServer';
declare var global: {globalEvalWithSourceUrl?: (string, string) => mixed, ...};
let pendingRequests = 0;
const cachedPromisesByUrl = new Map<string, Promise<void>>();
function asyncRequest(
url: string,
): Promise<{body: string, headers: {[string]: string}}> {
let id = null;
let responseText = null;
let headers = null;
let dataListener;
let completeListener;
let responseListener;
let incrementalDataListener;
return new Promise<{body: string, headers: {[string]: string}}>(
(resolve, reject) => {
dataListener = Networking.addListener(
'didReceiveNetworkData',
([requestId, response]) => {
if (requestId === id) {
responseText = response;
}
},
);
incrementalDataListener = Networking.addListener(
'didReceiveNetworkIncrementalData',
([requestId, data]) => {
if (requestId === id) {
if (responseText != null) {
responseText += data;
} else {
responseText = data;
}
}
},
);
responseListener = Networking.addListener(
'didReceiveNetworkResponse',
([requestId, status, responseHeaders]) => {
if (requestId === id) {
headers = responseHeaders;
}
},
);
completeListener = Networking.addListener(
'didCompleteNetworkResponse',
([requestId, error]) => {
if (requestId === id) {
if (error) {
reject(error);
} else {
//$FlowFixMe[incompatible-call]
resolve({body: responseText, headers});
}
}
},
);
Networking.sendRequest(
'GET',
'asyncRequest',
url,
{},
'',
'text',
true,
0,
requestId => {
id = requestId;
},
true,
);
},
).finally(() => {
dataListener?.remove();
completeListener?.remove();
responseListener?.remove();
incrementalDataListener?.remove();
});
}
function buildUrlForBundle(bundlePathAndQuery: string) {
const {url: serverUrl} = getDevServer();
return (
serverUrl.replace(/\/+$/, '') + '/' + bundlePathAndQuery.replace(/^\/+/, '')
);
}
export default function loadBundleFromServer(
bundlePathAndQuery: string,
): Promise<void> {
const requestUrl = buildUrlForBundle(bundlePathAndQuery);
let loadPromise = cachedPromisesByUrl.get(requestUrl);
if (loadPromise) {
return loadPromise;
}
DevLoadingView.showMessage('Downloading...', 'load');
++pendingRequests;
loadPromise = asyncRequest(requestUrl)
.then<void>(({body, headers}) => {
if (
headers['Content-Type'] != null &&
headers['Content-Type'].indexOf('application/json') >= 0
) {
// Errors are returned as JSON.
throw new Error(
JSON.parse(body).message ||
`Unknown error fetching '${bundlePathAndQuery}'`,
);
}
HMRClient.registerBundle(requestUrl);
// Some engines do not support `sourceURL` as a comment. We expose a
// `globalEvalWithSourceUrl` function to handle updates in that case.
if (global.globalEvalWithSourceUrl) {
global.globalEvalWithSourceUrl(body, requestUrl);
} else {
// eslint-disable-next-line no-eval
eval(body);
}
})
.catch<void>(e => {
cachedPromisesByUrl.delete(requestUrl);
throw e;
})
.finally(() => {
if (!--pendingRequests) {
DevLoadingView.hide();
}
});
cachedPromisesByUrl.set(requestUrl, loadPromise);
return loadPromise;
}