Skip to content

Commit 9d2aa9c

Browse files
committed
Fix Blob.slice() for negative start and inverted ranges
Blob.slice() handled a negative `end` (relative to the end of the blob) but not a negative `start`, so `blob.slice(-100)` produced a negative offset and an oversized blob instead of slicing the last 100 bytes. It also computed `size = end - start` without clamping, so calling `slice(start, end)` with `end` before `start` produced a negative size. Normalize a negative start relative to the blob size (matching the existing end handling) and clamp the resulting size to a minimum of 0, per the W3C Blob.slice() semantics. Add tests for negative start, negative end, and end-precedes-start.
1 parent b364490 commit 9d2aa9c

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)