Skip to content

Commit dd3c200

Browse files
javachemeta-codesync[bot]
authored andcommitted
Fix width/height not propagating to styles when uri is used (#55495)
Summary: Pull Request resolved: #55495 Changelog: [General][Fixed] When using Image with a `uri`, `width` and `height` the default dimensions were being lost Reviewed By: yungsters Differential Revision: D92891095 fbshipit-source-id: ce6a136603be5c56dd49f8695412165ffe75b33b
1 parent 995879c commit dd3c200

5 files changed

Lines changed: 102 additions & 13 deletions

File tree

packages/react-native/Libraries/Image/Image.android.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {ImageProps} from './ImageProps';
1515
import type {ImageSourceHeaders} from './ImageSourceUtils';
1616
import type {AbstractImageAndroid, ImageAndroid} from './ImageTypes.flow';
1717

18+
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
1819
import flattenStyle from '../StyleSheet/flattenStyle';
1920
import StyleSheet from '../StyleSheet/StyleSheet';
2021
import TextAncestorContext from '../Text/TextAncestorContext';
@@ -201,17 +202,33 @@ let BaseImage: AbstractImageAndroid = ({
201202
let sources_;
202203
let headers_: ?ImageSourceHeaders;
203204
if (Array.isArray(source_)) {
204-
style_ = [styles.base, style];
205+
const {
206+
headers: sourceHeaders,
207+
width: sourceWidth,
208+
height: sourceHeight,
209+
} = source_[0];
210+
headers_ = sourceHeaders;
211+
// Default to the first source's width and height if only one is provided
212+
if (ReactNativeFeatureFlags.fixImageSrcDimensionPropagation()) {
213+
style_ = [
214+
source_.length === 1 && {width: sourceWidth, height: sourceHeight},
215+
styles.base,
216+
style,
217+
];
218+
} else {
219+
style_ = [styles.base, style];
220+
}
205221
sources_ = source_;
206-
headers_ = sources_[0].headers;
207222
} else {
208-
const {uri} = source_;
223+
const {uri, width: sourceWidth, height: sourceHeight} = source_;
209224
if (uri === '') {
210225
console.warn('source.uri should not be an empty string');
211226
}
212-
const width_ = source_.width ?? width;
213-
const height_ = source_.height ?? height;
214-
style_ = [{width: width_, height: height_}, styles.base, style];
227+
style_ = [
228+
{width: sourceWidth ?? width, height: sourceHeight ?? height},
229+
styles.base,
230+
style,
231+
];
215232
sources_ = [source_];
216233
}
217234

packages/react-native/Libraries/Image/ImageSourceUtils.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,15 @@ export type ImageSourceHeaders = {
2323
* A function which returns the appropriate value for image source
2424
* by resolving the `source`, `src` and `srcSet` props.
2525
*/
26-
export function getImageSourcesFromImageProps(
27-
imageProps: ImageProps,
28-
):
26+
export function getImageSourcesFromImageProps(imageProps: ImageProps):
2927
| ?ResolvedAssetSource
30-
| ReadonlyArray<{uri: string, headers: ImageSourceHeaders, ...}> {
28+
| ReadonlyArray<{
29+
+uri: string,
30+
+headers: ImageSourceHeaders,
31+
+width: ?number,
32+
+height: ?number,
33+
...
34+
}> {
3135
let source = resolveAssetSource(imageProps.source);
3236

3337
let sources;

packages/react-native/Libraries/Image/__tests__/Image-itest.js

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
* LICENSE file in the root directory of this source tree.
66
*
77
* @flow strict-local
8+
* @fantom_flags fixImageSrcDimensionPropagation:*
89
* @format
910
*/
1011

1112
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
1213

1314
import type {AccessibilityProps, HostInstance} from 'react-native';
1415

16+
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
1517
import * as Fantom from '@react-native/fantom';
1618
import * as React from 'react';
1719
import {createRef} from 'react';
@@ -239,14 +241,26 @@ describe('<Image>', () => {
239241

240242
Fantom.runTask(() => {
241243
root.render(
242-
<Image referrerPolicy={referrerPolicy} src={LOGO_SOURCE.uri} />,
244+
<>
245+
<Image referrerPolicy={referrerPolicy} src={LOGO_SOURCE.uri} />
246+
<Image referrerPolicy={referrerPolicy} source={LOGO_SOURCE} />
247+
</>,
243248
);
244249
});
245250

246251
expect(
247252
root.getRenderedOutput({props: ['source-header']}).toJSX(),
248253
).toEqual(
249-
<rn-image source-header-Referrer-Policy={referrerPolicy} />,
254+
<>
255+
<rn-image
256+
key="0"
257+
source-header-Referrer-Policy={referrerPolicy}
258+
/>
259+
<rn-image
260+
key="1"
261+
source-header-Referrer-Policy={referrerPolicy}
262+
/>
263+
</>,
250264
);
251265
});
252266
});
@@ -444,6 +458,44 @@ describe('<Image>', () => {
444458
/>,
445459
);
446460
});
461+
462+
it('merges dimension information into source', () => {
463+
const root = Fantom.createRoot();
464+
465+
Fantom.runTask(() => {
466+
root.render(
467+
<Image
468+
src="https://reactnative.dev/img/tiny_logo.png"
469+
width={40}
470+
height={40}
471+
/>,
472+
);
473+
});
474+
475+
expect(
476+
root
477+
.getRenderedOutput({props: ['source', 'width', 'height']})
478+
.toJSX(),
479+
).toEqual(
480+
ReactNativeFeatureFlags.fixImageSrcDimensionPropagation() ? (
481+
<rn-image
482+
source-scale="1"
483+
source-type="remote"
484+
source-size="{40, 40}"
485+
source-uri="https://reactnative.dev/img/tiny_logo.png"
486+
width="40.000000"
487+
height="40.000000"
488+
/>
489+
) : (
490+
<rn-image
491+
source-scale="1"
492+
source-type="remote"
493+
source-size="{40, 40}"
494+
source-uri="https://reactnative.dev/img/tiny_logo.png"
495+
/>
496+
),
497+
);
498+
});
447499
});
448500

449501
describe('srcSet', () => {

packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,16 @@ const definitions: FeatureFlagDefinitions = {
947947
},
948948
ossReleaseStage: 'none',
949949
},
950+
fixImageSrcDimensionPropagation: {
951+
defaultValue: false,
952+
metadata: {
953+
description:
954+
'Fix image dimensions not being passed through when src is used',
955+
expectedReleaseValue: true,
956+
purpose: 'release',
957+
},
958+
ossReleaseStage: 'none',
959+
},
950960
fixVirtualizeListCollapseWindowSize: {
951961
defaultValue: false,
952962
metadata: {

packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<4680a90fe6a071f6352de95fc1ca01ba>>
7+
* @generated SignedSource<<7d3f35de8808eb703debde85df332df8>>
88
* @flow strict
99
* @noformat
1010
*/
@@ -34,6 +34,7 @@ export type ReactNativeFeatureFlagsJsOnly = $ReadOnly<{
3434
deferFlatListFocusChangeRenderUpdate: Getter<boolean>,
3535
disableMaintainVisibleContentPosition: Getter<boolean>,
3636
externalElementInspectionEnabled: Getter<boolean>,
37+
fixImageSrcDimensionPropagation: Getter<boolean>,
3738
fixVirtualizeListCollapseWindowSize: Getter<boolean>,
3839
isLayoutAnimationEnabled: Getter<boolean>,
3940
shouldUseAnimatedObjectForTransform: Getter<boolean>,
@@ -157,6 +158,11 @@ export const disableMaintainVisibleContentPosition: Getter<boolean> = createJava
157158
*/
158159
export const externalElementInspectionEnabled: Getter<boolean> = createJavaScriptFlagGetter('externalElementInspectionEnabled', true);
159160

161+
/**
162+
* Fix image dimensions not being passed through when src is used
163+
*/
164+
export const fixImageSrcDimensionPropagation: Getter<boolean> = createJavaScriptFlagGetter('fixImageSrcDimensionPropagation', false);
165+
160166
/**
161167
* Fixing an edge case where the current window size is not properly calculated with fast scrolling. Window size collapsed to 1 element even if windowSize more than the current amount of elements
162168
*/

0 commit comments

Comments
 (0)