Skip to content

Commit 4501979

Browse files
fallintoplacemeta-codesync[bot]
authored andcommitted
Preserve negative values in transformOrigin strings (#57691)
Summary: The numeric tokenizer updated in #57487 still starts at the first digit when a percentage or pixel value is negative. This silently changes values such as `-12.5px -7.5px` into `[12.5, 7.5, 0]`. Allow a leading minus in numeric tokens so negative percentages, pixel offsets, and leading-dot decimals retain their sign. The pattern is intentionally limited to the failing negative case and leaves leading-plus values unchanged. ## Changelog: [GENERAL] [FIXED] - Preserve negative values in `transformOrigin` strings. Pull Request resolved: #57691 Test Plan: - Added Fantom regression coverage for negative percentages, x/y/z pixel offsets, and leading-dot decimals in `processTransformOrigin-itest.js` - `./node_modules/.bin/prettier --check packages/react-native/Libraries/StyleSheet/processTransformOrigin.js packages/react-native/Libraries/StyleSheet/__tests__/processTransformOrigin-itest.js` - `./node_modules/.bin/eslint --max-warnings 0 packages/react-native/Libraries/StyleSheet/processTransformOrigin.js packages/react-native/Libraries/StyleSheet/__tests__/processTransformOrigin-itest.js` - Ran focused runtime checks against the Flow-stripped parser for the new negative cases and existing leading-plus behavior Reviewed By: javache Differential Revision: D113756417 Pulled By: fabriziocucci fbshipit-source-id: a1506ada24adbeb81892a7c1d821e03ccd388de2
1 parent 4043e81 commit 4501979

3 files changed

Lines changed: 54 additions & 1 deletion

File tree

packages/react-native/Libraries/StyleSheet/__tests__/processTransformOrigin-itest.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,5 +122,16 @@ describe('processTransformOrigin', () => {
122122
expect(processTransformOrigin('12.5px 7.5px')).toEqual([12.5, 7.5, 0]);
123123
expect(processTransformOrigin('.5% .5px')).toEqual(['.5%', 0.5, 0]);
124124
});
125+
it('should preserve negative percentage and pixel values', () => {
126+
expect(processTransformOrigin('-50.5% -30.2%')).toEqual([
127+
'-50.5%',
128+
'-30.2%',
129+
0,
130+
]);
131+
expect(processTransformOrigin('-12.5px -7.5px -2.5px')).toEqual([
132+
-12.5, -7.5, -2.5,
133+
]);
134+
expect(processTransformOrigin('-.5% -.5px')).toEqual(['-.5%', -0.5, 0]);
135+
});
125136
});
126137
});

packages/react-native/Libraries/StyleSheet/processTransformOrigin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import invariant from 'invariant';
1212

1313
// Pre-compiled regex pattern for performance - avoids regex compilation on each call
1414
const TRANSFORM_ORIGIN_REGEX =
15-
/(top|bottom|left|right|center|\d*\.?\d+(?:%|px)|0)/gi;
15+
/(top|bottom|left|right|center|-?\d*\.?\d+(?:%|px)|0)/gi;
1616

1717
const INDEX_X = 0;
1818
const INDEX_Y = 1;

packages/react-native/ReactCommon/react/renderer/css/tests/CSSTransformOriginTest.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,4 +455,46 @@ TEST(CSSTransformOrigin, decimal_percentage_percentage) {
455455
EXPECT_EQ(origin.z, CSSLength{});
456456
}
457457

458+
TEST(CSSTransformOrigin, negative_lengths) {
459+
auto value = parseCSSProperty<CSSTransformOrigin>("-12.5px -7.5px -2.5px");
460+
EXPECT_TRUE(std::holds_alternative<CSSTransformOrigin>(value));
461+
auto& origin = std::get<CSSTransformOrigin>(value);
462+
463+
EXPECT_TRUE(std::holds_alternative<CSSLength>(origin.x));
464+
EXPECT_EQ(std::get<CSSLength>(origin.x).value, -12.5f);
465+
EXPECT_EQ(std::get<CSSLength>(origin.x).unit, CSSLengthUnit::Px);
466+
467+
EXPECT_TRUE(std::holds_alternative<CSSLength>(origin.y));
468+
EXPECT_EQ(std::get<CSSLength>(origin.y).value, -7.5f);
469+
EXPECT_EQ(std::get<CSSLength>(origin.y).unit, CSSLengthUnit::Px);
470+
471+
EXPECT_EQ(origin.z.value, -2.5f);
472+
EXPECT_EQ(origin.z.unit, CSSLengthUnit::Px);
473+
}
474+
475+
TEST(CSSTransformOrigin, negative_percentages) {
476+
auto value = parseCSSProperty<CSSTransformOrigin>("-50.5% -30.2%");
477+
EXPECT_TRUE(std::holds_alternative<CSSTransformOrigin>(value));
478+
auto& origin = std::get<CSSTransformOrigin>(value);
479+
480+
EXPECT_TRUE(std::holds_alternative<CSSPercentage>(origin.x));
481+
EXPECT_EQ(std::get<CSSPercentage>(origin.x).value, -50.5f);
482+
483+
EXPECT_TRUE(std::holds_alternative<CSSPercentage>(origin.y));
484+
EXPECT_EQ(std::get<CSSPercentage>(origin.y).value, -30.2f);
485+
}
486+
487+
TEST(CSSTransformOrigin, negative_leading_dot_values) {
488+
auto value = parseCSSProperty<CSSTransformOrigin>("-.5% -.5px");
489+
EXPECT_TRUE(std::holds_alternative<CSSTransformOrigin>(value));
490+
auto& origin = std::get<CSSTransformOrigin>(value);
491+
492+
EXPECT_TRUE(std::holds_alternative<CSSPercentage>(origin.x));
493+
EXPECT_EQ(std::get<CSSPercentage>(origin.x).value, -0.5f);
494+
495+
EXPECT_TRUE(std::holds_alternative<CSSLength>(origin.y));
496+
EXPECT_EQ(std::get<CSSLength>(origin.y).value, -0.5f);
497+
EXPECT_EQ(std::get<CSSLength>(origin.y).unit, CSSLengthUnit::Px);
498+
}
499+
458500
} // namespace facebook::react

0 commit comments

Comments
 (0)