fix(std/node): Buffer.copy doesn't work as expected (#8125)

This commit is contained in:
Steven Guerrero 2020-10-26 09:42:36 -05:00 committed by GitHub
parent 6a8d0d81c1
commit d52fb903cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 20 deletions

View file

@ -163,10 +163,16 @@ export default class Buffer extends Uint8Array {
} }
} }
const buffer = new Buffer(totalLength); const buffer = Buffer.allocUnsafe(totalLength);
let pos = 0; let pos = 0;
for (const buf of list) { for (const item of list) {
buffer.set(buf, pos); let buf: Buffer;
if (!(item instanceof Buffer)) {
buf = Buffer.from(item);
} else {
buf = item;
}
buf.copy(buffer, pos);
pos += buf.length; pos += buf.length;
} }
@ -247,7 +253,12 @@ export default class Buffer extends Uint8Array {
sourceStart = 0, sourceStart = 0,
sourceEnd = this.length, sourceEnd = this.length,
): number { ): number {
const sourceBuffer = this.subarray(sourceStart, sourceEnd); const sourceBuffer = this
.subarray(sourceStart, sourceEnd)
.subarray(0, Math.max(0, targetBuffer.length - targetStart));
if (sourceBuffer.length === 0) return 0;
targetBuffer.set(sourceBuffer, targetStart); targetBuffer.set(sourceBuffer, targetStart);
return sourceBuffer.length; return sourceBuffer.length;
} }

View file

@ -260,10 +260,15 @@ Deno.test({
Deno.test({ Deno.test({
name: "Two Buffers are concatenated", name: "Two Buffers are concatenated",
fn() { fn() {
const buffer1 = Buffer.alloc(1); const data1 = [1, 2, 3];
const buffer2 = Buffer.alloc(2); const data2 = [4, 5, 6];
const buffer1 = Buffer.from(data1);
const buffer2 = Buffer.from(data2);
const resultBuffer = Buffer.concat([buffer1, buffer2]); const resultBuffer = Buffer.concat([buffer1, buffer2]);
assertEquals(resultBuffer.length, 3, "Buffer length should be 3"); const expectedBuffer = Buffer.from([...data1, ...data2]);
assertEquals(resultBuffer, expectedBuffer);
}, },
}); });
@ -285,27 +290,95 @@ Deno.test({
}); });
Deno.test({ Deno.test({
name: "concat respects totalLenght parameter", name: "Buffer concat respects totalLenght parameter",
fn() { fn() {
const maxLength1 = 10;
const buffer1 = Buffer.alloc(2); const buffer1 = Buffer.alloc(2);
const buffer2 = Buffer.alloc(2); const buffer2 = Buffer.alloc(2);
const resultBuffer = Buffer.concat([buffer1, buffer2], 10); assertEquals(
assertEquals(resultBuffer.length, 10, "Buffer length should be 10"); Buffer.concat([buffer1, buffer2], maxLength1).length,
maxLength1,
);
const maxLength2 = 3;
const buffer3 = Buffer.alloc(2);
const buffer4 = Buffer.alloc(2);
assertEquals(
Buffer.concat([buffer3, buffer4], maxLength2).length,
maxLength2,
);
}, },
}); });
Deno.test({ Deno.test({
name: "concat totalLenght throws if is lower than the size of the buffers", name: "Buffer copy works as expected",
fn() { fn() {
const buffer1 = Buffer.alloc(2); const data1 = new Uint8Array([1, 2, 3]);
const buffer2 = Buffer.alloc(2); const data2 = new Uint8Array([4, 5, 6]);
assertThrows(
() => { const buffer1 = Buffer.from(data1);
Buffer.concat([buffer1, buffer2], 3); const buffer2 = Buffer.from(data2);
},
RangeError, //Mutates data_1
"offset is out of bounds", data1.set(data2);
"should throw on negative numbers", //Mutates buffer_1
buffer2.copy(buffer1);
assertEquals(
data1,
buffer1,
);
},
});
Deno.test({
name: "Buffer copy respects the starting point for copy",
fn() {
const buffer1 = Buffer.from([1, 2, 3]);
const buffer2 = Buffer.alloc(8);
buffer1.copy(buffer2, 5);
const expected = Buffer.from([0, 0, 0, 0, 0, 1, 2, 3]);
assertEquals(
buffer2,
expected,
);
},
});
Deno.test({
name: "Buffer copy doesn't throw on offset but copies until offset reached",
fn() {
const buffer1 = Buffer.from([1, 2, 3]);
const buffer2 = Buffer.alloc(8);
const writtenBytes1 = buffer1.copy(buffer2, 6);
assertEquals(
writtenBytes1,
2,
);
assertEquals(
buffer2,
Buffer.from([0, 0, 0, 0, 0, 0, 1, 2]),
);
const buffer3 = Buffer.from([1, 2, 3]);
const buffer4 = Buffer.alloc(8);
const writtenBytes2 = buffer3.copy(buffer4, 8);
assertEquals(
writtenBytes2,
0,
);
assertEquals(
buffer4,
Buffer.from([0, 0, 0, 0, 0, 0, 0, 0]),
); );
}, },
}); });