summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--benchmark/buffers/buffer-copy.js19
-rw-r--r--lib/buffer.js70
-rw-r--r--test/parallel/test-buffer-alloc.js3
-rw-r--r--test/parallel/test-buffer-copy.js23
4 files changed, 105 insertions, 10 deletions
diff --git a/benchmark/buffers/buffer-copy.js b/benchmark/buffers/buffer-copy.js
new file mode 100644
index 0000000000..164f314207
--- /dev/null
+++ b/benchmark/buffers/buffer-copy.js
@@ -0,0 +1,19 @@
+'use strict';
+const common = require('../common.js');
+
+const bench = common.createBenchmark(main, {
+ bytes: [0, 8, 128, 32 * 1024],
+ partial: ['true', 'false'],
+ n: [6e6]
+});
+
+function main({ n, bytes, partial }) {
+ const source = Buffer.allocUnsafe(bytes);
+ const target = Buffer.allocUnsafe(bytes);
+ const sourceStart = (partial === 'true' ? Math.floor(bytes / 2) : 0);
+ bench.start();
+ for (let i = 0; i < n; i++) {
+ source.copy(target, 0, sourceStart);
+ }
+ bench.end(n);
+}
diff --git a/lib/buffer.js b/lib/buffer.js
index 8c16f07ace..7b656496e5 100644
--- a/lib/buffer.js
+++ b/lib/buffer.js
@@ -25,7 +25,6 @@ const { Math, Object } = primordials;
const {
byteLengthUtf8,
- copy: _copy,
compare: _compare,
compareOffset,
createFromString,
@@ -69,6 +68,7 @@ const {
ERR_INVALID_ARG_VALUE,
ERR_INVALID_BUFFER_SIZE,
ERR_INVALID_OPT_VALUE,
+ ERR_OUT_OF_RANGE,
ERR_UNKNOWN_ENCODING
},
hideStackFrames
@@ -157,6 +157,74 @@ function showFlaggedDeprecation() {
bufferWarningAlreadyEmitted = true;
}
+function toInteger(n, defaultVal) {
+ n = +n;
+ if (!Number.isNaN(n) &&
+ n >= Number.MIN_SAFE_INTEGER &&
+ n <= Number.MAX_SAFE_INTEGER) {
+ return ((n % 1) === 0 ? n : Math.floor(n));
+ }
+ return defaultVal;
+}
+
+function _copy(source, target, targetStart, sourceStart, sourceEnd) {
+ if (!isUint8Array(source))
+ throw new ERR_INVALID_ARG_TYPE('source', ['Buffer', 'Uint8Array'], source);
+ if (!isUint8Array(target))
+ throw new ERR_INVALID_ARG_TYPE('target', ['Buffer', 'Uint8Array'], target);
+
+ if (targetStart === undefined) {
+ targetStart = 0;
+ } else {
+ targetStart = toInteger(targetStart, 0);
+ if (targetStart < 0)
+ throw new ERR_OUT_OF_RANGE('targetStart', '>= 0', targetStart);
+ }
+
+ if (sourceStart === undefined) {
+ sourceStart = 0;
+ } else {
+ sourceStart = toInteger(sourceStart, 0);
+ if (sourceStart < 0)
+ throw new ERR_OUT_OF_RANGE('sourceStart', '>= 0', sourceStart);
+ }
+
+ if (sourceEnd === undefined) {
+ sourceEnd = source.length;
+ } else {
+ sourceEnd = toInteger(sourceEnd, 0);
+ if (sourceEnd < 0)
+ throw new ERR_OUT_OF_RANGE('sourceEnd', '>= 0', sourceEnd);
+ }
+
+ if (targetStart >= target.length || sourceStart >= sourceEnd)
+ return 0;
+
+ if (sourceStart > source.length) {
+ throw new ERR_OUT_OF_RANGE('sourceStart',
+ `<= ${source.length}`,
+ sourceStart);
+ }
+
+ if (sourceEnd - sourceStart > target.length - targetStart)
+ sourceEnd = sourceStart + target.length - targetStart;
+
+ let nb = sourceEnd - sourceStart;
+ const targetLen = target.length - targetStart;
+ const sourceLen = source.length - sourceStart;
+ if (nb > targetLen)
+ nb = targetLen;
+ if (nb > sourceLen)
+ nb = sourceLen;
+
+ if (sourceStart !== 0 || sourceEnd !== source.length)
+ source = new Uint8Array(source.buffer, source.byteOffset + sourceStart, nb);
+
+ target.set(source, targetStart);
+
+ return nb;
+}
+
/**
* The Buffer() constructor is deprecated in documentation and should not be
* used moving forward. Rather, developers should use one of the three new
diff --git a/test/parallel/test-buffer-alloc.js b/test/parallel/test-buffer-alloc.js
index 75c2cae2b0..de3e7fa523 100644
--- a/test/parallel/test-buffer-alloc.js
+++ b/test/parallel/test-buffer-alloc.js
@@ -967,7 +967,8 @@ common.expectsError(
{
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
- message: 'argument must be a buffer'
+ message: 'The "target" argument must be one of type Buffer or Uint8Array.' +
+ ' Received type undefined'
});
assert.throws(() => Buffer.from(), {
diff --git a/test/parallel/test-buffer-copy.js b/test/parallel/test-buffer-copy.js
index 9810c9824b..f668c26165 100644
--- a/test/parallel/test-buffer-copy.js
+++ b/test/parallel/test-buffer-copy.js
@@ -6,12 +6,6 @@ const assert = require('assert');
const b = Buffer.allocUnsafe(1024);
const c = Buffer.allocUnsafe(512);
-const errorProperty = {
- code: 'ERR_OUT_OF_RANGE',
- type: RangeError,
- message: 'Index out of range'
-};
-
let cntr = 0;
{
@@ -116,7 +110,13 @@ b.copy(c, 0, 100, 10);
// Copy throws at negative sourceStart
common.expectsError(
() => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), 0, -1),
- errorProperty);
+ {
+ code: 'ERR_OUT_OF_RANGE',
+ type: RangeError,
+ message: 'The value of "sourceStart" is out of range. ' +
+ 'It must be >= 0. Received -1'
+ }
+);
{
// Check sourceEnd resets to targetEnd if former is greater than the latter
@@ -130,7 +130,14 @@ common.expectsError(
// Throw with negative sourceEnd
common.expectsError(
- () => b.copy(c, 0, -1), errorProperty);
+ () => b.copy(c, 0, 0, -1),
+ {
+ code: 'ERR_OUT_OF_RANGE',
+ type: RangeError,
+ message: 'The value of "sourceEnd" is out of range. ' +
+ 'It must be >= 0. Received -1'
+ }
+);
// When sourceStart is greater than sourceEnd, zero copied
assert.strictEqual(b.copy(c, 0, 100, 10), 0);