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
15 changes: 14 additions & 1 deletion packages/react-native/Libraries/Alert/RCTAlertManager.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,25 @@ import NativeDialogManagerAndroid from '../NativeModules/specs/NativeDialogManag

function emptyCallback() {}

/**
* Shows an alert dialog on Android using the native DialogManagerAndroid module.
* Falls back gracefully if the native module is not available.
*
* @param {Args} args - The alert configuration (title, message, buttons, etc.)
* @param {Function} callback - Callback function invoked with (id, value) when user selects an option
* @returns {void}
* @note NativeDialogManagerAndroid provides better Android-specific UI/UX than the
* standard AlertManager. If unavailable, the alert silently fails to prevent crashes.
* See TODO(5998984) for improved polyfill implementation.
*/
export function alertWithArgs(
args: Args,
callback: (id: number, value: string) => void,
) {
// TODO(5998984): Polyfill it correctly with DialogManagerAndroid
if (!NativeDialogManagerAndroid) {
console.warn(
'NativeDialogManagerAndroid is not available. Alert may not be displayed.',
);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,15 @@ type OnAnimationDidFailCallback = () => void;
let isLayoutAnimationEnabled: boolean =
ReactNativeFeatureFlags.isLayoutAnimationEnabled();

/**
* Internal function to enable or disable layout animations.
* When disabled, configureNext calls will be no-ops.
*
* @param {boolean} value - Whether to enable layout animations
* @internal
*/
function setLayoutAnimationEnabled(value: boolean) {
isLayoutAnimationEnabled = isLayoutAnimationEnabled;
isLayoutAnimationEnabled = value;
}

/**
Expand Down
18 changes: 12 additions & 6 deletions packages/react-native/Libraries/Utilities/FeatureDetection.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,25 @@
*/

/**
* @return whether or not a @param {function} f is provided natively by calling
* `toString` and check if the result includes `[native code]` in it.
* Detects if a function is a native function (not a polyfill or user-defined).
*
* Note that a polyfill can technically fake this behavior but few does it.
* Therefore, this is usually good enough for our purpose.
* Checks if the function's toString representation includes `[native code]`.
* Note: A polyfill can technically fake this, but most don't, making this
* check reliable for practical purposes.
*
* @param {Function} f - Function to check
* @returns {boolean} True if the function is a native function
*/
export function isNativeFunction(f: Function): boolean {
return typeof f === 'function' && f.toString().indexOf('[native code]') > -1;
}

/**
* @return whether or not the constructor of @param {object} o is an native
* function named with @param {string} expectedName.
* Checks if an object's constructor is a native function with a specific name.
*
* @param {Object} o - Object to check
* @param {string} expectedName - Expected constructor name
* @returns {boolean} True if the constructor is native and matches the expected name
*/
export function hasNativeConstructor(o: Object, expectedName: string): boolean {
const con = Object.getPrototypeOf(o).constructor;
Expand Down
22 changes: 20 additions & 2 deletions packages/react-native/Libraries/Utilities/RCTLog.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ const levelsMap = {
let warningHandler: ?(...Array<unknown>) => void = null;

const RCTLog = {
// level one of log, info, warn, error, mustfix
/**
* Logs to console only if the native logging hook is unavailable.
* If available, delegates to native logging and reports warnings to LogBox.
*
* @param {string} level - Log level: 'log', 'info', 'warn', 'error', or 'fatal'
* @param {...any} args - Arguments to log
*/
logIfNoNativeHook(level: string, ...args: Array<unknown>): void {
// We already printed in the native console, so only log here if using a js debugger
if (typeof global.nativeLoggingHook === 'undefined') {
Expand All @@ -36,7 +42,14 @@ const RCTLog = {
}
},

// Log to console regardless of nativeLoggingHook
/**
* Logs to console regardless of native logging hook availability.
* Throws an invariant if the log level is invalid.
*
* @param {string} level - Log level: 'log', 'info', 'warn', 'error', or 'fatal'
* @param {...any} args - Arguments to log
* @throws Invariant error if level is not a valid log level
*/
logToConsole(level: string, ...args: Array<unknown>): void {
// $FlowFixMe[invalid-computed-prop]
const logFn = levelsMap[level];
Expand All @@ -48,6 +61,11 @@ const RCTLog = {
console[logFn](...args);
},

/**
* Sets a custom warning handler to process warnings reported to LogBox.
*
* @param {?Function} handler - Function to handle warnings, or null to remove the handler
*/
setWarningHandler(handler: typeof warningHandler): void {
warningHandler = handler;
},
Expand Down
17 changes: 17 additions & 0 deletions packages/react-native/Libraries/Utilities/SceneTracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,33 @@ let _listeners: Array<(scene: Scene) => void> = [];

let _activeScene: Scene = {name: 'default'};

/**
* Global scene tracker for managing the currently active scene in the application.
* Notifies listeners whenever the active scene changes.
*/
const SceneTracker = {
/**
* Sets the currently active scene and notifies all registered listeners.
* @param {Scene} scene - The new active scene object
*/
setActiveScene(scene: Scene) {
_activeScene = scene;
_listeners.forEach(listener => listener(_activeScene));
},

/**
* Gets the currently active scene.
* @returns {Scene} The active scene object
*/
getActiveScene(): Scene {
return _activeScene;
},

/**
* Registers a listener to be called whenever the active scene changes.
* @param {Function} callback - Function called with the new scene when it changes
* @returns {Object} Object with a remove() method to unsubscribe
*/
addActiveSceneChangedListener(callback: (scene: Scene) => void): {
remove: () => void,
...
Expand Down
14 changes: 12 additions & 2 deletions packages/react-native/Libraries/Utilities/differ/deepDiffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,18 @@ function unstable_setLogListeners(listeners: ?LogListeners) {
logListeners = listeners;
}

/*
* @returns {bool} true if different, false if equal
/**
* Deep equality comparison that recursively checks all properties.
*
* Returns true if values differ, false if equal. Handles primitives, objects,
* arrays, and mixed types. Functions are considered equal by default unless
* unsafelyIgnoreFunctions is set to false.
*
* @param {any} one - First value
* @param {any} two - Second value
* @param {Options|number} maxDepthOrOptions - Max recursion depth or options
* @param {Options} maybeOptions - Options when first is number
* @returns {boolean} True if different, false if equal
*/
function deepDiffer(
one: any,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ const dummyInsets = {
bottom: undefined,
};

/**
* Compares two inset objects for equality.
* Returns true if the insets are different, false if equal.
*
* @param {Inset} one - First inset object (top, left, right, bottom)
* @param {Inset} two - Second inset object
* @returns {boolean} True if insets differ, false if equal
* @performance O(1) - Compares only four numeric values
*/
function insetsDiffer(one: Inset, two: Inset): boolean {
one = one || dummyInsets;
two = two || dummyInsets;
Expand Down
16 changes: 10 additions & 6 deletions packages/react-native/Libraries/Utilities/differ/matricesDiffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@
'use strict';

/**
* Unrolls an array comparison specially for matrices. Prioritizes
* checking of indices that are most likely to change so that the comparison
* bails as early as possible.
* Unrolls an array comparison specially for matrices (4x4 transformation matrices).
*
* @param {MatrixMath.Matrix} one First matrix.
* @param {MatrixMath.Matrix} two Second matrix.
* @return {boolean} Whether or not the two matrices differ.
* Prioritizes checking of indices that are most likely to change so that the
* comparison bails as early as possible. This optimizes for common transformations.
*
* Index check order: [12,13,14,5,10,0,1,2,3,4,6,7,8,9,11,15]
*
* @param {?Array<number>} one - First matrix (16 elements)
* @param {?Array<number>} two - Second matrix (16 elements)
* @returns {boolean} True if matrices differ, false if equal
* @performance O(1) - Fixed size comparison, early exit on first difference
*/
function matricesDiffer(one: ?Array<number>, two: ?Array<number>): boolean {
if (one === two) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ type Point = {

const dummyPoint: Point = {x: undefined, y: undefined};

/**
* Compares two point objects for equality.
* Returns true if the points are different, false if equal.
*
* @param {?Point} one - First point object with x, y coordinates
* @param {?Point} two - Second point object with x, y coordinates
* @returns {boolean} True if points differ, false if equal
* @performance O(1) - Compares only two numeric values
*/
function pointsDiffer(one: ?Point, two: ?Point): boolean {
one = one || dummyPoint;
two = two || dummyPoint;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@
const dummySize = {width: undefined, height: undefined};
type Size = {width: ?number, height: ?number};

/**
* Compares two size objects for equality.
* Returns true if the sizes are different, false if equal.
*
* @param {Size} one - First size object with width, height
* @param {Size} two - Second size object with width, height
* @returns {boolean} True if sizes differ, false if equal
* @performance O(1) - Compares only two numeric values
*/
function sizesDiffer(one: Size, two: Size): boolean {
const defaultedOne = one || dummySize;
const defaultedTwo = two || dummySize;
Expand Down
15 changes: 13 additions & 2 deletions packages/react-native/Libraries/Utilities/dismissKeyboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,24 @@
* @format
*/

// This function dismisses the currently-open keyboard, if any.

'use strict';

const TextInputState =
require('../Components/TextInput/TextInputState').default;

/**
* Programmatically dismisses the currently-open keyboard on the device.
*
* This function finds the currently focused text input and blurs it, which triggers
* the keyboard dismissal on iOS and Android.
*
* @example
* import { dismissKeyboard } from 'react-native';
* dismissKeyboard(); // Hide the keyboard
*
* @returns {void}
* @note This is a no-op if no text input is currently focused.
*/
function dismissKeyboard() {
TextInputState.blurTextInput(TextInputState.currentlyFocusedInput());
}
Expand Down
14 changes: 14 additions & 0 deletions packages/react-native/Libraries/Utilities/mapWithSeparator.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@

'use strict';

/**
* Maps an array of items to new values, inserting a separator between items.
*
* @template TFrom - Type of input array elements
* @template TTo - Type of output array elements
* @param {Array<TFrom>} items - Items to map
* @param {Function} itemRenderer - Function to render each item: (item, index, items) => TTo
* @param {Function} spacerRenderer - Function to render separators: (index) => TTo
* @returns {Array<TTo>} Array with items and separators interleaved
*
* @example
* mapWithSeparator(['a', 'b', 'c'], x => <Text>{x}</Text>, () => <Comma />)
* // Returns: [<Text>a</Text>, <Comma />, <Text>b</Text>, <Comma />, <Text>c</Text>]
*/
function mapWithSeparator<TFrom, TTo>(
items: Array<TFrom>,
itemRenderer: (item: TFrom, index: number, items: Array<TFrom>) => TTo,
Expand Down
14 changes: 14 additions & 0 deletions packages/react-native/Libraries/Utilities/stringifyViewConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
* @format
*/

/**
* Serializes a view configuration object to a JSON string for debugging and logging.
*
* Handles special cases like function properties by representing them with the
* Unicode function symbol (ƒ) followed by the function name.
*
* @param {any} viewConfig - The view configuration object to stringify
* @returns {string} Formatted JSON string with 2-space indentation
*
* @example
* const config = { name: 'View', style: { flex: 1 }, onPress: [Function] };
* const json = stringifyViewConfig(config);
* // Returns: "{ ... name: 'View', style: { flex: 1 }, onPress: ƒ onPress ... }"
*/
export default function stringifyViewConfig(viewConfig: any): string {
return JSON.stringify(
viewConfig,
Expand Down
4 changes: 3 additions & 1 deletion packages/virtualized-lists/Lists/VirtualizedList.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ class VirtualizedList extends StateSafePureComponent<
this._scrollMetrics.visibleLength,
);

// TODO: consider using `ref.scrollToEnd` directly
// Using scrollToOffset instead of direct ref.scrollToEnd to maintain consistent
// offset calculation and support the optional animation parameter. The direct ref
// approach would bypass important viewOffset adjustments.
this.scrollToOffset({animated, offset});
}

Expand Down
Loading