diff --git a/lib/buffer.js b/lib/buffer.js index cc213f12dacf..f46a25fc2c5a 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -616,66 +616,51 @@ Buffer.concat = function concat(list, length) { if (list.length === 0) return new FastBuffer(); - if (length === undefined) { + const autoLength = length === undefined; + if (autoLength) { length = 0; - for (let i = 0; i < list.length; i++) { - const buf = list[i]; - if (!isUint8Array(buf)) { - // TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE. - // Instead, find the proper error code for this. - throw new ERR_INVALID_ARG_TYPE( - `list[${i}]`, ['Buffer', 'Uint8Array'], buf); - } - length += TypedArrayPrototypeGetByteLength(buf); - } - - const buffer = allocate(length); - let pos = 0; - for (let i = 0; i < list.length; i++) { - const buf = list[i]; - const bufLength = TypedArrayPrototypeGetByteLength(buf); - TypedArrayPrototypeSet(buffer, buf, pos); - pos += bufLength; - } - - if (pos < length) { - TypedArrayPrototypeFill(buffer, 0, pos, length); - } - return buffer; + } else { + validateOffset(length, 'length'); } - validateOffset(length, 'length'); - for (let i = 0; i < list.length; i++) { - if (!isUint8Array(list[i])) { - // TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE. - // Instead, find the proper error code for this. - throw new ERR_INVALID_ARG_TYPE( - `list[${i}]`, ['Buffer', 'Uint8Array'], list[i]); + let i = 0; + let j = 0; + let pos = 0; + const postPositions = new Array(list.length); + try { + for (; i < list.length; i++) { + pos += TypedArrayPrototypeGetByteLength(list[i]); + postPositions[i] = pos; + j += pos <= length; } + } catch { + // TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE. + // Instead, find the proper error code for this. + throw new ERR_INVALID_ARG_TYPE( + `list[${i}]`, ['Buffer', 'Uint8Array'], list[i]); + } + if (autoLength) { + length = pos; + j = list.length; } const buffer = allocate(length); - let pos = 0; - for (let i = 0; i < list.length; i++) { - const buf = list[i]; - const bufLength = TypedArrayPrototypeGetByteLength(buf); - if (pos + bufLength > length) { - TypedArrayPrototypeSet(buffer, - TypedArrayPrototypeSubarray(buf, 0, length - pos), - pos); - pos = length; - break; - } - TypedArrayPrototypeSet(buffer, buf, pos); - pos += bufLength; + // Copy from every input that fits completely. + for (pos = i = 0; i < j; i++) { + TypedArrayPrototypeSet(buffer, list[i], pos); + pos = postPositions[i]; } - // Note: `length` is always equal to `buffer.length` at this point if (pos < length) { - // Zero-fill the remaining bytes if the specified `length` was more than - // the actual total length, i.e. if we have some remaining allocated bytes - // there were not initialized. - TypedArrayPrototypeFill(buffer, 0, pos, length); + // Populate the remaining bytes, either by partially consuming the next + // input or by zero-filling. + if (j < list.length) { + TypedArrayPrototypeSet(buffer, + TypedArrayPrototypeSubarray(list[j], 0, length - pos), + pos); + } else { + TypedArrayPrototypeFill(buffer, 0, pos, length); + } } return buffer;