From 9d38b800bac90160c7b0e0fb14ceef89b14a5d0b Mon Sep 17 00:00:00 2001 From: Aravind M Nair Date: Fri, 31 Jul 2026 16:20:19 +0530 Subject: [PATCH] Remove unused Promise polyfill and promise dependency Every supported JS engine ships a native Promise, but the polyfill branch in polyfillPromise.js is statically reachable, so Metro bundles the promise package into every app even though it is never used. Remove the dead branch, Libraries/Promise.js and the promise dependency. DEV unhandled-rejection tracking is unchanged. Fixes #57702 --- flow-typed/npm/promise_v8.x.x.js | 30 ------------------- .../Libraries/Core/polyfillPromise.js | 30 ++++++------------- packages/react-native/Libraries/Promise.js | 23 -------------- .../promiseRejectionTrackingOptions.js | 11 +++++-- packages/react-native/package.json | 1 - 5 files changed, 17 insertions(+), 78 deletions(-) delete mode 100644 flow-typed/npm/promise_v8.x.x.js delete mode 100644 packages/react-native/Libraries/Promise.js diff --git a/flow-typed/npm/promise_v8.x.x.js b/flow-typed/npm/promise_v8.x.x.js deleted file mode 100644 index 7358622e3bea..000000000000 --- a/flow-typed/npm/promise_v8.x.x.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @flow strict - * @format - */ - -declare module 'promise/setimmediate/es6-extensions' { - declare module.exports: typeof Promise; -} - -declare module 'promise/setimmediate/done' { - declare module.exports: typeof Promise; -} - -declare module 'promise/setimmediate/finally' { - declare module.exports: typeof Promise; -} - -declare module 'promise/setimmediate/rejection-tracking' { - declare module.exports: { - enable: ( - options?: ?{ - whitelist?: ?Array, - allRejections?: ?boolean, - onUnhandled?: ?(number, unknown) => void, - onHandled?: ?(number, unknown) => void, - }, - ) => void, - disable: () => void, - }; -} diff --git a/packages/react-native/Libraries/Core/polyfillPromise.js b/packages/react-native/Libraries/Core/polyfillPromise.js index 5bfec271d1c5..a202b3b749e6 100644 --- a/packages/react-native/Libraries/Core/polyfillPromise.js +++ b/packages/react-native/Libraries/Core/polyfillPromise.js @@ -10,29 +10,17 @@ 'use strict'; -const {polyfillGlobal} = require('../Utilities/PolyfillFunctions'); - /** - * Set up Promise. The native Promise implementation throws the following error: - * ERROR: Event loop not supported. - * - * If you don't need these polyfills, don't use InitializeCore; just directly - * require the modules you need from InitializeCore for setup. + * Set up Promise. All supported JS engines provide a spec-compliant native + * Promise implementation, so it no longer needs to be polyfilled. In DEV, + * enable unhandled rejection tracking where the engine supports it. */ -// If global.Promise is provided by Hermes, we are confident that it can provide -// all the methods needed by React Native, so we can directly use it. -if (global?.HermesInternal?.hasPromise?.()) { - const HermesPromise = global.Promise; - - if (__DEV__) { - if (typeof HermesPromise !== 'function') { - console.error('HermesPromise does not exist'); - } - global.HermesInternal?.enablePromiseRejectionTracker?.( - require('../promiseRejectionTrackingOptions').default, - ); +if (__DEV__) { + if (typeof global.Promise !== 'function') { + console.error('Promise does not exist'); } -} else { - polyfillGlobal('Promise', () => require('../Promise').default); + global.HermesInternal?.enablePromiseRejectionTracker?.( + require('../promiseRejectionTrackingOptions').default, + ); } diff --git a/packages/react-native/Libraries/Promise.js b/packages/react-native/Libraries/Promise.js deleted file mode 100644 index 5184765a0c83..000000000000 --- a/packages/react-native/Libraries/Promise.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 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 - * @format - */ - -'use strict'; - -import Promise from 'promise/setimmediate/es6-extensions'; - -require('promise/setimmediate/finally'); - -if (__DEV__) { - require('promise/setimmediate/rejection-tracking').enable( - require('./promiseRejectionTrackingOptions').default, - ); -} - -export default Promise; diff --git a/packages/react-native/Libraries/promiseRejectionTrackingOptions.js b/packages/react-native/Libraries/promiseRejectionTrackingOptions.js index 95fcf1c093d0..4a7b5ec3b515 100644 --- a/packages/react-native/Libraries/promiseRejectionTrackingOptions.js +++ b/packages/react-native/Libraries/promiseRejectionTrackingOptions.js @@ -8,11 +8,16 @@ * @format */ -import typeof {enable} from 'promise/setimmediate/rejection-tracking'; - import ExceptionsManager from './Core/ExceptionsManager'; -const rejectionTrackingOptions: NonNullable[0]> = { +type RejectionTrackingOptions = { + whitelist?: ?Array, + allRejections?: ?boolean, + onUnhandled?: ?(number, unknown) => void, + onHandled?: ?(number, unknown) => void, +}; + +const rejectionTrackingOptions: RejectionTrackingOptions = { allRejections: true, onHandled: id => { const warning = diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 9ba6a5668473..95ccddaf327e 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -169,7 +169,6 @@ "metro-source-map": "^0.87.0", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", - "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2",