/** * 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 */ 'use strict'; const {isNativeFunction} = require('../Utilities/FeatureDetection'); const {polyfillGlobal} = require('../Utilities/PolyfillFunctions'); if (__DEV__) { if (typeof global.Promise !== 'function') { console.error('Promise should exist before setting up timers.'); } } // Currently, Hermes `Promise` is implemented via Internal Bytecode. const hasHermesPromiseQueuedToJSVM = global.HermesInternal?.hasPromise?.() === true && global.HermesInternal?.useEngineQueue?.() === true; const hasNativePromise = isNativeFunction(Promise); const hasPromiseQueuedToJSVM = hasNativePromise || hasHermesPromiseQueuedToJSVM; // In bridgeless mode, timers are host functions installed from cpp. if (global.RN$Bridgeless !== true) { /** * Set up timers. * You can use this module directly, or just require InitializeCore. */ const defineLazyTimer = ( name: | $TEMPORARY$string<'cancelAnimationFrame'> | $TEMPORARY$string<'cancelIdleCallback'> | $TEMPORARY$string<'clearInterval'> | $TEMPORARY$string<'clearTimeout'> | $TEMPORARY$string<'requestAnimationFrame'> | $TEMPORARY$string<'requestIdleCallback'> | $TEMPORARY$string<'setInterval'> | $TEMPORARY$string<'setTimeout'>, ) => { polyfillGlobal(name, () => require('./Timers/JSTimers')[name]); }; defineLazyTimer('setTimeout'); defineLazyTimer('clearTimeout'); defineLazyTimer('setInterval'); defineLazyTimer('clearInterval'); defineLazyTimer('requestAnimationFrame'); defineLazyTimer('cancelAnimationFrame'); defineLazyTimer('requestIdleCallback'); defineLazyTimer('cancelIdleCallback'); } /** * Set up immediate APIs, which is required to use the same microtask queue * as the Promise. */ if (hasPromiseQueuedToJSVM) { // When promise queues to the JSVM microtasks queue, we shim the immediate // APIs via `queueMicrotask` to maintain the backward compatibility. polyfillGlobal( 'setImmediate', () => require('./Timers/immediateShim').setImmediate, ); polyfillGlobal( 'clearImmediate', () => require('./Timers/immediateShim').clearImmediate, ); } else { // When promise was polyfilled hence is queued to the RN microtask queue, // we polyfill the immediate APIs as aliases to the ReactNativeMicrotask APIs. // Note that in bridgeless mode, immediate APIs are installed from cpp. if (global.RN$Bridgeless !== true) { polyfillGlobal( 'setImmediate', () => require('./Timers/JSTimers').queueReactNativeMicrotask, ); polyfillGlobal( 'clearImmediate', () => require('./Timers/JSTimers').clearReactNativeMicrotask, ); } } /** * Set up the microtask queueing API, which is required to use the same * microtask queue as the Promise. */ if (hasHermesPromiseQueuedToJSVM) { // Fast path for Hermes. polyfillGlobal('queueMicrotask', () => global.HermesInternal?.enqueueJob); } else { // Polyfill it with promise (regardless it's polyfilled or native) otherwise. polyfillGlobal( 'queueMicrotask', () => require('./Timers/queueMicrotask.js').default, ); }