Skip to content

Commit b29dc96

Browse files
durvesh1992meta-codesync[bot]
authored andcommitted
Fix Blob.slice() for negative start and inverted ranges (#57374)
Summary: `Blob.slice(start, end)` is modeled on the [W3C Blob API](https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice), where both `start` and `end` may be negative (relative to the end of the blob) and an `end` that precedes `start` yields an empty blob. The current implementation handles a negative `end` but not a negative `start`: ```js if (typeof start === 'number') { if (start > size) { start = size; } // only the upper bound is checked offset += start; size -= start; if (typeof end === 'number') { if (end < 0) { end = this.size + end; } // negative end IS handled if (end > this.size) { end = this.size; } size = end - start; // not clamped to >= 0 } } ``` So: - `blob.slice(-100)` sets `offset` to a **negative** value and makes `size` *larger* than the blob, instead of slicing the last 100 bytes. - `blob.slice(200, 100)` (end before start) produces a **negative** size. ## Fix - Normalize a negative `start` relative to the blob size (`Math.max(this.size + start, 0)`), mirroring the existing `end` handling. - Clamp the resulting size with `Math.max(end - start, 0)` so an inverted range yields an empty blob. Changelog: [General][Fixed] Fix Blob.slice() for negative start and inverted ranges Pull Request resolved: #57374 Test Plan: Added tests to `Libraries/Blob/__tests__/Blob-test.js` for negative start, negative end, and end-precedes-start. The negative-start and inverted-range cases fail before this change (negative offset / negative size) and pass after; existing slice tests and the rest of the suite still pass (8/8). ESLint clean on the changed files. ## Changelog: [General] [Fixed] - Fix `Blob.slice()` for negative start offsets and inverted ranges Reviewed By: cortinico Differential Revision: D110173869 Pulled By: javache fbshipit-source-id: 9f15bfa9c7d8fbba3f7f3b2473c3b39c9cf9d2fe
1 parent f500f42 commit b29dc96

2 files changed

Lines changed: 39 additions & 1 deletion

File tree

packages/react-native/Libraries/Blob/Blob.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ class Blob {
8686
let {offset, size} = this.data;
8787

8888
if (typeof start === 'number') {
89+
if (start < 0) {
90+
// A negative start is relative to the end of the blob.
91+
// $FlowFixMe[reassign-const]
92+
start = Math.max(this.size + start, 0);
93+
}
8994
if (start > size) {
9095
// $FlowFixMe[reassign-const]
9196
start = size;
@@ -102,7 +107,8 @@ class Blob {
102107
// $FlowFixMe[reassign-const]
103108
end = this.size;
104109
}
105-
size = end - start;
110+
// Clamp to 0 so an end that precedes start yields an empty blob.
111+
size = Math.max(end - start, 0);
106112
}
107113
}
108114
return BlobManager.createFromOptions({

packages/react-native/Libraries/Blob/__tests__/Blob-test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,38 @@ describe('Blob', function () {
8181
expect(sliceC.size).toBe(Math.min(blob.data.size, 34569) - 34543);
8282
});
8383

84+
it('should slice a blob with a negative start', () => {
85+
const blob = new Blob();
86+
blob.data.size = 34546;
87+
88+
// A negative start is relative to the end of the blob.
89+
const slice = blob.slice(-100);
90+
91+
expect(slice.data.offset).toBe(34446);
92+
expect(slice.size).toBe(100);
93+
});
94+
95+
it('should slice a blob with a negative end', () => {
96+
const blob = new Blob();
97+
blob.data.size = 34546;
98+
99+
// A negative end is relative to the end of the blob.
100+
const slice = blob.slice(0, -100);
101+
102+
expect(slice.data.offset).toBe(0);
103+
expect(slice.size).toBe(34446);
104+
});
105+
106+
it('should return an empty slice when end precedes start', () => {
107+
const blob = new Blob();
108+
blob.data.size = 34546;
109+
110+
const slice = blob.slice(200, 100);
111+
112+
expect(slice.data.offset).toBe(200);
113+
expect(slice.size).toBe(0);
114+
});
115+
84116
it('should slice a blob and sets a contentType', () => {
85117
const blob = new Blob();
86118

0 commit comments

Comments
 (0)