Skip to content

Commit 18a397a

Browse files
committed
docs: enhance JSDoc for style filtering functions
- Add comprehensive JSDoc for filterCssVariables with explicit return type - Clarify hasNonOverlappingProperties one-directional design is intentional - Document empty array handling convention in flattenStyleArray - Address GitHub Copilot review concerns with improved documentation All concerns were about documentation clarity, not logic bugs. Code remains functionally identical with 970 tests passing.
1 parent dffa268 commit 18a397a

File tree

1 file changed

+43
-4
lines changed

1 file changed

+43
-4
lines changed

src/native/styles/index.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,21 @@ import {
1818
import { calculateProps } from "./calculate-props";
1919

2020
/**
21-
* Checks if two style objects have non-overlapping properties
21+
* Checks if the left style object has any properties that are not present in the right style object.
22+
* This is used to determine if styles need to be preserved in an array or if right can completely override left.
23+
*
24+
* Note: This intentionally only checks one direction (left → right). We don't need to check if right has
25+
* properties that left doesn't have, because right will always be applied/merged. The question we're
26+
* answering is: "Does left have any properties that would be lost if we just used right?" If yes, we
27+
* create a style array [left, right] to preserve both. If no, right can safely replace left entirely.
28+
*
29+
* @param left - The left style object to check
30+
* @param right - The right style object to compare against
31+
* @returns true if left has at least one property key that doesn't exist in right, false otherwise
32+
*
33+
* @example
34+
* hasNonOverlappingProperties({color: 'red', fontSize: 12}, {color: 'blue'}) // true - fontSize is not in right
35+
* hasNonOverlappingProperties({color: 'red'}, {color: 'blue', fontSize: 12}) // false - all left keys exist in right
2236
*/
2337
function hasNonOverlappingProperties(
2438
left: Record<string, any>,
@@ -41,7 +55,14 @@ function hasNonOverlappingProperties(
4155
}
4256

4357
/**
44-
* Flattens a style array into a single object, with rightmost values taking precedence
58+
* Flattens a style array into a single object when possible, with rightmost values taking precedence.
59+
* Returns the original array if it contains any non-plain objects, arrays, or CSS variable objects.
60+
*
61+
* Note: This function assumes the input array has already been filtered (e.g., by filterCssVariables),
62+
* so empty arrays should not reach this function. If they do, they will be treated as non-flattenable.
63+
*
64+
* @param styleArray - The style array to potentially flatten
65+
* @returns A single merged object if all items are plain objects, otherwise the original array
4566
*/
4667
function flattenStyleArray(styleArray: any[]): any {
4768
// Check if we can flatten to a single object (all items are plain objects)
@@ -62,9 +83,27 @@ function flattenStyleArray(styleArray: any[]): any {
6283
}
6384

6485
/**
65-
* Recursively filters out CSS variable objects (with VAR_SYMBOL) from style values
86+
* Recursively filters out CSS variable objects (with VAR_SYMBOL) from style values.
87+
* This prevents CSS variable runtime objects from leaking into React Native component props.
88+
*
89+
* @param value - The value to filter (can be any type: object, array, primitive, etc.)
90+
* @param depth - Internal recursion depth counter to prevent stack overflow (max 100)
91+
* @returns The filtered value with CSS variables removed, or `undefined` if the entire value
92+
* should be filtered out (e.g., empty arrays, objects with only VAR_SYMBOL properties)
93+
*
94+
* Filtering behavior:
95+
* - Objects with VAR_SYMBOL property: returns `undefined` (completely filtered)
96+
* - Arrays: filters out VAR_SYMBOL objects, returns `undefined` if empty after filtering
97+
* - Objects: recursively filters properties, returns `undefined` if no properties remain
98+
* - Primitives (null, undefined, numbers, strings, booleans): returned as-is
99+
* - Symbol properties: intentionally filtered out for React Native compatibility
100+
*
101+
* @example
102+
* filterCssVariables({fontSize: 16, color: {[VAR_SYMBOL]: true}}) // {fontSize: 16}
103+
* filterCssVariables([{margin: 10}, {[VAR_SYMBOL]: true}]) // [{margin: 10}]
104+
* filterCssVariables({color: {[VAR_SYMBOL]: true}}) // undefined (all props filtered)
66105
*/
67-
function filterCssVariables(value: any, depth = 0): any {
106+
function filterCssVariables(value: any, depth = 0): any | undefined {
68107
// Prevent stack overflow on deeply nested structures
69108
if (depth > 100) {
70109
return value;

0 commit comments

Comments
 (0)