Skip to content

Commit e4cf0a1

Browse files
ya-nshmeta-codesync[bot]
authored andcommitted
fix: parse Image srcSet densities consistently (#56890)
Summary: - parse Image `srcSet` entries even when there is no space after the comma - keep fractional density descriptors like `1.5x` - keep bare `x` descriptors out of the source list ## Changelog: [General] [Fixed] - Parse Image srcSet density descriptors consistently Pull Request resolved: #56890 Test Plan: - `yarn jest packages/react-native/Libraries/Image/__tests__/ImageSourceUtils-test.js --runInBand` - `npx prettier --check packages/react-native/Libraries/Image/ImageSourceUtils.js packages/react-native/Libraries/Image/__tests__/ImageSourceUtils-test.js` - `yarn flow-check` Reviewed By: christophpurrer Differential Revision: D105689719 Pulled By: javache fbshipit-source-id: f0b947c9fcc6a70211925287bca9f753a161b39c
1 parent 88a6ace commit e4cf0a1

2 files changed

Lines changed: 67 additions & 3 deletions

File tree

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,20 @@ export function getImageSourcesFromImageProps(imageProps: ImageProps):
4747
}
4848
if (srcSet != null) {
4949
const sourceList = [];
50-
const srcSetList = srcSet.split(', ');
50+
const srcSetList = srcSet
51+
.split(',')
52+
.map(imageSrc => imageSrc.trim())
53+
.filter(Boolean);
5154
// `src` prop should be used with default scale if `srcSet` does not have 1x scale.
5255
let shouldUseSrcForDefaultScale = true;
5356
srcSetList.forEach(imageSrc => {
54-
const [uri, xScale = '1x'] = imageSrc.split(' ');
57+
const [uri, xScale = '1x'] = imageSrc.split(/\s+/);
5558
if (!xScale.endsWith('x')) {
5659
console.warn(
5760
'The provided format for scale is not supported yet. Please use scales like 1x, 2x, etc.',
5861
);
5962
} else {
60-
const scale = parseInt(xScale.split('x')[0], 10);
63+
const scale = parseFloat(xScale.slice(0, -1));
6164
if (!isNaN(scale)) {
6265
// 1x scale is provided in `srcSet` prop so ignore the `src` prop if provided.
6366
shouldUseSrcForDefaultScale =

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

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,67 @@ describe('ImageSourceUtils', () => {
105105
expect(sources[1]).toEqual(expect.objectContaining({uri: uri2, scale: 1}));
106106
});
107107

108+
it('should parse srcSet values without spaces after commas', () => {
109+
const imageProps = {
110+
srcSet: 'uri1 1x,uri2 2x,uri3 3x',
111+
};
112+
const sources = getImageSourcesFromImageProps(imageProps);
113+
114+
expect(sources).toBeDefined();
115+
expect(sources).toHaveLength(3);
116+
if (!Array.isArray(sources)) {
117+
throw new Error('Expected `sources` to be an array');
118+
}
119+
expect(sources[0]).toEqual(
120+
expect.objectContaining({uri: 'uri1', scale: 1}),
121+
);
122+
expect(sources[1]).toEqual(
123+
expect.objectContaining({uri: 'uri2', scale: 2}),
124+
);
125+
expect(sources[2]).toEqual(
126+
expect.objectContaining({uri: 'uri3', scale: 3}),
127+
);
128+
});
129+
130+
it('should parse fractional srcSet scales', () => {
131+
const imageProps = {
132+
srcSet: 'uri1 1.5x, uri2 2x',
133+
};
134+
const sources = getImageSourcesFromImageProps(imageProps);
135+
136+
expect(sources).toBeDefined();
137+
expect(sources).toHaveLength(2);
138+
if (!Array.isArray(sources)) {
139+
throw new Error('Expected `sources` to be an array');
140+
}
141+
expect(sources[0]).toEqual(
142+
expect.objectContaining({uri: 'uri1', scale: 1.5}),
143+
);
144+
expect(sources[1]).toEqual(
145+
expect.objectContaining({uri: 'uri2', scale: 2}),
146+
);
147+
});
148+
149+
it('should ignore srcSet entries with a bare x descriptor', () => {
150+
const imageProps = {
151+
src: 'fallbackUri',
152+
srcSet: 'invalid x, uri2 2x',
153+
};
154+
const sources = getImageSourcesFromImageProps(imageProps);
155+
156+
expect(sources).toBeDefined();
157+
expect(sources).toHaveLength(2);
158+
if (!Array.isArray(sources)) {
159+
throw new Error('Expected `sources` to be an array');
160+
}
161+
expect(sources[0]).toEqual(
162+
expect.objectContaining({uri: 'uri2', scale: 2}),
163+
);
164+
expect(sources[1]).toEqual(
165+
expect.objectContaining({uri: 'fallbackUri', scale: 1}),
166+
);
167+
});
168+
108169
it('should warn when an unsupported scale is provided in srcSet', () => {
109170
const mockWarn = jest.spyOn(console, 'warn').mockImplementation(() => {});
110171
let uri1 = 'uri1';

0 commit comments

Comments
 (0)