Skip to content

Commit 1f1cc9b

Browse files
committed
fix: address review feedback on finalKey merge block
- Guard finalKey block with config.target.length === 1 so it only runs for length-1 array targets, not nested paths handled by recursion - Explicitly write filtered rightValue in all code paths to prevent unfiltered VAR_SYMBOL objects from leaking into RN props - Add defensive comment about leaf-key storage limitation in getStyledProps
1 parent a4eda4b commit 1f1cc9b

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

src/native/styles/index.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,12 @@ export function getStyledProps(
196196
// deepMergeConfig produces a full props object via Object.assign({}, left, right).
197197
// Later iterations overwrite earlier ones' correctly-merged target props.
198198
// We save each iteration's target value and restore them after the loop.
199+
//
200+
// Note: This uses the leaf key of config.target for storage/restoration.
201+
// For nested array targets (length > 1), the leaf key is stored at the
202+
// top level, which is correct because deepMergeConfig already builds the
203+
// nested structure. If two configs ever share the same leaf key, the last
204+
// one wins — but no built-in component mapping produces this scenario.
199205
const computedTargets: Record<string, any> = {};
200206
const consumedSources: string[] = [];
201207

@@ -475,15 +481,18 @@ function deepMergeConfig(
475481
// above runs 0 iterations. Merge the target prop so inline styles don't
476482
// silently overwrite className-computed styles (same as string target path).
477483
const finalKey = config.target[config.target.length - 1];
478-
if (finalKey && rightIsInline) {
484+
if (config.target.length === 1 && finalKey && rightIsInline) {
479485
let rightValue = right?.[finalKey];
480486
if (rightValue !== undefined) {
481487
rightValue = filterCssVariables(rightValue);
482488
}
483489
if (rightValue === undefined || rightValue === null) {
484-
// Inline is empty — preserve className-computed value
490+
// Inline is empty or fully filtered — preserve className-computed value
485491
if (left && finalKey in left) {
486492
result[finalKey] = left[finalKey];
493+
} else {
494+
// No left value either — remove unfiltered inline value from result
495+
delete result[finalKey];
487496
}
488497
} else if (left && finalKey in left) {
489498
const leftValue = left[finalKey];
@@ -498,11 +507,16 @@ function deepMergeConfig(
498507
if (leftIsObj && rightIsObj) {
499508
if (hasNonOverlappingProperties(leftValue, rightValue)) {
500509
result[finalKey] = [leftValue, rightValue];
510+
} else {
511+
// All left keys are in right — use filtered right value
512+
result[finalKey] = rightValue;
501513
}
502-
// else: all left keys are in right, right overrides — already set by mergeDefinedProps
503514
} else {
504515
result[finalKey] = [leftValue, rightValue];
505516
}
517+
} else {
518+
// No left value — use filtered right value (not the unfiltered one from mergeDefinedProps)
519+
result[finalKey] = rightValue;
506520
}
507521
}
508522

0 commit comments

Comments
 (0)