aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alex Lam S.L <alexlamsl@gmail.com> 2023-03-08 08:29:29 +0200
committerGravatar GitHub <noreply@github.com> 2023-03-07 22:29:29 -0800
commit28346e4a390036270e393192550175a01d0e7f41 (patch)
tree123e509a186d58a99266fdad81539114a44d687b
parent95b59ea0ef637abde76dad4a100cae6c496c1470 (diff)
downloadbun-28346e4a390036270e393192550175a01d0e7f41.tar.gz
bun-28346e4a390036270e393192550175a01d0e7f41.tar.zst
bun-28346e4a390036270e393192550175a01d0e7f41.zip
improve `Buffer` compatibility with Node.js (#2341)
* improve `Buffer` compatibility with Node.js * use `memmove()` allow `encoding` to be `undefined`
-rw-r--r--src/baby_list.zig2
-rw-r--r--src/base64/base64.zig92
-rw-r--r--src/bun.js/bindings/Buffer.h2
-rw-r--r--src/bun.js/bindings/JSBuffer.cpp574
-rw-r--r--src/bun.js/bindings/JSBufferEncodingType.cpp5
-rw-r--r--src/bun.js/bindings/headers-handwritten.h4
-rw-r--r--src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp345
-rw-r--r--src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h81
-rw-r--r--src/bun.js/builtins/js/JSBufferPrototype.js272
-rw-r--r--src/bun.js/node/buffer.zig114
-rw-r--r--src/bun.js/webcore/base64.zig445
-rw-r--r--src/bun.js/webcore/body.zig1
-rw-r--r--src/bun.js/webcore/encoding.zig154
-rw-r--r--src/bun.js/webcore/streams.zig2
-rw-r--r--src/http/websocket_http_client.zig2
-rw-r--r--src/napi/napi.zig14
-rw-r--r--src/string_immutable.zig44
-rw-r--r--src/string_mutable.zig2
-rw-r--r--test/js/node/buffer.test.js2132
19 files changed, 2115 insertions, 2172 deletions
diff --git a/src/baby_list.zig b/src/baby_list.zig
index 0df33b2dc..2ebb383e6 100644
--- a/src/baby_list.zig
+++ b/src/baby_list.zig
@@ -177,7 +177,7 @@ pub fn BabyList(comptime Type: type) type {
const orig_len = list_.items.len;
var slice_ = list_.items.ptr[orig_len..list_.capacity];
- const result = strings.copyUTF16IntoUTF8WithBuffer(slice_, []const u16, remain, trimmed, out_len);
+ const result = strings.copyUTF16IntoUTF8WithBuffer(slice_, []const u16, remain, trimmed, out_len, true);
remain = remain[result.read..];
list_.items.len += @as(usize, result.written);
if (result.read == 0 or result.written == 0) break;
diff --git a/src/base64/base64.zig b/src/base64/base64.zig
index daf5b228e..0cd16fb8c 100644
--- a/src/base64/base64.zig
+++ b/src/base64/base64.zig
@@ -5,34 +5,28 @@ pub const DecodeResult = struct {
fail: bool = false,
};
-pub fn decode(destination: []u8, source: []const u8) DecodeResult {
- var wrote: usize = 0;
- const result = zig_base64.standard.decoderWithIgnore(&[_]u8{
- ' ',
- '\n',
- '\r',
- '\t',
+const mixed_decoder = brk: {
+ var decoder = zig_base64.standard.decoderWithIgnore("\xff \t\r\n" ++ [_]u8{
std.ascii.control_code.vt,
- }).decode(destination, source, &wrote) catch {
- return .{
- .written = wrote,
- .fail = true,
- };
- };
+ std.ascii.control_code.ff,
+ });
- return .{ .written = result, .fail = false };
-}
+ for (zig_base64.url_safe_alphabet_chars[62..], 62..) |c, i| {
+ decoder.decoder.char_to_index[c] = @intCast(u8, i);
+ }
-pub fn decodeURLSafe(destination: []u8, source: []const u8) DecodeResult {
+ break :brk decoder;
+};
+
+pub fn decode(destination: []u8, source: []const u8) DecodeResult {
var wrote: usize = 0;
- const result = urlsafe.decode(destination, source, &wrote) catch {
+ mixed_decoder.decode(destination, source, &wrote) catch {
return .{
.written = wrote,
.fail = true,
};
};
-
- return .{ .written = result, .fail = false };
+ return .{ .written = wrote, .fail = false };
}
pub fn encode(destination: []u8, source: []const u8) usize {
@@ -58,14 +52,6 @@ pub fn encodeLen(source: anytype) usize {
return zig_base64.standard.Encoder.calcSize(source.len);
}
-pub const urlsafe = zig_base64.Base64DecoderWithIgnore.init(
- zig_base64.url_safe_alphabet_chars,
- null,
- "= \t\r\n" ++ [_]u8{ std.ascii.control_code.vt, std.ascii.control_code.ff },
-);
-
-pub const urlsafeEncoder = zig_base64.url_safe_no_pad.Encoder;
-
// This is just std.base64 copy-pasted
// with support for returning how many bytes were decoded
const zig_base64 = struct {
@@ -118,7 +104,7 @@ const zig_base64 = struct {
pub const url_safe_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*;
fn urlSafeBase64DecoderWithIgnore(ignore: []const u8) Base64DecoderWithIgnore {
- return Base64DecoderWithIgnore.init(url_safe_alphabet_chars, null, ignore);
+ return Base64DecoderWithIgnore.init(url_safe_alphabet_chars, '=', ignore);
}
/// URL-safe Base64 codecs, with padding
@@ -316,7 +302,7 @@ const zig_base64 = struct {
/// Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding
/// `InvalidPadding` is returned if the input length is not valid.
- pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) Error!usize {
+ pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) usize {
var result = source_len / 4 * 3;
if (decoder_with_ignore.decoder.pad_char == null) {
const leftover = source_len % 4;
@@ -329,7 +315,7 @@ const zig_base64 = struct {
/// Invalid padding results in error.InvalidPadding.
/// Decoding more data than can fit in dest results in error.NoSpaceLeft. See also ::calcSizeUpperBound.
/// Returns the number of bytes written to dest.
- pub fn decode(decoder_with_ignore: *const Base64DecoderWithIgnore, dest: []u8, source: []const u8, wrote: *usize) Error!usize {
+ pub fn decode(decoder_with_ignore: *const Base64DecoderWithIgnore, dest: []u8, source: []const u8, wrote: *usize) Error!void {
const decoder = &decoder_with_ignore.decoder;
var acc: u12 = 0;
var acc_len: u4 = 0;
@@ -337,16 +323,21 @@ const zig_base64 = struct {
var leftover_idx: ?usize = null;
defer {
- wrote.* = leftover_idx orelse dest_idx;
+ wrote.* = dest_idx;
}
for (source, 0..) |c, src_idx| {
if (decoder_with_ignore.char_is_ignored[c]) continue;
const d = decoder.char_to_index[c];
if (d == Base64Decoder.invalid_char) {
- if (decoder.pad_char == null or c != decoder.pad_char.?) return error.InvalidCharacter;
- leftover_idx = src_idx;
- break;
+ if (decoder.pad_char) |pad_char| {
+ if (c == pad_char) {
+ leftover_idx = src_idx;
+ break;
+ }
+ }
+ if (decoder_with_ignore.char_is_ignored[Base64Decoder.invalid_char]) continue;
+ return error.InvalidCharacter;
}
acc = (acc << 6) + d;
acc_len += 6;
@@ -357,27 +348,26 @@ const zig_base64 = struct {
dest_idx += 1;
}
}
- if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) {
- return error.InvalidPadding;
- }
- const padding_len = acc_len / 2;
- if (leftover_idx == null) {
- if (decoder.pad_char != null and padding_len != 0) return error.InvalidPadding;
- return dest_idx;
- }
- var leftover = source[leftover_idx.?..];
+ if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) return error.InvalidPadding;
+
if (decoder.pad_char) |pad_char| {
- var padding_chars: usize = 0;
- for (leftover) |c| {
- if (decoder_with_ignore.char_is_ignored[c]) continue;
- if (c != pad_char) {
- return if (c == Base64Decoder.invalid_char) error.InvalidCharacter else error.InvalidPadding;
+ const padding_len = acc_len / 2;
+
+ if (leftover_idx) |idx| {
+ var leftover = source[idx..];
+ var padding_chars: usize = 0;
+ for (leftover) |c| {
+ if (decoder_with_ignore.char_is_ignored[c]) continue;
+ if (c != pad_char) {
+ return if (c == Base64Decoder.invalid_char) error.InvalidCharacter else error.InvalidPadding;
+ }
+ padding_chars += 1;
}
- padding_chars += 1;
+ if (padding_chars != padding_len) return error.InvalidPadding;
+ } else if (padding_len > 0) {
+ return error.InvalidPadding;
}
- if (padding_chars != padding_len) return error.InvalidPadding;
}
- return dest_idx;
}
};
diff --git a/src/bun.js/bindings/Buffer.h b/src/bun.js/bindings/Buffer.h
index fecc627a1..4f1583513 100644
--- a/src/bun.js/bindings/Buffer.h
+++ b/src/bun.js/bindings/Buffer.h
@@ -16,7 +16,7 @@ extern "C" JSC::EncodedJSValue JSBuffer__bufferFromLength(JSC::JSGlobalObject* l
extern "C" JSC::EncodedJSValue JSBuffer__bufferFromPointerAndLengthAndDeinit(JSC::JSGlobalObject* lexicalGlobalObject, char* ptr, size_t length, void* ctx, JSTypedArrayBytesDeallocator bytesDeallocator);
extern "C" JSC::EncodedJSValue Bun__encoding__toString(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject, Encoding encoding);
extern "C" JSC::EncodedJSValue Bun__encoding__toStringUTF8(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject);
-extern "C" void Bun__Buffer_fill(ZigString*, void*, size_t, WebCore::BufferEncodingType);
+extern "C" bool Bun__Buffer_fill(ZigString*, void*, size_t, WebCore::BufferEncodingType);
namespace WebCore {
diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp
index 2ce07617a..9b3854b95 100644
--- a/src/bun.js/bindings/JSBuffer.cpp
+++ b/src/bun.js/bindings/JSBuffer.cpp
@@ -133,6 +133,35 @@ static int normalizeCompareVal(int val, size_t a_length, size_t b_length)
return val;
}
+static inline uint32_t parseIndex(JSC::JSGlobalObject* lexicalGlobalObject, JSC::ThrowScope& scope, JSValue arg)
+{
+ if (auto num = arg.tryGetAsUint32Index())
+ return num.value();
+
+ if (arg.isNumber())
+ throwRangeError(lexicalGlobalObject, scope, "Invalid array length"_s);
+ else
+ throwTypeError(lexicalGlobalObject, scope, "Expected number"_s);
+
+ return 0;
+}
+
+static inline WebCore::BufferEncodingType parseEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSC::ThrowScope& scope, JSValue arg)
+{
+ if (UNLIKELY(!arg.isString())) {
+ throwTypeError(lexicalGlobalObject, scope, "Expected string"_s);
+ return WebCore::BufferEncodingType::utf8;
+ }
+
+ std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg);
+ if (UNLIKELY(!encoded)) {
+ throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
+ return WebCore::BufferEncodingType::utf8;
+ }
+
+ return encoded.value();
+}
+
namespace WebCore {
using namespace JSC;
@@ -190,8 +219,11 @@ using namespace JSC;
static inline EncodedJSValue writeToBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSArrayBufferView* castedThis, JSString* str, uint32_t offset, uint32_t length, BufferEncodingType encoding)
{
+ if (UNLIKELY(str->length() == 0))
+ return JSC::JSValue::encode(JSC::jsNumber(0));
+
auto view = str->tryGetValue(lexicalGlobalObject);
- int64_t written = 0;
+ size_t written = 0;
switch (encoding) {
case WebCore::BufferEncodingType::utf8:
@@ -358,9 +390,6 @@ static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGl
RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
- if (str->length() == 0)
- return constructBufferEmpty(lexicalGlobalObject);
-
if (arg1 && arg1.isString()) {
std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg1);
if (!encoded) {
@@ -371,6 +400,9 @@ static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGl
encoding = encoded.value();
}
+ if (str->length() == 0)
+ return constructBufferEmpty(lexicalGlobalObject);
+
JSC::EncodedJSValue result = constructFromEncoding(lexicalGlobalObject, str, encoding);
RELEASE_AND_RETURN(scope, result);
@@ -380,7 +412,12 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG
{
VM& vm = lexicalGlobalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- auto length = callFrame->uncheckedArgument(0).toInt32(lexicalGlobalObject);
+ auto lengthArg = callFrame->uncheckedArgument(0);
+ if (UNLIKELY(!lengthArg.isNumber())) {
+ throwTypeError(lexicalGlobalObject, scope, "Expected number"_s);
+ return JSValue::encode(jsUndefined());
+ }
+ auto length = lengthArg.toInt32(lexicalGlobalObject);
if (length < 0) {
throwRangeError(lexicalGlobalObject, scope, "Invalid array length"_s);
return JSValue::encode(jsUndefined());
@@ -392,10 +429,56 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG
// fill argument
if (UNLIKELY(callFrame->argumentCount() > 1)) {
auto* uint8Array = JSC::JSUint8Array::createUninitialized(lexicalGlobalObject, subclassStructure, length);
-
auto value = callFrame->argument(1);
- if (!value.isString()) {
+ if (value.isString()) {
+ size_t length = uint8Array->byteLength();
+ size_t start = 0;
+ size_t end = length;
+ WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
+ if (callFrame->argumentCount() > 2) {
+ EnsureStillAliveScope arg2 = callFrame->uncheckedArgument(2);
+ if (!arg2.value().isUndefined()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, arg2.value());
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
+ }
+ }
+ auto startPtr = uint8Array->typedVector() + start;
+ auto str_ = value.toWTFString(lexicalGlobalObject);
+ ZigString str = Zig::toZigString(str_);
+
+ if (UNLIKELY(!Bun__Buffer_fill(&str, startPtr, end - start, encoding))) {
+ throwTypeError(lexicalGlobalObject, scope, "Failed to decode value"_s);
+ return JSC::JSValue::encode(jsUndefined());
+ }
+ } else if (auto* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value)) {
+ if (UNLIKELY(view->isDetached())) {
+ throwVMTypeError(lexicalGlobalObject, scope, "Uint8Array is detached"_s);
+ return JSValue::encode(jsUndefined());
+ }
+
+ size_t length = view->byteLength();
+ if (UNLIKELY(length == 0)) {
+ throwTypeError(lexicalGlobalObject, scope, "Buffer cannot be empty"_s);
+ return JSC::JSValue::encode(jsUndefined());
+ }
+
+ auto* start = uint8Array->typedVector();
+ auto* head = start;
+ size_t remain = uint8Array->byteLength();
+ memmove(head, view->vector(), length);
+ remain -= length;
+ head += length;
+ while (remain >= length) {
+ memcpy(head, start, length);
+ remain -= length;
+ head += length;
+ length <<= 1;
+ }
+ if (remain > 0) {
+ memcpy(head, start, remain);
+ }
+ } else {
auto value_ = value.toInt32(lexicalGlobalObject) & 0xFF;
auto value_uint8 = static_cast<uint8_t>(value_);
@@ -408,33 +491,9 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG
auto startPtr = uint8Array->typedVector() + start;
auto endPtr = uint8Array->typedVector() + end;
memset(startPtr, value_uint8, endPtr - startPtr);
- RELEASE_AND_RETURN(scope, JSC::JSValue::encode(uint8Array));
}
- {
- size_t length = uint8Array->byteLength();
- size_t start = 0;
- size_t end = length;
- WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
- if (callFrame->argumentCount() > 2) {
- EnsureStillAliveScope arg2 = callFrame->uncheckedArgument(2);
- if (arg2.value().isString()) {
- std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg2.value());
- if (!encoded) {
- throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
- return JSC::JSValue::encode(jsUndefined());
- }
-
- encoding = encoded.value();
- }
- }
- auto startPtr = uint8Array->typedVector() + start;
- auto str_ = value.toWTFString(lexicalGlobalObject);
- ZigString str = Zig::toZigString(str_);
-
- Bun__Buffer_fill(&str, startPtr, end - start, encoding);
- RELEASE_AND_RETURN(scope, JSC::JSValue::encode(uint8Array));
- }
+ RELEASE_AND_RETURN(scope, JSC::JSValue::encode(uint8Array));
} else {
auto* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, length);
if (UNLIKELY(!uint8Array)) {
@@ -585,6 +644,10 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_compareBody(JSC::J
throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Buffer (first argument)"_s);
return JSValue::encode(jsUndefined());
}
+ if (UNLIKELY(castedThis->isDetached())) {
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Uint8Array (first argument) is detached"_s);
+ return JSValue::encode(jsUndefined());
+ }
auto buffer = callFrame->uncheckedArgument(1);
JSC::JSArrayBufferView* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(buffer);
@@ -592,13 +655,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_compareBody(JSC::J
throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Buffer (2nd argument)"_s);
return JSValue::encode(jsUndefined());
}
-
if (UNLIKELY(view->isDetached())) {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Uint8Array (first argument) is detached"_s);
- return JSValue::encode(jsUndefined());
- }
-
- if (UNLIKELY(castedThis->isDetached())) {
throwVMTypeError(lexicalGlobalObject, throwScope, "Uint8Array (second argument) is detached"_s);
return JSValue::encode(jsUndefined());
}
@@ -611,43 +668,27 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_compareBody(JSC::J
size_t sourceEndInit = castedThis->byteLength();
size_t sourceEnd = sourceEndInit;
- if (callFrame->argumentCount() > 2) {
- if (auto targetEnd_ = callFrame->uncheckedArgument(2).tryGetAsUint32Index()) {
- targetStart = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
-
- if (callFrame->argumentCount() > 3) {
- auto targetEndArgument = callFrame->uncheckedArgument(3);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- targetEnd = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
-
- if (callFrame->argumentCount() > 4) {
- auto targetEndArgument = callFrame->uncheckedArgument(4);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- sourceStart = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
-
- if (callFrame->argumentCount() > 5) {
- auto targetEndArgument = callFrame->uncheckedArgument(5);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- sourceEnd = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
+ switch (callFrame->argumentCount()) {
+ default:
+ sourceEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(5));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 5:
+ sourceStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(4));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 4:
+ targetEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 3:
+ targetStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ break;
+ case 2:
+ case 1:
+ case 0:
+ break;
}
targetStart = std::min(targetStart, std::min(targetEnd, targetEndInit));
@@ -822,43 +863,26 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_compareBody(JSC::JSG
size_t sourceEndInit = castedThis->byteLength();
size_t sourceEnd = sourceEndInit;
- if (callFrame->argumentCount() > 1) {
- if (auto targetEnd_ = callFrame->uncheckedArgument(1).tryGetAsUint32Index()) {
- targetStart = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
-
- if (callFrame->argumentCount() > 2) {
- auto targetEndArgument = callFrame->uncheckedArgument(2);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- targetEnd = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
-
- if (callFrame->argumentCount() > 3) {
- auto targetEndArgument = callFrame->uncheckedArgument(3);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- sourceStart = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
-
- if (callFrame->argumentCount() > 4) {
- auto targetEndArgument = callFrame->uncheckedArgument(4);
- if (auto targetEnd_ = targetEndArgument.tryGetAsUint32Index()) {
- sourceEnd = targetEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
+ switch (callFrame->argumentCount()) {
+ default:
+ sourceEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(4));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 4:
+ sourceStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 3:
+ targetEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 2:
+ targetStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ break;
+ case 1:
+ case 0:
+ break;
}
targetStart = std::min(targetStart, std::min(targetEnd, targetEndInit));
@@ -905,31 +929,22 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_copyBody(JSC::JSGlob
size_t sourceEndInit = castedThis->byteLength();
size_t sourceEnd = sourceEndInit;
- if (callFrame->argumentCount() > 1) {
- if (auto targetStart_ = callFrame->uncheckedArgument(1).tryGetAsUint32Index()) {
- targetStart = targetStart_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
-
- if (callFrame->argumentCount() > 2) {
- if (auto sourceStart_ = callFrame->uncheckedArgument(2).tryGetAsUint32Index()) {
- sourceStart = sourceStart_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
-
- if (callFrame->argumentCount() > 3) {
- if (auto sourceEnd_ = callFrame->uncheckedArgument(3).tryGetAsUint32Index()) {
- sourceEnd = sourceEnd_.value();
- } else {
- throwVMTypeError(lexicalGlobalObject, throwScope, "Expected number"_s);
- return JSValue::encode(jsUndefined());
- }
- }
+ switch (callFrame->argumentCount()) {
+ default:
+ sourceEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 3:
+ sourceStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ FALLTHROUGH;
+ case 2:
+ targetStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined()));
+ break;
+ case 1:
+ case 0:
+ break;
}
targetStart = std::min(targetStart, targetEnd);
@@ -993,120 +1008,111 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob
}
auto value = callFrame->uncheckedArgument(0);
+ const size_t limit = castedThis->byteLength();
+ size_t start = 0;
+ size_t end = limit;
+ WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
+ JSValue encodingValue = jsUndefined();
+ JSValue offsetValue = jsUndefined();
+ JSValue lengthValue = jsUndefined();
- if (!value.isString()) {
- auto value_ = value.toInt32(lexicalGlobalObject) & 0xFF;
+ switch (callFrame->argumentCount()) {
+ case 4:
+ encodingValue = callFrame->uncheckedArgument(3);
+ FALLTHROUGH;
+ case 3:
+ lengthValue = callFrame->uncheckedArgument(2);
+ FALLTHROUGH;
+ case 2:
+ offsetValue = callFrame->uncheckedArgument(1);
+ FALLTHROUGH;
+ default:
+ break;
+ }
- auto value_uint8 = static_cast<uint8_t>(value_);
+ if (offsetValue.isUndefined() || offsetValue.isString()) {
+ encodingValue = offsetValue;
+ offsetValue = jsUndefined();
+ } else if (lengthValue.isString()) {
+ encodingValue = lengthValue;
+ lengthValue = jsUndefined();
+ }
+
+ if (!encodingValue.isUndefined()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, encodingValue);
RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
+ }
- auto length = castedThis->byteLength();
- auto start = 0;
- auto end = length;
- if (callFrame->argumentCount() > 1) {
- if (auto start_ = callFrame->uncheckedArgument(1).tryGetAsUint32Index()) {
- start = start_.value();
- } else {
- return throwVMError(lexicalGlobalObject, scope, createRangeError(lexicalGlobalObject, "start out of range"_s));
- }
- if (callFrame->argumentCount() > 2) {
- if (auto end_ = callFrame->uncheckedArgument(2).tryGetAsUint32Index()) {
- end = end_.value();
- } else {
- return throwVMError(lexicalGlobalObject, scope, createRangeError(lexicalGlobalObject, "end out of range"_s));
- }
- }
- }
- if (start > end) {
- return throwVMError(lexicalGlobalObject, scope, createRangeError(lexicalGlobalObject, "start out of range"_s));
- }
- if (end > length) {
- return throwVMError(lexicalGlobalObject, scope, createRangeError(lexicalGlobalObject, "end out of range"_s));
- }
- auto startPtr = castedThis->typedVector() + start;
- auto endPtr = castedThis->typedVector() + end;
- memset(startPtr, value_uint8, endPtr - startPtr);
- return JSValue::encode(castedThis);
+ if (!offsetValue.isUndefined()) {
+ start = parseIndex(lexicalGlobalObject, scope, offsetValue);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
}
- {
- EnsureStillAliveScope value_ = callFrame->argument(0);
-
- size_t length = castedThis->byteLength();
- size_t start = 0;
- size_t end = length;
- WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
-
- JSValue encodingValue = jsUndefined();
- JSValue offsetValue = jsUndefined();
- JSValue lengthValue = jsUndefined();
-
- switch (callFrame->argumentCount()) {
- case 4:
- encodingValue = callFrame->uncheckedArgument(3);
- FALLTHROUGH;
- case 3:
- lengthValue = callFrame->uncheckedArgument(2);
- FALLTHROUGH;
- case 2:
- offsetValue = callFrame->uncheckedArgument(1);
- FALLTHROUGH;
- default:
- break;
- }
+ if (!lengthValue.isUndefined()) {
+ end = parseIndex(lexicalGlobalObject, scope, lengthValue);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
+ }
- if (offsetValue.isUndefined() || offsetValue.isString()) {
- encodingValue = offsetValue;
- offsetValue = jsUndefined();
- } else if (lengthValue.isString()) {
- encodingValue = lengthValue;
- lengthValue = jsUndefined();
- }
+ if (start >= end) {
+ RELEASE_AND_RETURN(scope, JSValue::encode(castedThis));
+ }
- if (encodingValue.isString()) {
- std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encodingValue);
- if (!encoded) {
- throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
- return JSC::JSValue::encode(jsUndefined());
- }
+ if (UNLIKELY(end > limit)) {
+ throwRangeError(lexicalGlobalObject, scope, "end out of range"_s);
+ return JSC::JSValue::encode(jsUndefined());
+ }
- encoding = encoded.value();
- }
+ if (value.isString()) {
+ auto startPtr = castedThis->typedVector() + start;
+ auto str_ = value.toWTFString(lexicalGlobalObject);
+ ZigString str = Zig::toZigString(str_);
- if (!offsetValue.isUndefined()) {
- if (auto offset = offsetValue.tryGetAsUint32Index()) {
- start = offset.value();
- } else {
- throwVMError(lexicalGlobalObject, scope, createRangeError(lexicalGlobalObject, "start out of range"_s));
- return JSC::JSValue::encode(jsUndefined());
- }
+ if (str.len == 0) {
+ memset(startPtr, 0, end - start);
+ } else if (UNLIKELY(!Bun__Buffer_fill(&str, startPtr, end - start, encoding))) {
+ throwTypeError(lexicalGlobalObject, scope, "Failed to decode value"_s);
+ return JSC::JSValue::encode(jsUndefined());
}
+ } else if (auto* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value)) {
+ auto* startPtr = castedThis->typedVector() + start;
+ auto* head = startPtr;
+ size_t remain = end - start;
- if (!lengthValue.isUndefined()) {
- if (auto length = lengthValue.tryGetAsUint32Index()) {
- end = std::min(static_cast<size_t>(length.value()), end);
- } else {
- throwVMError(lexicalGlobalObject, scope, createRangeError(lexicalGlobalObject, "end out of range"_s));
- return JSC::JSValue::encode(jsUndefined());
- }
+ if (UNLIKELY(view->isDetached())) {
+ throwVMTypeError(lexicalGlobalObject, scope, "Uint8Array is detached"_s);
+ return JSValue::encode(jsUndefined());
}
- if (start >= end) {
- return JSValue::encode(castedThis);
+ size_t length = view->byteLength();
+ if (UNLIKELY(length == 0)) {
+ throwTypeError(lexicalGlobalObject, scope, "Buffer cannot be empty"_s);
+ return JSC::JSValue::encode(jsUndefined());
}
- auto startPtr = castedThis->typedVector() + start;
- auto str_ = value.toWTFString(lexicalGlobalObject);
- ZigString str = Zig::toZigString(str_);
-
- if (str.len > 0) {
- Bun__Buffer_fill(&str, startPtr, end - start, encoding);
- } else {
- memset(startPtr, 0, end - start);
+ memmove(head, view->vector(), length);
+ remain -= length;
+ head += length;
+ while (remain >= length) {
+ memcpy(head, startPtr, length);
+ remain -= length;
+ head += length;
+ length <<= 1;
+ }
+ if (remain > 0) {
+ memcpy(head, startPtr, remain);
}
+ } else {
+ auto value_ = value.toInt32(lexicalGlobalObject) & 0xFF;
- RELEASE_AND_RETURN(scope, JSValue::encode(castedThis));
+ auto value_uint8 = static_cast<uint8_t>(value_);
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
+
+ auto startPtr = castedThis->typedVector() + start;
+ auto endPtr = castedThis->typedVector() + end;
+ memset(startPtr, value_uint8, endPtr - startPtr);
}
+
+ RELEASE_AND_RETURN(scope, JSValue::encode(castedThis));
}
static int64_t indexOf(const uint8_t* thisPtr, int64_t thisLength, const uint8_t* valuePtr, int64_t valueLength, int64_t byteOffset)
@@ -1150,42 +1156,42 @@ static int64_t indexOf(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame*
int64_t byteOffset = last ? length - 1 : 0;
if (callFrame->argumentCount() > 1) {
- auto byteOffset_ = callFrame->uncheckedArgument(1).toNumber(lexicalGlobalObject);
- RETURN_IF_EXCEPTION(scope, -1);
-
- if (std::isnan(byteOffset_) || std::isinf(byteOffset_)) {
- byteOffset = last ? length - 1 : 0;
- } else if (byteOffset_ < 0) {
- byteOffset = length + static_cast<int64_t>(byteOffset_);
+ EnsureStillAliveScope arg1 = callFrame->uncheckedArgument(1);
+ if (arg1.value().isString()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, arg1.value());
+ RETURN_IF_EXCEPTION(scope, -1);
} else {
- byteOffset = static_cast<int64_t>(byteOffset_);
- }
+ auto byteOffset_ = arg1.value().toNumber(lexicalGlobalObject);
+ RETURN_IF_EXCEPTION(scope, -1);
- if (last) {
- if (byteOffset < 0) {
- return -1;
- } else if (byteOffset > length - 1) {
- byteOffset = length - 1;
- }
- } else {
- if (byteOffset <= 0) {
- byteOffset = 0;
- } else if (byteOffset > length - 1) {
- return -1;
+ if (std::isnan(byteOffset_) || std::isinf(byteOffset_)) {
+ byteOffset = last ? length - 1 : 0;
+ } else if (byteOffset_ < 0) {
+ byteOffset = length + static_cast<int64_t>(byteOffset_);
+ } else {
+ byteOffset = static_cast<int64_t>(byteOffset_);
}
- }
- if (callFrame->argumentCount() > 2) {
- EnsureStillAliveScope encodingValue = callFrame->uncheckedArgument(2);
-
- if (encodingValue.value().isString()) {
- std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encodingValue.value());
- if (!encoded) {
- throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
- return JSC::JSValue::encode(jsUndefined());
+ if (last) {
+ if (byteOffset < 0) {
+ return -1;
+ } else if (byteOffset > length - 1) {
+ byteOffset = length - 1;
+ }
+ } else {
+ if (byteOffset <= 0) {
+ byteOffset = 0;
+ } else if (byteOffset > length - 1) {
+ return -1;
}
+ }
- encoding = encoded.value();
+ if (callFrame->argumentCount() > 2) {
+ EnsureStillAliveScope encodingValue = callFrame->uncheckedArgument(2);
+ if (!encodingValue.value().isUndefined()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, encodingValue.value());
+ RETURN_IF_EXCEPTION(scope, -1);
+ }
}
}
}
@@ -1420,6 +1426,7 @@ static inline JSC::EncodedJSValue jsBufferToString(JSC::VM& vm, JSC::JSGlobalObj
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
{
auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto scope = DECLARE_THROW_SCOPE(vm);
uint32_t offset = 0;
uint32_t length = castedThis->length();
uint32_t byteLength = length;
@@ -1436,18 +1443,10 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS
case 3:
case 1: {
EnsureStillAliveScope arg1 = callFrame->uncheckedArgument(0);
- if (arg1.value().isString()) {
- std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg1.value());
- if (!encoded) {
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
- return JSC::JSValue::encode(jsUndefined());
- }
-
- encoding = encoded.value();
+ if (!arg1.value().isUndefined()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, arg1.value());
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
}
-
if (callFrame->argumentCount() == 1)
break;
}
@@ -1456,8 +1455,6 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS
JSC::JSValue arg2 = callFrame->uncheckedArgument(1);
int32_t ioffset = arg2.toInt32(lexicalGlobalObject);
if (ioffset < 0) {
- auto scope = DECLARE_THROW_SCOPE(vm);
-
throwTypeError(lexicalGlobalObject, scope, "Offset must be a positive integer"_s);
return JSC::JSValue::encode(jsUndefined());
}
@@ -1524,9 +1521,6 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo
return JSC::JSValue::encode(jsUndefined());
}
- if (str->length() == 0)
- return JSC::JSValue::encode(JSC::jsNumber(0));
-
JSValue offsetValue = jsUndefined();
JSValue lengthValue = jsUndefined();
JSValue encodingValue = jsUndefined();
@@ -1546,14 +1540,8 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo
}
auto setEncoding = [&]() {
- if (encodingValue.isString()) {
- std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encodingValue);
- if (!encoded) {
- throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s);
- return;
- }
-
- encoding = encoded.value();
+ if (!encodingValue.isUndefined()) {
+ encoding = parseEncoding(lexicalGlobalObject, scope, encodingValue);
}
};
@@ -1570,6 +1558,11 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo
RELEASE_AND_RETURN(scope, writeToBuffer(lexicalGlobalObject, castedThis, str, offset, length, encoding));
}
+ if (UNLIKELY(!offsetValue.isNumber())) {
+ throwTypeError(lexicalGlobalObject, scope, "Invalid offset"_s);
+ return JSC::JSValue::encode(jsUndefined());
+ }
+
int32_t userOffset = offsetValue.toInt32(lexicalGlobalObject);
RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined()));
if (userOffset < 0 || userOffset > max) {
@@ -1845,11 +1838,15 @@ static const HashTableValue JSBufferPrototypeTableValues[]
{ "readInt32BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadInt32BECodeGenerator, 1 } },
{ "readInt32LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadInt32LECodeGenerator, 1 } },
{ "readInt8"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadInt8CodeGenerator, 2 } },
+ { "readIntBE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadIntBECodeGenerator, 1 } },
+ { "readIntLE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadIntLECodeGenerator, 1 } },
{ "readUInt16BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt16BECodeGenerator, 1 } },
{ "readUInt16LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt16LECodeGenerator, 1 } },
{ "readUInt32BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt32BECodeGenerator, 1 } },
{ "readUInt32LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt32LECodeGenerator, 1 } },
{ "readUInt8"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt8CodeGenerator, 1 } },
+ { "readUIntBE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUIntBECodeGenerator, 1 } },
+ { "readUIntLE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUIntLECodeGenerator, 1 } },
{ "readUint16BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt16BECodeGenerator, 1 } },
{ "readUint16LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt16LECodeGenerator, 1 } },
{ "readUint32BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadUInt32BECodeGenerator, 1 } },
@@ -1861,6 +1858,7 @@ static const HashTableValue JSBufferPrototypeTableValues[]
{ "swap32"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_swap32, 0 } },
{ "swap64"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_swap64, 0 } },
{ "toJSON"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeToJSONCodeGenerator, 1 } },
+ { "toLocaleString"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_toString, 4 } },
{ "toString"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_toString, 4 } },
{ "ucs2Slice"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeUcs2SliceCodeGenerator, 2 } },
{ "ucs2Write"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeUcs2WriteCodeGenerator, 1 } },
@@ -1886,6 +1884,8 @@ static const HashTableValue JSBufferPrototypeTableValues[]
{ "writeInt32BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteInt32BECodeGenerator, 1 } },
{ "writeInt32LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteInt32LECodeGenerator, 1 } },
{ "writeInt8"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteInt8CodeGenerator, 1 } },
+ { "writeIntBE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteIntBECodeGenerator, 1 } },
+ { "writeIntLE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteIntLECodeGenerator, 1 } },
{ "writeUInt16"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16LECodeGenerator, 1 } },
{ "writeUInt16BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16BECodeGenerator, 1 } },
{ "writeUInt16LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16LECodeGenerator, 1 } },
@@ -1893,6 +1893,8 @@ static const HashTableValue JSBufferPrototypeTableValues[]
{ "writeUInt32BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt32BECodeGenerator, 1 } },
{ "writeUInt32LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt32LECodeGenerator, 1 } },
{ "writeUInt8"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt8CodeGenerator, 1 } },
+ { "writeUIntBE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUIntBECodeGenerator, 1 } },
+ { "writeUIntLE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUIntLECodeGenerator, 1 } },
{ "writeUint16"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16LECodeGenerator, 1 } },
{ "writeUint16BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16BECodeGenerator, 1 } },
{ "writeUint16LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeWriteUInt16LECodeGenerator, 1 } },
diff --git a/src/bun.js/bindings/JSBufferEncodingType.cpp b/src/bun.js/bindings/JSBufferEncodingType.cpp
index 8d99dd4db..dde9e1be2 100644
--- a/src/bun.js/bindings/JSBufferEncodingType.cpp
+++ b/src/bun.js/bindings/JSBufferEncodingType.cpp
@@ -39,7 +39,6 @@ static const NeverDestroyed<String> values[] = {
MAKE_STATIC_STRING_IMPL("base64"),
MAKE_STATIC_STRING_IMPL("base64url"),
MAKE_STATIC_STRING_IMPL("hex"),
- MAKE_STATIC_STRING_IMPL("buffer"),
};
String convertEnumerationToString(BufferEncodingType enumerationValue)
@@ -104,8 +103,6 @@ template<> std::optional<BufferEncodingType> parseEnumeration<BufferEncodingType
case 'B': {
if (WTF::equalIgnoringASCIICase(encoding, "binary"_s))
return BufferEncodingType::latin1; // BINARY is a deprecated alias of LATIN1.
- if (WTF::equalIgnoringASCIICase(encoding, "buffer"_s))
- return BufferEncodingType::buffer;
if (WTF::equalIgnoringASCIICase(encoding, "base64"_s))
return BufferEncodingType::base64;
if (WTF::equalIgnoringASCIICase(encoding, "base64url"_s))
@@ -135,7 +132,7 @@ template<> std::optional<BufferEncodingType> parseEnumeration<BufferEncodingType
}
template<> const char* expectedEnumerationValues<BufferEncodingType>()
{
- return "\"utf8\", \"ucs2\", \"utf16le\", \"latin1\", \"ascii\", \"base64\", \"base64url\", \"hex\", \"buffer\"";
+ return "\"utf8\", \"ucs2\", \"utf16le\", \"latin1\", \"ascii\", \"base64\", \"base64url\", \"hex\"";
}
} // namespace WebCore
diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h
index 8f925e84f..d4e1e72af 100644
--- a/src/bun.js/bindings/headers-handwritten.h
+++ b/src/bun.js/bindings/headers-handwritten.h
@@ -268,8 +268,8 @@ extern "C" const char* Bun__version_sha;
extern "C" void ZigString__free_global(const unsigned char* ptr, size_t len);
-extern "C" int64_t Bun__encoding__writeLatin1(const unsigned char* ptr, size_t len, unsigned char* to, size_t other_len, Encoding encoding);
-extern "C" int64_t Bun__encoding__writeUTF16(const UChar* ptr, size_t len, unsigned char* to, size_t other_len, Encoding encoding);
+extern "C" size_t Bun__encoding__writeLatin1(const unsigned char* ptr, size_t len, unsigned char* to, size_t other_len, Encoding encoding);
+extern "C" size_t Bun__encoding__writeUTF16(const UChar* ptr, size_t len, unsigned char* to, size_t other_len, Encoding encoding);
extern "C" size_t Bun__encoding__byteLengthLatin1(const unsigned char* ptr, size_t len, Encoding encoding);
extern "C" size_t Bun__encoding__byteLengthUTF16(const UChar* ptr, size_t len, Encoding encoding);
diff --git a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp
index 8aff61064..1ce441bb6 100644
--- a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.cpp
@@ -180,6 +180,146 @@ const char* const s_jsBufferPrototypeReadUInt32BECode =
"})\n" \
;
+const JSC::ConstructAbility s_jsBufferPrototypeReadIntLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeReadIntLECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeReadIntLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeReadIntLECodeLength = 882;
+static const JSC::Intrinsic s_jsBufferPrototypeReadIntLECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeReadIntLECode =
+ "(function (offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " return view.getInt8(offset);\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " return view.getInt16(offset, true);\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " const val = view.getUint16(offset, true) + view.getUint8(offset + 2) * 2 ** 16;\n" \
+ " return val | (val & 2 ** 23) * 0x1fe;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " return view.getInt32(offset, true);\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " const last = view.getUint8(offset + 4);\n" \
+ " return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset, true);\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " const last = view.getUint16(offset + 4, true);\n" \
+ " return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset, true);\n" \
+ " }\n" \
+ " }\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeReadIntBECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeReadIntBECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeReadIntBECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeReadIntBECodeLength = 888;
+static const JSC::Intrinsic s_jsBufferPrototypeReadIntBECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeReadIntBECode =
+ "(function (offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " return view.getInt8(offset);\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " return view.getInt16(offset, false);\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " const val = view.getUint16(offset + 1, false) + view.getUint8(offset) * 2 ** 16;\n" \
+ " return val | (val & 2 ** 23) * 0x1fe;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " return view.getInt32(offset, false);\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " const last = view.getUint8(offset);\n" \
+ " return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset + 1, false);\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " const last = view.getUint16(offset, false);\n" \
+ " return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset + 2, false);\n" \
+ " }\n" \
+ " }\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeReadUIntLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeReadUIntLECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeReadUIntLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeReadUIntLECodeLength = 723;
+static const JSC::Intrinsic s_jsBufferPrototypeReadUIntLECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeReadUIntLECode =
+ "(function (offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " return view.getUint8(offset);\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " return view.getUint16(offset, true);\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " return view.getUint16(offset, true) + view.getUint8(offset + 2) * 2 ** 16;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " return view.getUint32(offset, true);\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " return view.getUint8(offset + 4) * 2 ** 32 + view.getUint32(offset, true);\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " return view.getUint16(offset + 4, true) * 2 ** 32 + view.getUint32(offset, true);\n" \
+ " }\n" \
+ " }\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeReadUIntBECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeReadUIntBECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeReadUIntBECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeReadUIntBECodeLength = 842;
+static const JSC::Intrinsic s_jsBufferPrototypeReadUIntBECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeReadUIntBECode =
+ "(function (offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " return view.getUint8(offset);\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " return view.getUint16(offset, false);\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " return view.getUint16(offset + 1, false) + view.getUint8(offset) * 2 ** 16;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " return view.getUint32(offset, false);\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " const last = view.getUint8(offset);\n" \
+ " return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset + 1, false);\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " const last = view.getUint16(offset, false);\n" \
+ " return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset + 2, false);\n" \
+ " }\n" \
+ " }\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ "})\n" \
+;
+
const JSC::ConstructAbility s_jsBufferPrototypeReadFloatLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeReadFloatLECodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_jsBufferPrototypeReadFloatLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
@@ -406,6 +546,186 @@ const char* const s_jsBufferPrototypeWriteUInt32BECode =
"})\n" \
;
+const JSC::ConstructAbility s_jsBufferPrototypeWriteIntLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeWriteIntLECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeWriteIntLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeWriteIntLECodeLength = 949;
+static const JSC::Intrinsic s_jsBufferPrototypeWriteIntLECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeWriteIntLECode =
+ "(function (value, offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " view.setInt8(offset, value);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " view.setInt16(offset, value, true);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " view.setUint16(offset, value & 0xFFFF, true);\n" \
+ " view.setInt8(offset + 2, Math.floor(value * 2 ** -16));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " view.setInt32(offset, value, true);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " view.setUint32(offset, value | 0, true);\n" \
+ " view.setInt8(offset + 4, Math.floor(value * 2 ** -32));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " view.setUint32(offset, value | 0, true);\n" \
+ " view.setInt16(offset + 4, Math.floor(value * 2 ** -32), true);\n" \
+ " break;\n" \
+ " }\n" \
+ " default: {\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ " }\n" \
+ " }\n" \
+ " return offset + byteLength;\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeWriteIntBECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeWriteIntBECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeWriteIntBECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeWriteIntBECodeLength = 955;
+static const JSC::Intrinsic s_jsBufferPrototypeWriteIntBECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeWriteIntBECode =
+ "(function (value, offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " view.setInt8(offset, value);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " view.setInt16(offset, value, false);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " view.setUint16(offset + 1, value & 0xFFFF, false);\n" \
+ " view.setInt8(offset, Math.floor(value * 2 ** -16));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " view.setInt32(offset, value, false);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " view.setUint32(offset + 1, value | 0, false);\n" \
+ " view.setInt8(offset, Math.floor(value * 2 ** -32));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " view.setUint32(offset + 2, value | 0, false);\n" \
+ " view.setInt16(offset, Math.floor(value * 2 ** -32), false);\n" \
+ " break;\n" \
+ " }\n" \
+ " default: {\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ " }\n" \
+ " }\n" \
+ " return offset + byteLength;\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeWriteUIntLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeWriteUIntLECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeWriteUIntLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeWriteUIntLECodeLength = 955;
+static const JSC::Intrinsic s_jsBufferPrototypeWriteUIntLECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeWriteUIntLECode =
+ "(function (value, offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " view.setUint8(offset, value);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " view.setUint16(offset, value, true);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " view.setUint16(offset, value & 0xFFFF, true);\n" \
+ " view.setUint8(offset + 2, Math.floor(value * 2 ** -16));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " view.setUint32(offset, value, true);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " view.setUint32(offset, value | 0, true);\n" \
+ " view.setUint8(offset + 4, Math.floor(value * 2 ** -32));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " view.setUint32(offset, value | 0, true);\n" \
+ " view.setUint16(offset + 4, Math.floor(value * 2 ** -32), true);\n" \
+ " break;\n" \
+ " }\n" \
+ " default: {\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ " }\n" \
+ " }\n" \
+ " return offset + byteLength;\n" \
+ "})\n" \
+;
+
+const JSC::ConstructAbility s_jsBufferPrototypeWriteUIntBECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeWriteUIntBECodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_jsBufferPrototypeWriteUIntBECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_jsBufferPrototypeWriteUIntBECodeLength = 961;
+static const JSC::Intrinsic s_jsBufferPrototypeWriteUIntBECodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeWriteUIntBECode =
+ "(function (value, offset, byteLength) {\n" \
+ " \"use strict\";\n" \
+ " const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);\n" \
+ " switch (byteLength) {\n" \
+ " case 1: {\n" \
+ " view.setUint8(offset, value);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 2: {\n" \
+ " view.setUint16(offset, value, false);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 3: {\n" \
+ " view.setUint16(offset + 1, value & 0xFFFF, false);\n" \
+ " view.setUint8(offset, Math.floor(value * 2 ** -16));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 4: {\n" \
+ " view.setUint32(offset, value, false);\n" \
+ " break;\n" \
+ " }\n" \
+ " case 5: {\n" \
+ " view.setUint32(offset + 1, value | 0, false);\n" \
+ " view.setUint8(offset, Math.floor(value * 2 ** -32));\n" \
+ " break;\n" \
+ " }\n" \
+ " case 6: {\n" \
+ " view.setUint32(offset + 2, value | 0, false);\n" \
+ " view.setUint16(offset, Math.floor(value * 2 ** -32), false);\n" \
+ " break;\n" \
+ " }\n" \
+ " default: {\n" \
+ " @throwRangeError(\"byteLength must be >= 1 and <= 6\");\n" \
+ " }\n" \
+ " }\n" \
+ " return offset + byteLength;\n" \
+ "})\n" \
+;
+
const JSC::ConstructAbility s_jsBufferPrototypeWriteFloatLECodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeWriteFloatLECodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_jsBufferPrototypeWriteFloatLECodeImplementationVisibility = JSC::ImplementationVisibility::Public;
@@ -719,7 +1039,7 @@ const char* const s_jsBufferPrototypeToJSONCode =
const JSC::ConstructAbility s_jsBufferPrototypeSliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeSliceCodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_jsBufferPrototypeSliceCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_jsBufferPrototypeSliceCodeLength = 612;
+const int s_jsBufferPrototypeSliceCodeLength = 613;
static const JSC::Intrinsic s_jsBufferPrototypeSliceCodeIntrinsic = JSC::NoIntrinsic;
const char* const s_jsBufferPrototypeSliceCode =
"(function (start, end) {\n" \
@@ -741,7 +1061,7 @@ const char* const s_jsBufferPrototypeSliceCode =
" }\n" \
"\n" \
" var start_ = adjustOffset(start, byteLength);\n" \
- " var end_ = end !== undefined ? adjustOffset(end, byteLength) : byteLength;\n" \
+ " var end_ = end !== @undefined ? adjustOffset(end, byteLength) : byteLength;\n" \
" return new Buffer(buffer, byteOffset + start_, end_ > start_ ? (end_ - start_) : 0);\n" \
"})\n" \
;
@@ -749,37 +1069,24 @@ const char* const s_jsBufferPrototypeSliceCode =
const JSC::ConstructAbility s_jsBufferPrototypeParentCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeParentCodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_jsBufferPrototypeParentCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_jsBufferPrototypeParentCodeLength = 57;
+const int s_jsBufferPrototypeParentCodeLength = 114;
static const JSC::Intrinsic s_jsBufferPrototypeParentCodeIntrinsic = JSC::NoIntrinsic;
const char* const s_jsBufferPrototypeParentCode =
"(function () {\n" \
" \"use strict\";\n" \
- " return this?.buffer;\n" \
+ " return @isObject(this) && this instanceof @Buffer ? this.buffer : @undefined;\n" \
"})\n" \
;
const JSC::ConstructAbility s_jsBufferPrototypeOffsetCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeOffsetCodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_jsBufferPrototypeOffsetCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_jsBufferPrototypeOffsetCodeLength = 61;
+const int s_jsBufferPrototypeOffsetCodeLength = 118;
static const JSC::Intrinsic s_jsBufferPrototypeOffsetCodeIntrinsic = JSC::NoIntrinsic;
const char* const s_jsBufferPrototypeOffsetCode =
"(function () {\n" \
" \"use strict\";\n" \
- " return this?.byteOffset;\n" \
- "})\n" \
-;
-
-const JSC::ConstructAbility s_jsBufferPrototypeInitializeBunBufferCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
-const JSC::ConstructorKind s_jsBufferPrototypeInitializeBunBufferCodeConstructorKind = JSC::ConstructorKind::None;
-const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBufferCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
-const int s_jsBufferPrototypeInitializeBunBufferCodeLength = 45;
-static const JSC::Intrinsic s_jsBufferPrototypeInitializeBunBufferCodeIntrinsic = JSC::NoIntrinsic;
-const char* const s_jsBufferPrototypeInitializeBunBufferCode =
- "(function (parameters)\n" \
- "{\n" \
- " \"use strict\";\n" \
- "\n" \
+ " return @isObject(this) && this instanceof @Buffer ? this.byteOffset : @undefined;\n" \
"})\n" \
;
diff --git a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h
index f7a3364de..60c00bedf 100644
--- a/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h
+++ b/src/bun.js/builtins/cpp/JSBufferPrototypeBuiltins.h
@@ -102,6 +102,26 @@ extern const int s_jsBufferPrototypeReadUInt32BECodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeReadUInt32BECodeConstructAbility;
extern const JSC::ConstructorKind s_jsBufferPrototypeReadUInt32BECodeConstructorKind;
extern const JSC::ImplementationVisibility s_jsBufferPrototypeReadUInt32BECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeReadIntLECode;
+extern const int s_jsBufferPrototypeReadIntLECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeReadIntLECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeReadIntLECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeReadIntLECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeReadIntBECode;
+extern const int s_jsBufferPrototypeReadIntBECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeReadIntBECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeReadIntBECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeReadIntBECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeReadUIntLECode;
+extern const int s_jsBufferPrototypeReadUIntLECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeReadUIntLECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeReadUIntLECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeReadUIntLECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeReadUIntBECode;
+extern const int s_jsBufferPrototypeReadUIntBECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeReadUIntBECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeReadUIntBECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeReadUIntBECodeImplementationVisibility;
extern const char* const s_jsBufferPrototypeReadFloatLECode;
extern const int s_jsBufferPrototypeReadFloatLECodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeReadFloatLECodeConstructAbility;
@@ -192,6 +212,26 @@ extern const int s_jsBufferPrototypeWriteUInt32BECodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeWriteUInt32BECodeConstructAbility;
extern const JSC::ConstructorKind s_jsBufferPrototypeWriteUInt32BECodeConstructorKind;
extern const JSC::ImplementationVisibility s_jsBufferPrototypeWriteUInt32BECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeWriteIntLECode;
+extern const int s_jsBufferPrototypeWriteIntLECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeWriteIntLECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeWriteIntLECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeWriteIntLECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeWriteIntBECode;
+extern const int s_jsBufferPrototypeWriteIntBECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeWriteIntBECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeWriteIntBECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeWriteIntBECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeWriteUIntLECode;
+extern const int s_jsBufferPrototypeWriteUIntLECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeWriteUIntLECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeWriteUIntLECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeWriteUIntLECodeImplementationVisibility;
+extern const char* const s_jsBufferPrototypeWriteUIntBECode;
+extern const int s_jsBufferPrototypeWriteUIntBECodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeWriteUIntBECodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeWriteUIntBECodeConstructorKind;
+extern const JSC::ImplementationVisibility s_jsBufferPrototypeWriteUIntBECodeImplementationVisibility;
extern const char* const s_jsBufferPrototypeWriteFloatLECode;
extern const int s_jsBufferPrototypeWriteFloatLECodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeWriteFloatLECodeConstructAbility;
@@ -332,11 +372,6 @@ extern const int s_jsBufferPrototypeOffsetCodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeOffsetCodeConstructAbility;
extern const JSC::ConstructorKind s_jsBufferPrototypeOffsetCodeConstructorKind;
extern const JSC::ImplementationVisibility s_jsBufferPrototypeOffsetCodeImplementationVisibility;
-extern const char* const s_jsBufferPrototypeInitializeBunBufferCode;
-extern const int s_jsBufferPrototypeInitializeBunBufferCodeLength;
-extern const JSC::ConstructAbility s_jsBufferPrototypeInitializeBunBufferCodeConstructAbility;
-extern const JSC::ConstructorKind s_jsBufferPrototypeInitializeBunBufferCodeConstructorKind;
-extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBufferCodeImplementationVisibility;
#define WEBCORE_FOREACH_JSBUFFERPROTOTYPE_BUILTIN_DATA(macro) \
macro(setBigUint64, jsBufferPrototypeSetBigUint64, 3) \
@@ -350,6 +385,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(readInt32BE, jsBufferPrototypeReadInt32BE, 1) \
macro(readUInt32LE, jsBufferPrototypeReadUInt32LE, 1) \
macro(readUInt32BE, jsBufferPrototypeReadUInt32BE, 1) \
+ macro(readIntLE, jsBufferPrototypeReadIntLE, 2) \
+ macro(readIntBE, jsBufferPrototypeReadIntBE, 2) \
+ macro(readUIntLE, jsBufferPrototypeReadUIntLE, 2) \
+ macro(readUIntBE, jsBufferPrototypeReadUIntBE, 2) \
macro(readFloatLE, jsBufferPrototypeReadFloatLE, 1) \
macro(readFloatBE, jsBufferPrototypeReadFloatBE, 1) \
macro(readDoubleLE, jsBufferPrototypeReadDoubleLE, 1) \
@@ -368,6 +407,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(writeInt32BE, jsBufferPrototypeWriteInt32BE, 2) \
macro(writeUInt32LE, jsBufferPrototypeWriteUInt32LE, 2) \
macro(writeUInt32BE, jsBufferPrototypeWriteUInt32BE, 2) \
+ macro(writeIntLE, jsBufferPrototypeWriteIntLE, 3) \
+ macro(writeIntBE, jsBufferPrototypeWriteIntBE, 3) \
+ macro(writeUIntLE, jsBufferPrototypeWriteUIntLE, 3) \
+ macro(writeUIntBE, jsBufferPrototypeWriteUIntBE, 3) \
macro(writeFloatLE, jsBufferPrototypeWriteFloatLE, 2) \
macro(writeFloatBE, jsBufferPrototypeWriteFloatBE, 2) \
macro(writeDoubleLE, jsBufferPrototypeWriteDoubleLE, 2) \
@@ -396,7 +439,6 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(slice, jsBufferPrototypeSlice, 2) \
macro(parent, jsBufferPrototypeParent, 0) \
macro(offset, jsBufferPrototypeOffset, 0) \
- macro(initializeBunBuffer, jsBufferPrototypeInitializeBunBuffer, 1) \
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_SETBIGUINT64 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READINT8 1
@@ -409,6 +451,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READINT32BE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READUINT32LE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READUINT32BE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READINTLE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READINTBE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READUINTLE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READUINTBE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READFLOATLE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READFLOATBE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_READDOUBLELE 1
@@ -427,6 +473,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEINT32BE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEUINT32LE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEUINT32BE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEINTLE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEINTBE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEUINTLE 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEUINTBE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEFLOATLE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEFLOATBE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEDOUBLELE 1
@@ -455,7 +505,6 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_SLICE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_PARENT 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_OFFSET 1
-#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_INITIALIZEBUNBUFFER 1
#define WEBCORE_FOREACH_JSBUFFERPROTOTYPE_BUILTIN_CODE(macro) \
macro(jsBufferPrototypeSetBigUint64Code, setBigUint64, ASCIILiteral(), s_jsBufferPrototypeSetBigUint64CodeLength) \
@@ -469,6 +518,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(jsBufferPrototypeReadInt32BECode, readInt32BE, ASCIILiteral(), s_jsBufferPrototypeReadInt32BECodeLength) \
macro(jsBufferPrototypeReadUInt32LECode, readUInt32LE, ASCIILiteral(), s_jsBufferPrototypeReadUInt32LECodeLength) \
macro(jsBufferPrototypeReadUInt32BECode, readUInt32BE, ASCIILiteral(), s_jsBufferPrototypeReadUInt32BECodeLength) \
+ macro(jsBufferPrototypeReadIntLECode, readIntLE, ASCIILiteral(), s_jsBufferPrototypeReadIntLECodeLength) \
+ macro(jsBufferPrototypeReadIntBECode, readIntBE, ASCIILiteral(), s_jsBufferPrototypeReadIntBECodeLength) \
+ macro(jsBufferPrototypeReadUIntLECode, readUIntLE, ASCIILiteral(), s_jsBufferPrototypeReadUIntLECodeLength) \
+ macro(jsBufferPrototypeReadUIntBECode, readUIntBE, ASCIILiteral(), s_jsBufferPrototypeReadUIntBECodeLength) \
macro(jsBufferPrototypeReadFloatLECode, readFloatLE, ASCIILiteral(), s_jsBufferPrototypeReadFloatLECodeLength) \
macro(jsBufferPrototypeReadFloatBECode, readFloatBE, ASCIILiteral(), s_jsBufferPrototypeReadFloatBECodeLength) \
macro(jsBufferPrototypeReadDoubleLECode, readDoubleLE, ASCIILiteral(), s_jsBufferPrototypeReadDoubleLECodeLength) \
@@ -487,6 +540,10 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(jsBufferPrototypeWriteInt32BECode, writeInt32BE, ASCIILiteral(), s_jsBufferPrototypeWriteInt32BECodeLength) \
macro(jsBufferPrototypeWriteUInt32LECode, writeUInt32LE, ASCIILiteral(), s_jsBufferPrototypeWriteUInt32LECodeLength) \
macro(jsBufferPrototypeWriteUInt32BECode, writeUInt32BE, ASCIILiteral(), s_jsBufferPrototypeWriteUInt32BECodeLength) \
+ macro(jsBufferPrototypeWriteIntLECode, writeIntLE, ASCIILiteral(), s_jsBufferPrototypeWriteIntLECodeLength) \
+ macro(jsBufferPrototypeWriteIntBECode, writeIntBE, ASCIILiteral(), s_jsBufferPrototypeWriteIntBECodeLength) \
+ macro(jsBufferPrototypeWriteUIntLECode, writeUIntLE, ASCIILiteral(), s_jsBufferPrototypeWriteUIntLECodeLength) \
+ macro(jsBufferPrototypeWriteUIntBECode, writeUIntBE, ASCIILiteral(), s_jsBufferPrototypeWriteUIntBECodeLength) \
macro(jsBufferPrototypeWriteFloatLECode, writeFloatLE, ASCIILiteral(), s_jsBufferPrototypeWriteFloatLECodeLength) \
macro(jsBufferPrototypeWriteFloatBECode, writeFloatBE, ASCIILiteral(), s_jsBufferPrototypeWriteFloatBECodeLength) \
macro(jsBufferPrototypeWriteDoubleLECode, writeDoubleLE, ASCIILiteral(), s_jsBufferPrototypeWriteDoubleLECodeLength) \
@@ -515,7 +572,6 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(jsBufferPrototypeSliceCode, slice, ASCIILiteral(), s_jsBufferPrototypeSliceCodeLength) \
macro(jsBufferPrototypeParentCode, parent, "get parent"_s, s_jsBufferPrototypeParentCodeLength) \
macro(jsBufferPrototypeOffsetCode, offset, "get offset"_s, s_jsBufferPrototypeOffsetCodeLength) \
- macro(jsBufferPrototypeInitializeBunBufferCode, initializeBunBuffer, ASCIILiteral(), s_jsBufferPrototypeInitializeBunBufferCodeLength) \
#define WEBCORE_FOREACH_JSBUFFERPROTOTYPE_BUILTIN_FUNCTION_NAME(macro) \
macro(asciiSlice) \
@@ -526,7 +582,6 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(base64urlWrite) \
macro(hexSlice) \
macro(hexWrite) \
- macro(initializeBunBuffer) \
macro(latin1Slice) \
macro(latin1Write) \
macro(offset) \
@@ -544,11 +599,15 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(readInt32BE) \
macro(readInt32LE) \
macro(readInt8) \
+ macro(readIntBE) \
+ macro(readIntLE) \
macro(readUInt16BE) \
macro(readUInt16LE) \
macro(readUInt32BE) \
macro(readUInt32LE) \
macro(readUInt8) \
+ macro(readUIntBE) \
+ macro(readUIntLE) \
macro(setBigUint64) \
macro(slice) \
macro(toJSON) \
@@ -571,11 +630,15 @@ extern const JSC::ImplementationVisibility s_jsBufferPrototypeInitializeBunBuffe
macro(writeInt32BE) \
macro(writeInt32LE) \
macro(writeInt8) \
+ macro(writeIntBE) \
+ macro(writeIntLE) \
macro(writeUInt16BE) \
macro(writeUInt16LE) \
macro(writeUInt32BE) \
macro(writeUInt32LE) \
macro(writeUInt8) \
+ macro(writeUIntBE) \
+ macro(writeUIntLE) \
#define DECLARE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \
JSC::FunctionExecutable* codeName##Generator(JSC::VM&);
diff --git a/src/bun.js/builtins/js/JSBufferPrototype.js b/src/bun.js/builtins/js/JSBufferPrototype.js
index 827e613d8..32aebb3f2 100644
--- a/src/bun.js/builtins/js/JSBufferPrototype.js
+++ b/src/bun.js/builtins/js/JSBufferPrototype.js
@@ -73,6 +73,116 @@ function readUInt32BE(offset) {
"use strict";
return (this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getUint32(offset, false);
}
+
+function readIntLE(offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ return view.getInt8(offset);
+ }
+ case 2: {
+ return view.getInt16(offset, true);
+ }
+ case 3: {
+ const val = view.getUint16(offset, true) + view.getUint8(offset + 2) * 2 ** 16;
+ return val | (val & 2 ** 23) * 0x1fe;
+ }
+ case 4: {
+ return view.getInt32(offset, true);
+ }
+ case 5: {
+ const last = view.getUint8(offset + 4);
+ return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset, true);
+ }
+ case 6: {
+ const last = view.getUint16(offset + 4, true);
+ return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset, true);
+ }
+ }
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+}
+function readIntBE(offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ return view.getInt8(offset);
+ }
+ case 2: {
+ return view.getInt16(offset, false);
+ }
+ case 3: {
+ const val = view.getUint16(offset + 1, false) + view.getUint8(offset) * 2 ** 16;
+ return val | (val & 2 ** 23) * 0x1fe;
+ }
+ case 4: {
+ return view.getInt32(offset, false);
+ }
+ case 5: {
+ const last = view.getUint8(offset);
+ return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset + 1, false);
+ }
+ case 6: {
+ const last = view.getUint16(offset, false);
+ return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset + 2, false);
+ }
+ }
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+}
+function readUIntLE(offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ return view.getUint8(offset);
+ }
+ case 2: {
+ return view.getUint16(offset, true);
+ }
+ case 3: {
+ return view.getUint16(offset, true) + view.getUint8(offset + 2) * 2 ** 16;
+ }
+ case 4: {
+ return view.getUint32(offset, true);
+ }
+ case 5: {
+ return view.getUint8(offset + 4) * 2 ** 32 + view.getUint32(offset, true);
+ }
+ case 6: {
+ return view.getUint16(offset + 4, true) * 2 ** 32 + view.getUint32(offset, true);
+ }
+ }
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+}
+function readUIntBE(offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ return view.getUint8(offset);
+ }
+ case 2: {
+ return view.getUint16(offset, false);
+ }
+ case 3: {
+ return view.getUint16(offset + 1, false) + view.getUint8(offset) * 2 ** 16;
+ }
+ case 4: {
+ return view.getUint32(offset, false);
+ }
+ case 5: {
+ const last = view.getUint8(offset);
+ return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + view.getUint32(offset + 1, false);
+ }
+ case 6: {
+ const last = view.getUint16(offset, false);
+ return (last | (last & 2 ** 15) * 0x1fffe) * 2 ** 32 + view.getUint32(offset + 2, false);
+ }
+ }
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+}
+
function readFloatLE(offset) {
"use strict";
return (this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getFloat32(offset, true);
@@ -105,6 +215,7 @@ function readBigUInt64BE(offset) {
"use strict";
return (this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getBigUint64(offset, false);
}
+
function writeInt8(value, offset) {
"use strict";
(this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setInt8(offset, value);
@@ -156,6 +267,155 @@ function writeUInt32BE(value, offset) {
return offset + 4;
}
+function writeIntLE(value, offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ view.setInt8(offset, value);
+ break;
+ }
+ case 2: {
+ view.setInt16(offset, value, true);
+ break;
+ }
+ case 3: {
+ view.setUint16(offset, value & 0xFFFF, true);
+ view.setInt8(offset + 2, Math.floor(value * 2 ** -16));
+ break;
+ }
+ case 4: {
+ view.setInt32(offset, value, true);
+ break;
+ }
+ case 5: {
+ view.setUint32(offset, value | 0, true);
+ view.setInt8(offset + 4, Math.floor(value * 2 ** -32));
+ break;
+ }
+ case 6: {
+ view.setUint32(offset, value | 0, true);
+ view.setInt16(offset + 4, Math.floor(value * 2 ** -32), true);
+ break;
+ }
+ default: {
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+ }
+ }
+ return offset + byteLength;
+}
+function writeIntBE(value, offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ view.setInt8(offset, value);
+ break;
+ }
+ case 2: {
+ view.setInt16(offset, value, false);
+ break;
+ }
+ case 3: {
+ view.setUint16(offset + 1, value & 0xFFFF, false);
+ view.setInt8(offset, Math.floor(value * 2 ** -16));
+ break;
+ }
+ case 4: {
+ view.setInt32(offset, value, false);
+ break;
+ }
+ case 5: {
+ view.setUint32(offset + 1, value | 0, false);
+ view.setInt8(offset, Math.floor(value * 2 ** -32));
+ break;
+ }
+ case 6: {
+ view.setUint32(offset + 2, value | 0, false);
+ view.setInt16(offset, Math.floor(value * 2 ** -32), false);
+ break;
+ }
+ default: {
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+ }
+ }
+ return offset + byteLength;
+}
+function writeUIntLE(value, offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ view.setUint8(offset, value);
+ break;
+ }
+ case 2: {
+ view.setUint16(offset, value, true);
+ break;
+ }
+ case 3: {
+ view.setUint16(offset, value & 0xFFFF, true);
+ view.setUint8(offset + 2, Math.floor(value * 2 ** -16));
+ break;
+ }
+ case 4: {
+ view.setUint32(offset, value, true);
+ break;
+ }
+ case 5: {
+ view.setUint32(offset, value | 0, true);
+ view.setUint8(offset + 4, Math.floor(value * 2 ** -32));
+ break;
+ }
+ case 6: {
+ view.setUint32(offset, value | 0, true);
+ view.setUint16(offset + 4, Math.floor(value * 2 ** -32), true);
+ break;
+ }
+ default: {
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+ }
+ }
+ return offset + byteLength;
+}
+function writeUIntBE(value, offset, byteLength) {
+ "use strict";
+ const view = this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength);
+ switch (byteLength) {
+ case 1: {
+ view.setUint8(offset, value);
+ break;
+ }
+ case 2: {
+ view.setUint16(offset, value, false);
+ break;
+ }
+ case 3: {
+ view.setUint16(offset + 1, value & 0xFFFF, false);
+ view.setUint8(offset, Math.floor(value * 2 ** -16));
+ break;
+ }
+ case 4: {
+ view.setUint32(offset, value, false);
+ break;
+ }
+ case 5: {
+ view.setUint32(offset + 1, value | 0, false);
+ view.setUint8(offset, Math.floor(value * 2 ** -32));
+ break;
+ }
+ case 6: {
+ view.setUint32(offset + 2, value | 0, false);
+ view.setUint16(offset, Math.floor(value * 2 ** -32), false);
+ break;
+ }
+ default: {
+ @throwRangeError("byteLength must be >= 1 and <= 6");
+ }
+ }
+ return offset + byteLength;
+}
+
function writeFloatLE(value, offset) {
"use strict";
(this.@dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setFloat32(offset, value, true);
@@ -296,24 +556,18 @@ function slice(start, end) {
}
var start_ = adjustOffset(start, byteLength);
- var end_ = end !== undefined ? adjustOffset(end, byteLength) : byteLength;
+ var end_ = end !== @undefined ? adjustOffset(end, byteLength) : byteLength;
return new Buffer(buffer, byteOffset + start_, end_ > start_ ? (end_ - start_) : 0);
}
@getter
function parent() {
"use strict";
- return this?.buffer;
+ return @isObject(this) && this instanceof @Buffer ? this.buffer : @undefined;
}
@getter
function offset() {
"use strict";
- return this?.byteOffset;
-}
-
-function initializeBunBuffer(parameters)
-{
- "use strict";
-
+ return @isObject(this) && this instanceof @Buffer ? this.byteOffset : @undefined;
}
diff --git a/src/bun.js/node/buffer.zig b/src/bun.js/node/buffer.zig
index 5a7d64955..f3cc3c2c2 100644
--- a/src/bun.js/node/buffer.zig
+++ b/src/bun.js/node/buffer.zig
@@ -1,96 +1,72 @@
-const std = @import("std");
const bun = @import("bun");
-const strings = bun.strings;
-const string = bun.string;
-const AsyncIO = @import("bun").AsyncIO;
-const JSC = @import("bun").JSC;
-const PathString = JSC.PathString;
-const Environment = bun.Environment;
-const C = bun.C;
-const Syscall = @import("./syscall.zig");
-const os = std.os;
-
-const JSGlobalObject = JSC.JSGlobalObject;
-const ArgumentsSlice = JSC.Node.ArgumentsSlice;
+const JSC = bun.JSC;
+const Encoder = JSC.WebCore.Encoder;
pub const BufferVectorized = struct {
- extern fn memset_pattern16(b: *anyopaque, pattern16: *const anyopaque, len: usize) void;
-
pub fn fill(
str: *JSC.ZigString,
buf_ptr: [*]u8,
fill_length: usize,
encoding: JSC.Node.Encoding,
- ) callconv(.C) void {
- if (str.len == 0) return;
+ ) callconv(.C) bool {
+ if (str.len == 0) return true;
var buf = buf_ptr[0..fill_length];
const written = switch (encoding) {
- JSC.Node.Encoding.utf8 => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.utf8, true)
+ .utf8 => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .utf8, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.utf8),
- JSC.Node.Encoding.ascii => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.ascii, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .utf8),
+ .ascii => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .ascii, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.ascii),
- JSC.Node.Encoding.latin1 => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.latin1, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .ascii),
+ .latin1 => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .latin1, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.latin1),
- JSC.Node.Encoding.buffer => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.buffer, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .latin1),
+ .buffer => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .buffer, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.buffer),
- JSC.Node.Encoding.utf16le,
- JSC.Node.Encoding.ucs2,
- => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.utf16le, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .buffer),
+ .utf16le, .ucs2 => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .utf16le, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.utf16le),
- JSC.Node.Encoding.base64 => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.base64, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .utf16le),
+ .base64 => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .base64, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.base64),
- JSC.Node.Encoding.base64url => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.base64url, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .base64),
+ .base64url => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .base64url, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.base64url),
- JSC.Node.Encoding.hex => if (str.is16Bit())
- JSC.WebCore.Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, JSC.Node.Encoding.hex, true)
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .base64url),
+ .hex => if (str.is16Bit())
+ Encoder.writeU16(str.utf16SliceAligned().ptr, str.utf16SliceAligned().len, buf.ptr, buf.len, .hex, true)
else
- JSC.WebCore.Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, JSC.Node.Encoding.hex),
- };
-
- if (written <= 0) {
- return;
- }
+ Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .hex),
+ } catch return false;
- var contents = buf[0..@intCast(usize, written)];
- buf = buf[@intCast(usize, written)..];
+ switch (written) {
+ 0 => {},
+ 1 => @memset(buf.ptr, buf[0], buf.len),
+ else => {
+ var contents = buf[0..written];
+ buf = buf[written..];
- if (contents.len == 1) {
- @memset(buf.ptr, contents[0], buf.len);
- return;
- }
-
- const minimum_contents = contents;
- while (buf.len >= contents.len) {
- const min_len = @min(contents.len, buf.len);
- bun.copy(u8, buf, contents[0..min_len]);
- if (buf.len <= contents.len) {
- break;
- }
- buf = buf[min_len..];
- contents.len *= 2;
- }
+ while (buf.len >= contents.len) {
+ bun.copy(u8, buf, contents);
+ buf = buf[contents.len..];
+ contents.len *= 2;
+ }
- while (buf.len > 0) {
- const to_fill = @min(minimum_contents.len, buf.len);
- bun.copy(u8, buf, minimum_contents[0..to_fill]);
- buf = buf[to_fill..];
+ if (buf.len > 0) {
+ bun.copy(u8, buf, contents[0..buf.len]);
+ }
+ },
}
+ return true;
}
};
diff --git a/src/bun.js/webcore/base64.zig b/src/bun.js/webcore/base64.zig
deleted file mode 100644
index aad1c471b..000000000
--- a/src/bun.js/webcore/base64.zig
+++ /dev/null
@@ -1,445 +0,0 @@
-// this is ripped from zig's stdlib
-const std = @import("std");
-const assert = std.debug.assert;
-const testing = std.testing;
-const mem = std.mem;
-
-pub const Error = error{
- InvalidCharacter,
- InvalidPadding,
- NoSpaceLeft,
-};
-
-/// Base64 codecs
-pub const Codecs = struct {
- alphabet_chars: [64]u8,
- pad_char: ?u8,
- decoderWithIgnore: fn (ignore: []const u8) Base64DecoderWithIgnore,
- Encoder: Base64Encoder,
- Decoder: Base64Decoder,
-};
-
-pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".*;
-fn standardBase64DecoderWithIgnore(ignore: []const u8) Base64DecoderWithIgnore {
- return Base64DecoderWithIgnore.init(standard_alphabet_chars, '=', ignore);
-}
-
-/// Standard Base64 codecs, with padding
-pub const standard = Codecs{
- .alphabet_chars = standard_alphabet_chars,
- .pad_char = '=',
- .decoderWithIgnore = standardBase64DecoderWithIgnore,
- .Encoder = Base64Encoder.init(standard_alphabet_chars, '='),
- .Decoder = Base64Decoder.init(standard_alphabet_chars, '='),
-};
-
-/// Standard Base64 codecs, without padding
-pub const standard_no_pad = Codecs{
- .alphabet_chars = standard_alphabet_chars,
- .pad_char = null,
- .decoderWithIgnore = standardBase64DecoderWithIgnore,
- .Encoder = Base64Encoder.init(standard_alphabet_chars, null),
- .Decoder = Base64Decoder.init(standard_alphabet_chars, null),
-};
-
-pub const url_safe_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*;
-fn urlSafeBase64DecoderWithIgnore(ignore: []const u8) Base64DecoderWithIgnore {
- return Base64DecoderWithIgnore.init(url_safe_alphabet_chars, null, ignore);
-}
-
-/// URL-safe Base64 codecs, with padding
-pub const url_safe = Codecs{
- .alphabet_chars = url_safe_alphabet_chars,
- .pad_char = '=',
- .decoderWithIgnore = urlSafeBase64DecoderWithIgnore,
- .Encoder = Base64Encoder.init(url_safe_alphabet_chars, '='),
- .Decoder = Base64Decoder.init(url_safe_alphabet_chars, '='),
-};
-
-/// URL-safe Base64 codecs, without padding
-pub const url_safe_no_pad = Codecs{
- .alphabet_chars = url_safe_alphabet_chars,
- .pad_char = null,
- .decoderWithIgnore = urlSafeBase64DecoderWithIgnore,
- .Encoder = Base64Encoder.init(url_safe_alphabet_chars, null),
- .Decoder = Base64Decoder.init(url_safe_alphabet_chars, null),
-};
-
-pub const standard_pad_char = @compileError("deprecated; use standard.pad_char");
-pub const standard_encoder = @compileError("deprecated; use standard.Encoder");
-pub const standard_decoder = @compileError("deprecated; use standard.Decoder");
-
-pub const Base64Encoder = struct {
- alphabet_chars: [64]u8,
- pad_char: ?u8,
-
- /// A bunch of assertions, then simply pass the data right through.
- pub fn init(alphabet_chars: [64]u8, pad_char: ?u8) Base64Encoder {
- assert(alphabet_chars.len == 64);
- var char_in_alphabet = [_]bool{false} ** 256;
- for (alphabet_chars) |c| {
- assert(!char_in_alphabet[c]);
- assert(pad_char == null or c != pad_char.?);
- char_in_alphabet[c] = true;
- }
- return Base64Encoder{
- .alphabet_chars = alphabet_chars,
- .pad_char = pad_char,
- };
- }
-
- /// Compute the encoded length
- pub fn calcSize(encoder: *const Base64Encoder, source_len: usize) usize {
- if (encoder.pad_char != null) {
- return @divTrunc(source_len + 2, 3) * 4;
- } else {
- const leftover = source_len % 3;
- return @divTrunc(source_len, 3) * 4 + @divTrunc(leftover * 4 + 2, 3);
- }
- }
-
- /// dest.len must at least be what you get from ::calcSize.
- pub fn encode(encoder: *const Base64Encoder, dest: []u8, source: []const u8) []const u8 {
- const out_len = encoder.calcSize(source.len);
- assert(dest.len >= out_len);
-
- var acc: u12 = 0;
- var acc_len: u4 = 0;
- var out_idx: usize = 0;
- for (source) |v| {
- acc = (acc << 8) + v;
- acc_len += 8;
- while (acc_len >= 6) {
- acc_len -= 6;
- dest[out_idx] = encoder.alphabet_chars[@truncate(u6, (acc >> acc_len))];
- out_idx += 1;
- }
- }
- if (acc_len > 0) {
- dest[out_idx] = encoder.alphabet_chars[@truncate(u6, (acc << 6 - acc_len))];
- out_idx += 1;
- }
- if (encoder.pad_char) |pad_char| {
- for (&dest[out_idx..]) |*pad| {
- pad.* = pad_char;
- }
- }
- return dest[0..out_len];
- }
-};
-
-pub const Base64Decoder = struct {
- const invalid_char: u8 = 0xff;
-
- /// e.g. 'A' => 0.
- /// `invalid_char` for any value not in the 64 alphabet chars.
- char_to_index: [256]u8,
- pad_char: ?u8,
-
- pub fn init(alphabet_chars: [64]u8, pad_char: ?u8) Base64Decoder {
- var result = Base64Decoder{
- .char_to_index = [_]u8{invalid_char} ** 256,
- .pad_char = pad_char,
- };
-
- var char_in_alphabet = [_]bool{false} ** 256;
- for (alphabet_chars, 0..) |c, i| {
- assert(!char_in_alphabet[c]);
- assert(pad_char == null or c != pad_char.?);
-
- result.char_to_index[c] = @intCast(u8, i);
- char_in_alphabet[c] = true;
- }
- return result;
- }
-
- /// Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding.
- /// `InvalidPadding` is returned if the input length is not valid.
- pub fn calcSizeUpperBound(decoder: *const Base64Decoder, source_len: usize) Error!usize {
- var result = source_len / 4 * 3;
- const leftover = source_len % 4;
- if (decoder.pad_char != null) {
- if (leftover % 4 != 0) return error.InvalidPadding;
- } else {
- if (leftover % 4 == 1) return error.InvalidPadding;
- result += leftover * 3 / 4;
- }
- return result;
- }
-
- /// Return the exact decoded size for a slice.
- /// `InvalidPadding` is returned if the input length is not valid.
- pub fn calcSizeForSlice(decoder: *const Base64Decoder, source: []const u8) Error!usize {
- const source_len = source.len;
- var result = try decoder.calcSizeUpperBound(source_len);
- if (decoder.pad_char) |pad_char| {
- if (source_len >= 1 and source[source_len - 1] == pad_char) result -= 1;
- if (source_len >= 2 and source[source_len - 2] == pad_char) result -= 1;
- }
- return result;
- }
-
- /// dest.len must be what you get from ::calcSize.
- /// invalid characters result in error.InvalidCharacter.
- /// invalid padding results in error.InvalidPadding.
- pub fn decode(decoder: *const Base64Decoder, dest: []u8, source: []const u8) Error!void {
- if (decoder.pad_char != null and source.len % 4 != 0) return error.InvalidPadding;
- var acc: u12 = 0;
- var acc_len: u4 = 0;
- var dest_idx: usize = 0;
- var leftover_idx: ?usize = null;
- for (source, 0..) |c, src_idx| {
- const d = decoder.char_to_index[c];
- if (d == invalid_char) {
- if (decoder.pad_char == null or c != decoder.pad_char.?) return error.InvalidCharacter;
- leftover_idx = src_idx;
- break;
- }
- acc = (acc << 6) + d;
- acc_len += 6;
- if (acc_len >= 8) {
- acc_len -= 8;
- dest[dest_idx] = @truncate(u8, acc >> acc_len);
- dest_idx += 1;
- }
- }
- if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) {
- return error.InvalidPadding;
- }
- if (leftover_idx == null) return;
- var leftover = source[leftover_idx.?..];
- if (decoder.pad_char) |pad_char| {
- const padding_len = acc_len / 2;
- var padding_chars: usize = 0;
- for (leftover) |c| {
- if (c != pad_char) {
- return if (c == Base64Decoder.invalid_char) error.InvalidCharacter else error.InvalidPadding;
- }
- padding_chars += 1;
- }
- if (padding_chars != padding_len) return error.InvalidPadding;
- }
- }
-};
-
-pub const Base64DecoderWithIgnore = struct {
- decoder: Base64Decoder,
- char_is_ignored: [256]bool,
-
- pub fn init(alphabet_chars: [64]u8, pad_char: ?u8, ignore_chars: []const u8) Base64DecoderWithIgnore {
- var result = Base64DecoderWithIgnore{
- .decoder = Base64Decoder.init(alphabet_chars, pad_char),
- .char_is_ignored = [_]bool{false} ** 256,
- };
- for (ignore_chars) |c| {
- assert(result.decoder.char_to_index[c] == Base64Decoder.invalid_char);
- assert(!result.char_is_ignored[c]);
- assert(result.decoder.pad_char != c);
- result.char_is_ignored[c] = true;
- }
- return result;
- }
-
- /// Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding
- /// `InvalidPadding` is returned if the input length is not valid.
- pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) Error!usize {
- var result = source_len / 4 * 3;
- if (decoder_with_ignore.decoder.pad_char == null) {
- const leftover = source_len % 4;
- result += leftover * 3 / 4;
- }
- return result;
- }
-
- /// Invalid characters that are not ignored result in error.InvalidCharacter.
- /// Invalid padding results in error.InvalidPadding.
- /// Decoding more data than can fit in dest results in error.NoSpaceLeft. See also ::calcSizeUpperBound.
- /// Returns the number of bytes written to dest.
- pub fn decode(decoder_with_ignore: *const Base64DecoderWithIgnore, dest: []u8, source: []const u8) Error!usize {
- const decoder = &decoder_with_ignore.decoder;
- var acc: u12 = 0;
- var acc_len: u4 = 0;
- var dest_idx: usize = 0;
- var leftover_idx: ?usize = null;
- for (source, 0..) |c, src_idx| {
- if (decoder_with_ignore.char_is_ignored[c]) continue;
- const d = decoder.char_to_index[c];
- if (d == Base64Decoder.invalid_char) {
- if (decoder.pad_char == null or c != decoder.pad_char.?) return error.InvalidCharacter;
- leftover_idx = src_idx;
- break;
- }
- acc = (acc << 6) + d;
- acc_len += 6;
- if (acc_len >= 8) {
- if (dest_idx == dest.len) return error.NoSpaceLeft;
- acc_len -= 8;
- dest[dest_idx] = @truncate(u8, acc >> acc_len);
- dest_idx += 1;
- }
- }
- if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) {
- return error.InvalidPadding;
- }
- const padding_len = acc_len / 2;
- if (leftover_idx == null) {
- if (decoder.pad_char != null and padding_len != 0) return error.InvalidPadding;
- return dest_idx;
- }
- var leftover = source[leftover_idx.?..];
- if (decoder.pad_char) |pad_char| {
- var padding_chars: usize = 0;
- for (leftover) |c| {
- if (decoder_with_ignore.char_is_ignored[c]) continue;
- if (c != pad_char) {
- return if (c == Base64Decoder.invalid_char) error.InvalidCharacter else error.InvalidPadding;
- }
- padding_chars += 1;
- }
- if (padding_chars != padding_len) return error.InvalidPadding;
- }
- return dest_idx;
- }
-};
-
-test "base64" {
- @setEvalBranchQuota(8000);
- try testBase64();
- comptime try testAllApis(standard, "comptime", "Y29tcHRpbWU=");
-}
-
-test "base64 url_safe_no_pad" {
- @setEvalBranchQuota(8000);
- try testBase64UrlSafeNoPad();
- comptime try testAllApis(url_safe_no_pad, "comptime", "Y29tcHRpbWU");
-}
-
-fn testBase64() !void {
- const codecs = standard;
-
- try testAllApis(codecs, "", "");
- try testAllApis(codecs, "f", "Zg==");
- try testAllApis(codecs, "fo", "Zm8=");
- try testAllApis(codecs, "foo", "Zm9v");
- try testAllApis(codecs, "foob", "Zm9vYg==");
- try testAllApis(codecs, "fooba", "Zm9vYmE=");
- try testAllApis(codecs, "foobar", "Zm9vYmFy");
-
- try testDecodeIgnoreSpace(codecs, "", " ");
- try testDecodeIgnoreSpace(codecs, "f", "Z g= =");
- try testDecodeIgnoreSpace(codecs, "fo", " Zm8=");
- try testDecodeIgnoreSpace(codecs, "foo", "Zm9v ");
- try testDecodeIgnoreSpace(codecs, "foob", "Zm9vYg = = ");
- try testDecodeIgnoreSpace(codecs, "fooba", "Zm9v YmE=");
- try testDecodeIgnoreSpace(codecs, "foobar", " Z m 9 v Y m F y ");
-
- // test getting some api errors
- try testError(codecs, "A", error.InvalidPadding);
- try testError(codecs, "AA", error.InvalidPadding);
- try testError(codecs, "AAA", error.InvalidPadding);
- try testError(codecs, "A..A", error.InvalidCharacter);
- try testError(codecs, "AA=A", error.InvalidPadding);
- try testError(codecs, "AA/=", error.InvalidPadding);
- try testError(codecs, "A/==", error.InvalidPadding);
- try testError(codecs, "A===", error.InvalidPadding);
- try testError(codecs, "====", error.InvalidPadding);
-
- try testNoSpaceLeftError(codecs, "AA==");
- try testNoSpaceLeftError(codecs, "AAA=");
- try testNoSpaceLeftError(codecs, "AAAA");
- try testNoSpaceLeftError(codecs, "AAAAAA==");
-}
-
-fn testBase64UrlSafeNoPad() !void {
- const codecs = url_safe_no_pad;
-
- try testAllApis(codecs, "", "");
- try testAllApis(codecs, "f", "Zg");
- try testAllApis(codecs, "fo", "Zm8");
- try testAllApis(codecs, "foo", "Zm9v");
- try testAllApis(codecs, "foob", "Zm9vYg");
- try testAllApis(codecs, "fooba", "Zm9vYmE");
- try testAllApis(codecs, "foobar", "Zm9vYmFy");
-
- try testDecodeIgnoreSpace(codecs, "", " ");
- try testDecodeIgnoreSpace(codecs, "f", "Z g ");
- try testDecodeIgnoreSpace(codecs, "fo", " Zm8");
- try testDecodeIgnoreSpace(codecs, "foo", "Zm9v ");
- try testDecodeIgnoreSpace(codecs, "foob", "Zm9vYg ");
- try testDecodeIgnoreSpace(codecs, "fooba", "Zm9v YmE");
- try testDecodeIgnoreSpace(codecs, "foobar", " Z m 9 v Y m F y ");
-
- // test getting some api errors
- try testError(codecs, "A", error.InvalidPadding);
- try testError(codecs, "AAA=", error.InvalidCharacter);
- try testError(codecs, "A..A", error.InvalidCharacter);
- try testError(codecs, "AA=A", error.InvalidCharacter);
- try testError(codecs, "AA/=", error.InvalidCharacter);
- try testError(codecs, "A/==", error.InvalidCharacter);
- try testError(codecs, "A===", error.InvalidCharacter);
- try testError(codecs, "====", error.InvalidCharacter);
-
- try testNoSpaceLeftError(codecs, "AA");
- try testNoSpaceLeftError(codecs, "AAA");
- try testNoSpaceLeftError(codecs, "AAAA");
- try testNoSpaceLeftError(codecs, "AAAAAA");
-}
-
-fn testAllApis(codecs: Codecs, expected_decoded: []const u8, expected_encoded: []const u8) !void {
- // Base64Encoder
- {
- var buffer: [0x100]u8 = undefined;
- const encoded = codecs.Encoder.encode(&buffer, expected_decoded);
- try testing.expectEqualSlices(u8, expected_encoded, encoded);
- }
-
- // Base64Decoder
- {
- var buffer: [0x100]u8 = undefined;
- var decoded = buffer[0..try codecs.Decoder.calcSizeForSlice(expected_encoded)];
- try codecs.Decoder.decode(decoded, expected_encoded);
- try testing.expectEqualSlices(u8, expected_decoded, decoded);
- }
-
- // Base64DecoderWithIgnore
- {
- const decoder_ignore_nothing = codecs.decoderWithIgnore("");
- var buffer: [0x100]u8 = undefined;
- var decoded = buffer[0..try decoder_ignore_nothing.calcSizeUpperBound(expected_encoded.len)];
- var written = try decoder_ignore_nothing.decode(decoded, expected_encoded);
- try testing.expect(written <= decoded.len);
- try testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]);
- }
-}
-
-fn testDecodeIgnoreSpace(codecs: Codecs, expected_decoded: []const u8, encoded: []const u8) !void {
- const decoder_ignore_space = codecs.decoderWithIgnore(" ");
- var buffer: [0x100]u8 = undefined;
- var decoded = buffer[0..try decoder_ignore_space.calcSizeUpperBound(encoded.len)];
- var written = try decoder_ignore_space.decode(decoded, encoded);
- try testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]);
-}
-
-fn testError(codecs: Codecs, encoded: []const u8, expected_err: anyerror) !void {
- const decoder_ignore_space = codecs.decoderWithIgnore(" ");
- var buffer: [0x100]u8 = undefined;
- if (codecs.Decoder.calcSizeForSlice(encoded)) |decoded_size| {
- var decoded = buffer[0..decoded_size];
- if (codecs.Decoder.decode(decoded, encoded)) |_| {
- return error.ExpectedError;
- } else |err| if (err != expected_err) return err;
- } else |err| if (err != expected_err) return err;
-
- if (decoder_ignore_space.decode(buffer[0..], encoded)) |_| {
- return error.ExpectedError;
- } else |err| if (err != expected_err) return err;
-}
-
-fn testNoSpaceLeftError(codecs: Codecs, encoded: []const u8) !void {
- const decoder_ignore_space = codecs.decoderWithIgnore(" ");
- var buffer: [0x100]u8 = undefined;
- var decoded = buffer[0 .. (try codecs.Decoder.calcSizeForSlice(encoded)) - 1];
- if (decoder_ignore_space.decode(decoded, encoded)) |_| {
- return error.ExpectedError;
- } else |err| if (err != error.NoSpaceLeft) return err;
-}
diff --git a/src/bun.js/webcore/body.zig b/src/bun.js/webcore/body.zig
index 97c9f7874..d4bd490c1 100644
--- a/src/bun.js/webcore/body.zig
+++ b/src/bun.js/webcore/body.zig
@@ -477,6 +477,7 @@ pub const Body = struct {
// blob.bytes[0..blob.bytes.len],
// []const u16,
// str.utf16SliceAligned(),
+ // true,
// );
// blob.len = @intCast(InlineBlob.IntSize, result.written);
// std.debug.assert(@as(usize, result.read) == str.len);
diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig
index deab624d0..d58513c1e 100644
--- a/src/bun.js/webcore/encoding.zig
+++ b/src/bun.js/webcore/encoding.zig
@@ -98,7 +98,7 @@ pub const TextEncoder = struct {
// max utf16 -> utf8 length
if (slice.len <= buf.len / 4) {
- const result = strings.copyUTF16IntoUTF8(&buf, @TypeOf(slice), slice);
+ const result = strings.copyUTF16IntoUTF8(&buf, @TypeOf(slice), slice, true);
if (result.read == 0 or result.written == 0) {
const uint8array = JSC.JSValue.createUninitializedUint8Array(globalThis, 3);
const array_buffer = uint8array.asArrayBuffer(globalThis).?;
@@ -221,7 +221,7 @@ pub const TextEncoder = struct {
) u64 {
var output = buf_ptr[0..buf_len];
const input = input_ptr[0..input_len];
- const result: strings.EncodeIntoResult = strings.copyUTF16IntoUTF8(output, []const u16, input);
+ const result: strings.EncodeIntoResult = strings.copyUTF16IntoUTF8(output, []const u16, input, true);
if (result.read == 0 or result.written == 0) {
const replacement_char = [_]u8{ 239, 191, 189 };
@memcpy(buf_ptr, &replacement_char, replacement_char.len);
@@ -683,7 +683,7 @@ pub const TextDecoder = struct {
};
pub const Encoder = struct {
- export fn Bun__encoding__writeLatin1(input: [*]const u8, len: usize, to: [*]u8, to_len: usize, encoding: u8) i64 {
+ export fn Bun__encoding__writeLatin1(input: [*]const u8, len: usize, to: [*]u8, to_len: usize, encoding: u8) usize {
return switch (@intToEnum(JSC.Node.Encoding, encoding)) {
.utf8 => writeU8(input, len, to, to_len, .utf8),
.latin1 => writeU8(input, len, to, to_len, .ascii),
@@ -694,9 +694,9 @@ pub const Encoder = struct {
.base64url => writeU8(input, len, to, to_len, .base64url),
.hex => writeU8(input, len, to, to_len, .hex),
else => unreachable,
- };
+ } catch 0;
}
- export fn Bun__encoding__writeUTF16(input: [*]const u16, len: usize, to: [*]u8, to_len: usize, encoding: u8) i64 {
+ export fn Bun__encoding__writeUTF16(input: [*]const u16, len: usize, to: [*]u8, to_len: usize, encoding: u8) usize {
return switch (@intToEnum(JSC.Node.Encoding, encoding)) {
.utf8 => writeU16(input, len, to, to_len, .utf8, false),
.latin1 => writeU16(input, len, to, to_len, .ascii, false),
@@ -707,7 +707,7 @@ pub const Encoder = struct {
.base64url => writeU16(input, len, to, to_len, .base64url, false),
.hex => writeU16(input, len, to, to_len, .hex, false),
else => unreachable,
- };
+ } catch 0;
}
export fn Bun__encoding__byteLengthLatin1(input: [*]const u8, len: usize, encoding: u8) usize {
return switch (@intToEnum(JSC.Node.Encoding, encoding)) {
@@ -783,7 +783,7 @@ pub const Encoder = struct {
}
// pub fn writeUTF16AsUTF8(utf16: [*]const u16, len: usize, to: [*]u8, to_len: usize) callconv(.C) i32 {
- // return @intCast(i32, strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, utf16[0..len]).written);
+ // return @intCast(i32, strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, utf16[0..len], true).written);
// }
pub fn toString(input_ptr: [*]const u8, len: usize, global: *JSGlobalObject, comptime encoding: JSC.Node.Encoding) JSValue {
@@ -839,7 +839,7 @@ pub const Encoder = struct {
return ZigString.toExternalU16(output.ptr, output.len, global);
},
- JSC.Node.Encoding.hex => {
+ .hex => {
var output = allocator.alloc(u8, input.len * 2) catch return ZigString.init("Out of memory").toErrorInstance(global);
const wrote = strings.encodeBytesToHex(output, input);
std.debug.assert(wrote == output.len);
@@ -848,11 +848,11 @@ pub const Encoder = struct {
return val.toExternalValue(global);
},
- JSC.Node.Encoding.base64url => {
+ .base64url => {
return JSC.WTF.toBase64URLStringValue(input, global);
},
- JSC.Node.Encoding.base64 => {
+ .base64 => {
const to_len = bun.base64.encodeLen(input);
var to = allocator.alloc(u8, to_len) catch return ZigString.init("Out of memory").toErrorInstance(global);
const wrote = bun.base64.encode(to, input);
@@ -861,7 +861,7 @@ pub const Encoder = struct {
}
}
- pub fn writeU8(input: [*]const u8, len: usize, to_ptr: [*]u8, to_len: usize, comptime encoding: JSC.Node.Encoding) i64 {
+ pub fn writeU8(input: [*]const u8, len: usize, to_ptr: [*]u8, to_len: usize, comptime encoding: JSC.Node.Encoding) !usize {
if (len == 0 or to_len == 0)
return 0;
@@ -873,11 +873,11 @@ pub const Encoder = struct {
// if (comptime encoding.isBinaryToText()) {}
switch (comptime encoding) {
- JSC.Node.Encoding.buffer => {
+ .buffer => {
const written = @min(len, to_len);
@memcpy(to_ptr, input, written);
- return @intCast(i64, written);
+ return written;
},
.latin1, .ascii => {
const written = @min(len, to_len);
@@ -891,14 +891,14 @@ pub const Encoder = struct {
strings.copyLatin1IntoASCII(to, remain);
}
- return @intCast(i64, written);
+ return written;
},
.utf8 => {
// need to encode
- return @intCast(i64, strings.copyLatin1IntoUTF8(to_ptr[0..to_len], []const u8, input[0..len]).written);
+ return strings.copyLatin1IntoUTF8(to_ptr[0..to_len], []const u8, input[0..len]).written;
},
// encode latin1 into UTF16
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => {
+ .ucs2, .utf16le => {
if (to_len < 2)
return 0;
@@ -917,29 +917,13 @@ pub const Encoder = struct {
}
},
- JSC.Node.Encoding.hex => {
- return @intCast(i64, strings.decodeHexToBytes(to_ptr[0..to_len], u8, input[0..len]));
- },
-
- JSC.Node.Encoding.base64url => {
- var slice = strings.trim(input[0..len], "\r\n\t " ++ [_]u8{std.ascii.control_code.vt});
- if (slice.len == 0)
- return 0;
-
- if (strings.endsWithComptime(slice, "==")) {
- slice = slice[0 .. slice.len - 2];
- } else if (slice[slice.len - 1] == '=') {
- slice = slice[0 .. slice.len - 1];
- }
-
- const wrote = bun.base64.decodeURLSafe(to_ptr[0..to_len], slice).written;
- return @intCast(i64, wrote);
+ .hex => {
+ return strings.decodeHexToBytes(to_ptr[0..to_len], u8, input[0..len]);
},
- JSC.Node.Encoding.base64 => {
- return @intCast(i64, bun.base64.decode(to_ptr[0..to_len], input[0..len]).written);
+ .base64, .base64url => {
+ return bun.base64.decode(to_ptr[0..to_len], input[0..len]).written;
},
- // else => return 0,
}
}
@@ -952,46 +936,46 @@ pub const Encoder = struct {
return strings.elementLengthLatin1IntoUTF8([]const u8, input[0..len]);
},
- .latin1, JSC.Node.Encoding.ascii, JSC.Node.Encoding.buffer => {
+ .latin1, .ascii, .buffer => {
return len;
},
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => {
+ .ucs2, .utf16le => {
return strings.elementLengthUTF8IntoUTF16([]const u8, input[0..len]) * 2;
},
- JSC.Node.Encoding.hex => {
+ .hex => {
return len / 2;
},
- JSC.Node.Encoding.base64, JSC.Node.Encoding.base64url => {
+ .base64, .base64url => {
return bun.base64.decodeLen(input[0..len]);
},
// else => return &[_]u8{};
}
}
- pub fn writeU16(input: [*]const u16, len: usize, to: [*]u8, to_len: usize, comptime encoding: JSC.Node.Encoding, comptime allow_partial_write: bool) i64 {
+ pub fn writeU16(input: [*]const u16, len: usize, to: [*]u8, to_len: usize, comptime encoding: JSC.Node.Encoding, comptime allow_partial_write: bool) !usize {
if (len == 0)
return 0;
switch (comptime encoding) {
.utf8 => {
- return @intCast(i32, strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, input[0..len]).written);
+ return strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, input[0..len], allow_partial_write).written;
},
- .latin1, JSC.Node.Encoding.ascii, JSC.Node.Encoding.buffer => {
+ .latin1, .ascii, .buffer => {
const out = @min(len, to_len);
strings.copyU16IntoU8(to[0..to_len], []const u16, input[0..out]);
- return @intCast(i64, out);
+ return out;
},
// string is already encoded, just need to copy the data
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => {
+ .ucs2, .utf16le => {
if (allow_partial_write) {
const bytes_input_len = len * 2;
const written = @min(bytes_input_len, to_len);
const input_u8 = @ptrCast([*]const u8, input);
strings.copyU16IntoU8(to[0..written], []const u8, input_u8[0..written]);
- return @intCast(i64, written);
+ return written;
} else {
const bytes_input_len = len * 2;
const written = @min(bytes_input_len, to_len);
@@ -1000,15 +984,15 @@ pub const Encoder = struct {
const fixed_len = (written / 2) * 2;
const input_u8 = @ptrCast([*]const u8, input);
strings.copyU16IntoU8(to[0..written], []const u8, input_u8[0..fixed_len]);
- return @intCast(i64, fixed_len);
+ return fixed_len;
}
},
- JSC.Node.Encoding.hex => {
- return @intCast(i64, strings.decodeHexToBytes(to[0..to_len], u16, input[0..len]));
+ .hex => {
+ return strings.decodeHexToBytes(to[0..to_len], u16, input[0..len]);
},
- JSC.Node.Encoding.base64, JSC.Node.Encoding.base64url => {
+ .base64, .base64url => {
if (to_len < 2 or len == 0)
return 0;
@@ -1033,15 +1017,15 @@ pub const Encoder = struct {
.ascii, .latin1, .utf8 => {
return strings.elementLengthUTF16IntoUTF8([]const u16, input[0..len]);
},
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.buffer, JSC.Node.Encoding.utf16le => {
+ .ucs2, .buffer, .utf16le => {
return len * 2;
},
- JSC.Node.Encoding.hex => {
+ .hex => {
return len / 2;
},
- JSC.Node.Encoding.base64, JSC.Node.Encoding.base64url => {
+ .base64, .base64url => {
return bun.base64.decodeLenUpperBound(len);
},
// else => return &[_]u8{};
@@ -1057,13 +1041,12 @@ pub const Encoder = struct {
}
pub fn constructFromU8(input: [*]const u8, len: usize, comptime encoding: JSC.Node.Encoding) []u8 {
- if (len == 0)
- return &[_]u8{};
+ if (len == 0) return &[_]u8{};
const allocator = VirtualMachine.get().allocator;
switch (comptime encoding) {
- JSC.Node.Encoding.buffer => {
+ .buffer => {
var to = allocator.alloc(u8, len) catch return &[_]u8{};
@memcpy(to.ptr, input, len);
@@ -1082,52 +1065,35 @@ pub const Encoder = struct {
},
// encode latin1 into UTF16
// return as bytes
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => {
+ .ucs2, .utf16le => {
var to = allocator.alloc(u16, len) catch return &[_]u8{};
_ = strings.copyLatin1IntoUTF16([]u16, to, []const u8, input[0..len]);
return std.mem.sliceAsBytes(to[0..len]);
},
- JSC.Node.Encoding.hex => {
+ .hex => {
if (len < 2)
return &[_]u8{};
var to = allocator.alloc(u8, len / 2) catch return &[_]u8{};
- return to[0..strings.decodeHexToBytes(to, u8, input[0..len])];
+ return to[0..strings.decodeHexToBytesTruncate(to, u8, input[0..len])];
},
- JSC.Node.Encoding.base64url => {
- var slice = strings.trim(input[0..len], "\r\n\t " ++ [_]u8{std.ascii.control_code.vt});
- if (slice.len == 0)
- return &[_]u8{};
+ .base64, .base64url => {
+ const slice = strings.trim(input[0..len], "\r\n\t " ++ [_]u8{std.ascii.control_code.vt});
+ if (slice.len == 0) return &[_]u8{};
- if (strings.endsWithComptime(slice, "==")) {
- slice = slice[0 .. slice.len - 2];
- } else if (slice[slice.len - 1] == '=') {
- slice = slice[0 .. slice.len - 1];
- }
+ const outlen = bun.base64.decodeLen(slice);
+ const to = allocator.alloc(u8, outlen) catch return &[_]u8{};
- const to_len = bun.base64.urlsafe.decoder.calcSizeForSlice(slice) catch unreachable;
- var to = allocator.alloc(u8, to_len) catch return &[_]u8{};
- const wrote = bun.base64.decodeURLSafe(to[0..to_len], slice).written;
+ const wrote = bun.base64.decode(to[0..outlen], slice).written;
return to[0..wrote];
},
-
- JSC.Node.Encoding.base64 => {
- var slice = strings.trim(input[0..len], "\r\n\t " ++ [_]u8{std.ascii.control_code.vt});
- var outlen = bun.base64.decodeLen(slice);
-
- var to = allocator.alloc(u8, outlen) catch return &[_]u8{};
- const written = bun.base64.decode(to[0..outlen], slice).written;
- return to[0..@min(written, outlen)];
- },
- // else => return 0,
}
}
pub fn constructFromU16(input: [*]const u16, len: usize, comptime encoding: JSC.Node.Encoding) []u8 {
- if (len == 0)
- return &[_]u8{};
+ if (len == 0) return &[_]u8{};
const allocator = VirtualMachine.get().allocator;
@@ -1135,7 +1101,7 @@ pub const Encoder = struct {
.utf8 => {
return strings.toUTF8AllocWithType(allocator, []const u16, input[0..len]) catch return &[_]u8{};
},
- JSC.Node.Encoding.latin1, JSC.Node.Encoding.buffer, JSC.Node.Encoding.ascii => {
+ .latin1, .buffer, .ascii => {
var to = allocator.alloc(u8, len) catch return &[_]u8{};
var input_bytes = std.mem.sliceAsBytes(input[0..len]);
@memcpy(to.ptr, input_bytes.ptr, input_bytes.len);
@@ -1146,34 +1112,24 @@ pub const Encoder = struct {
return to;
},
// string is already encoded, just need to copy the data
- JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => {
+ .ucs2, .utf16le => {
var to = std.mem.sliceAsBytes(allocator.alloc(u16, len * 2) catch return &[_]u8{});
@memcpy(to.ptr, std.mem.sliceAsBytes(input[0..len]).ptr, std.mem.sliceAsBytes(input[0..len]).len);
return to;
},
- JSC.Node.Encoding.hex => {
+ .hex => {
var to = allocator.alloc(u8, len * 2) catch return &[_]u8{};
- return to[0..strings.decodeHexToBytes(to, u16, input[0..len])];
+ return to[0..strings.decodeHexToBytesTruncate(to, u16, input[0..len])];
},
- JSC.Node.Encoding.base64 => {
- // very very slow case!
- // shouldn't really happen though
- var transcoded = strings.toUTF8Alloc(allocator, input[0..len]) catch return &[_]u8{};
- defer allocator.free(transcoded);
- return constructFromU8(transcoded.ptr, transcoded.len, .base64);
- },
-
- JSC.Node.Encoding.base64url => {
-
+ .base64, .base64url => {
// very very slow case!
// shouldn't really happen though
var transcoded = strings.toUTF8Alloc(allocator, input[0..len]) catch return &[_]u8{};
defer allocator.free(transcoded);
- return constructFromU8(transcoded.ptr, transcoded.len, .base64url);
+ return constructFromU8(transcoded.ptr, transcoded.len, encoding);
},
- // else => return 0,
}
}
diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig
index 1de209b69..748b4583c 100644
--- a/src/bun.js/webcore/streams.zig
+++ b/src/bun.js/webcore/streams.zig
@@ -983,7 +983,7 @@ pub const Sink = struct {
if (stack_size >= str.len * 2) {
var buf: [stack_size]u8 = undefined;
- const copied = strings.copyUTF16IntoUTF8(&buf, []const u16, str);
+ const copied = strings.copyUTF16IntoUTF8(&buf, []const u16, str, true);
std.debug.assert(copied.written <= stack_size);
std.debug.assert(copied.read <= stack_size);
if (input.isDone()) {
diff --git a/src/http/websocket_http_client.zig b/src/http/websocket_http_client.zig
index a4f9284d3..a5be7faab 100644
--- a/src/http/websocket_http_client.zig
+++ b/src/http/websocket_http_client.zig
@@ -776,7 +776,7 @@ const Copy = union(enum) {
switch (this) {
.utf16 => |utf16| {
header.len = WebsocketHeader.packLength(content_byte_len);
- const encode_into_result = strings.copyUTF16IntoUTF8(to_mask, []const u16, utf16);
+ const encode_into_result = strings.copyUTF16IntoUTF8(to_mask, []const u16, utf16, true);
std.debug.assert(@as(usize, encode_into_result.written) == content_byte_len);
std.debug.assert(@as(usize, encode_into_result.read) == utf16.len);
header.len = WebsocketHeader.packLength(encode_into_result.written);
diff --git a/src/napi/napi.zig b/src/napi/napi.zig
index b06e25d7e..99d7c82fb 100644
--- a/src/napi/napi.zig
+++ b/src/napi/napi.zig
@@ -384,11 +384,8 @@ pub export fn napi_get_value_string_latin1(env: napi_env, value: napi_value, buf
if (zig_str.is16Bit()) {
const utf16 = zig_str.utf16SliceAligned();
- const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, buf_.len, .latin1, false);
- if (wrote < 0) {
- return genericFailure();
- }
- maybeAppendNull(&buf[@intCast(usize, wrote)], bufsize == 0);
+ const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, buf_.len, .latin1, false) catch return genericFailure();
+ maybeAppendNull(&buf[wrote], bufsize == 0);
// if zero terminated, report the length of the string without the null
result.* = @intCast(@TypeOf(result.*), wrote);
return .ok;
@@ -448,11 +445,8 @@ pub export fn napi_get_value_string_utf8(env: napi_env, value: napi_value, buf_p
if (zig_str.is16Bit()) {
const utf16 = zig_str.utf16SliceAligned();
- const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, buf_.len, .utf8, false);
- if (wrote < 0) {
- return genericFailure();
- }
- buf[@intCast(usize, wrote)] = 0;
+ const wrote = JSC.WebCore.Encoder.writeU16(utf16.ptr, utf16.len, buf, buf_.len, .utf8, false) catch return genericFailure();
+ buf[wrote] = 0;
if (result_ptr) |result| {
result.* = @intCast(@TypeOf(result.*), wrote);
}
diff --git a/src/string_immutable.zig b/src/string_immutable.zig
index e85fc4ef8..7bdd7cfe5 100644
--- a/src/string_immutable.zig
+++ b/src/string_immutable.zig
@@ -2550,7 +2550,7 @@ pub fn latin1ToCodepointBytesAssumeNotASCII16(char: u32) u16 {
return latin1_to_utf16_conversion_table[@truncate(u8, char)];
}
-pub fn copyUTF16IntoUTF8(buf: []u8, comptime Type: type, utf16: Type) EncodeIntoResult {
+pub fn copyUTF16IntoUTF8(buf: []u8, comptime Type: type, utf16: Type, comptime allow_partial_write: bool) EncodeIntoResult {
if (comptime Type == []const u16) {
if (bun.FeatureFlags.use_simdutf) {
if (utf16.len == 0)
@@ -2564,14 +2564,14 @@ pub fn copyUTF16IntoUTF8(buf: []u8, comptime Type: type, utf16: Type) EncodeInto
else
buf.len;
- return copyUTF16IntoUTF8WithBuffer(buf, Type, utf16, trimmed, out_len);
+ return copyUTF16IntoUTF8WithBuffer(buf, Type, utf16, trimmed, out_len, allow_partial_write);
}
}
- return copyUTF16IntoUTF8WithBuffer(buf, Type, utf16, utf16, utf16.len);
+ return copyUTF16IntoUTF8WithBuffer(buf, Type, utf16, utf16, utf16.len, allow_partial_write);
}
-pub fn copyUTF16IntoUTF8WithBuffer(buf: []u8, comptime Type: type, utf16: Type, trimmed: Type, out_len: usize) EncodeIntoResult {
+pub fn copyUTF16IntoUTF8WithBuffer(buf: []u8, comptime Type: type, utf16: Type, trimmed: Type, out_len: usize, comptime allow_partial_write: bool) EncodeIntoResult {
var remaining = buf;
var utf16_remaining = utf16;
var ended_on_non_ascii = false;
@@ -2604,7 +2604,7 @@ pub fn copyUTF16IntoUTF8WithBuffer(buf: []u8, comptime Type: type, utf16: Type,
const width: usize = replacement.utf8Width();
if (width > remaining.len) {
ended_on_non_ascii = width > 1;
- switch (width) {
+ if (comptime allow_partial_write) switch (width) {
2 => {
if (remaining.len > 0) {
//only first will be written
@@ -2650,7 +2650,7 @@ pub fn copyUTF16IntoUTF8WithBuffer(buf: []u8, comptime Type: type, utf16: Type,
},
else => {},
- }
+ };
break;
}
@@ -3257,8 +3257,9 @@ pub fn indexOfNotChar(slice: []const u8, char: u8) ?u32 {
return null;
}
+const invalid_char: u8 = 0xff;
const hex_table: [255]u8 = brk: {
- var values: [255]u8 = [_]u8{0} ** 255;
+ var values: [255]u8 = [_]u8{invalid_char} ** 255;
values['0'] = 0;
values['1'] = 1;
values['2'] = 2;
@@ -3285,22 +3286,41 @@ const hex_table: [255]u8 = brk: {
break :brk values;
};
-pub fn decodeHexToBytes(destination: []u8, comptime Char: type, source: []const Char) usize {
+pub fn decodeHexToBytes(destination: []u8, comptime Char: type, source: []const Char) !usize {
+ return _decodeHexToBytes(destination, Char, source, false);
+}
+
+pub fn decodeHexToBytesTruncate(destination: []u8, comptime Char: type, source: []const Char) usize {
+ return _decodeHexToBytes(destination, Char, source, true) catch 0;
+}
+
+inline fn _decodeHexToBytes(destination: []u8, comptime Char: type, source: []const Char, comptime truncate: bool) !usize {
var remain = destination;
var input = source;
- while (input.len > 1 and remain.len > 0) {
+ while (remain.len > 0 and input.len > 1) {
const int = input[0..2].*;
+ if (comptime @sizeOf(Char) > 1) {
+ if (int[0] > std.math.maxInt(u8) or int[1] > std.math.maxInt(u8)) {
+ if (comptime truncate) break;
+ return error.InvalidByteSequence;
+ }
+ }
const a = hex_table[@truncate(u8, int[0])];
const b = hex_table[@truncate(u8, int[1])];
- if (a == 255 or b == 255) {
- break;
+ if (a == invalid_char or b == invalid_char) {
+ if (comptime truncate) break;
+ return error.InvalidByteSequence;
}
remain[0] = a << 4 | b;
remain = remain[1..];
input = input[2..];
}
+ if (comptime !truncate) {
+ if (remain.len > 0 and input.len > 0) return error.InvalidByteSequence;
+ }
+
return destination.len - remain.len;
}
@@ -3615,7 +3635,7 @@ pub fn formatUTF16Type(comptime Slice: type, slice_: Slice, writer: anytype) !vo
var slice = slice_;
while (slice.len > 0) {
- const result = strings.copyUTF16IntoUTF8(chunk, Slice, slice);
+ const result = strings.copyUTF16IntoUTF8(chunk, Slice, slice, true);
if (result.read == 0 or result.written == 0)
break;
try writer.writeAll(chunk[0..result.written]);
diff --git a/src/string_mutable.zig b/src/string_mutable.zig
index d7b0cf930..129ea1481 100644
--- a/src/string_mutable.zig
+++ b/src/string_mutable.zig
@@ -327,6 +327,7 @@ pub const MutableString = struct {
this.remain()[0 .. bytes.len * 2],
[]const u16,
bytes,
+ true,
);
this.context.list.items.len += @as(usize, decoded.written);
return pending.len;
@@ -340,6 +341,7 @@ pub const MutableString = struct {
this.remain()[0 .. bytes.len * 2],
[]const u16,
bytes,
+ true,
);
this.pos += @as(usize, decoded.written);
}
diff --git a/test/js/node/buffer.test.js b/test/js/node/buffer.test.js
index 568bf8d44..f0295b08f 100644
--- a/test/js/node/buffer.test.js
+++ b/test/js/node/buffer.test.js
@@ -1,4 +1,5 @@
-import { describe, it, expect, beforeEach, afterEach, test } from "bun:test";
+import { Buffer, SlowBuffer } from "buffer";
+import { describe, it, expect, beforeEach, afterEach } from "bun:test";
import { gc } from "harness";
const BufferModule = await import("buffer");
@@ -6,25 +7,6 @@ const BufferModule = await import("buffer");
beforeEach(() => gc());
afterEach(() => gc());
-function assert(a) {
- expect(a).toBeTruthy();
-}
-
-Object.assign(assert, {
- ok(a) {
- expect(a).toBeTruthy();
- },
- deepStrictEqual(a, b) {
- expect(b).toStrictEqual(a);
- },
- strictEqual(a, b) {
- expect(a).toBe(b);
- },
- throws(a, b) {
- expect(a).toThrow();
- },
-});
-
// https://github.com/oven-sh/bun/issues/2052
it("Buffer global is settable", () => {
var prevBuffer = globalThis.Buffer;
@@ -35,68 +17,72 @@ it("Buffer global is settable", () => {
expect(globalThis.Buffer).toBe(prevBuffer);
});
-it("Buffer.alloc", () => {
+it("length overflow", () => {
// Verify the maximum Uint8Array size. There is no concrete limit by spec. The
// internal limits should be updated if this fails.
- assert.throws(() => new Uint8Array(2 ** 32 + 1), {
- message: "Invalid typed array length: 4294967297",
- });
+ expect(() => new Uint8Array(2 ** 32 + 1)).toThrow(/length/);
+});
+it("truncate input values", () => {
const b = Buffer.allocUnsafe(1024);
- assert.strictEqual(b.length, 1024);
+ expect(b.length).toBe(1024);
b[0] = -1;
- assert.strictEqual(b[0], 255);
+ expect(b[0]).toBe(255);
for (let i = 0; i < 1024; i++) {
- b[i] = i % 256;
+ b[i] = i;
}
for (let i = 0; i < 1024; i++) {
- assert.strictEqual(i % 256, b[i]);
+ expect(i % 256).toBe(b[i]);
}
+});
+it("Buffer.allocUnsafe()", () => {
const c = Buffer.allocUnsafe(512);
- assert.strictEqual(c.length, 512);
+ expect(c.length).toBe(512);
+});
+it("Buffer.from()", () => {
const d = Buffer.from([]);
- assert.strictEqual(d.length, 0);
+ expect(d.length).toBe(0);
+});
- // Test offset properties
- {
- const b = Buffer.alloc(128);
- assert.strictEqual(b.length, 128);
- assert.strictEqual(b.byteOffset, 0);
- assert.strictEqual(b.offset, 0);
- }
+it("offset properties", () => {
+ const b = Buffer.alloc(128);
+ expect(b.length).toBe(128);
+ expect(b.byteOffset).toBe(0);
+ expect(b.offset).toBe(0);
+});
- // Test creating a Buffer from a Uint32Array
- {
- const ui32 = new Uint32Array(4).fill(42);
- const e = Buffer.from(ui32);
- for (const [index, value] of e.entries()) {
- assert.strictEqual(value, ui32[index]);
- }
+it("creating a Buffer from a Uint32Array", () => {
+ const ui32 = new Uint32Array(4).fill(42);
+ const e = Buffer.from(ui32);
+ for (const [index, value] of e.entries()) {
+ expect(value).toBe(ui32[index]);
}
- // Test creating a Buffer from a Uint32Array (old constructor)
- {
- const ui32 = new Uint32Array(4).fill(42);
- const e = Buffer(ui32);
- for (const [key, value] of e.entries()) {
- assert.deepStrictEqual(value, ui32[key]);
- }
+});
+
+it("creating a Buffer from a Uint32Array (old constructor)", () => {
+ const ui32 = new Uint32Array(4).fill(42);
+ const e = Buffer(ui32);
+ for (const [key, value] of e.entries()) {
+ expect(value).toBe(ui32[key]);
}
+});
+it("invalid encoding", () => {
+ const b = Buffer.allocUnsafe(64);
// Test invalid encoding for Buffer.toString
- assert.throws(() => b.toString("invalid"), /Unknown encoding: invalid/);
+ expect(() => b.toString("invalid")).toThrow(/encoding/);
// Invalid encoding for Buffer.write
- assert.throws(() => b.write("test string", 0, 5, "invalid"), /Unknown encoding: invalid/);
+ expect(() => b.write("test string", 0, 5, "invalid")).toThrow(/encoding/);
// Unsupported arguments for Buffer.write
- // assert.throws(() => b.write("test", "utf8", 0), {
- // code: "ERR_INVALID_ARG_TYPE",
- // });
+ expect(() => b.write("test", "utf8", 0)).toThrow(/invalid/i);
+});
- // Try to create 0-length buffers. Should not throw.
+it("create 0-length buffers", () => {
Buffer.from("");
Buffer.from("", "ascii");
Buffer.from("", "latin1");
@@ -107,490 +93,445 @@ it("Buffer.alloc", () => {
new Buffer("", "latin1");
new Buffer("", "binary");
Buffer(0);
+});
- const outOfRangeError = {
- code: "ERR_OUT_OF_RANGE",
- name: "RangeError",
- };
-
+it("write() beyond end of buffer", () => {
+ const b = Buffer.allocUnsafe(64);
// Try to write a 0-length string beyond the end of b
- // assert.throws(() => b.write("", 2048), outOfRangeError);
-
- // // Throw when writing to negative offset
- // assert.throws(() => b.write("a", -1), outOfRangeError);
-
- // // Throw when writing past bounds from the pool
- // assert.throws(() => b.write("a", 2048), outOfRangeError);
-
- // // Throw when writing to negative offset
- // assert.throws(() => b.write("a", -1), outOfRangeError);
+ expect(() => b.write("", 2048)).toThrow(RangeError);
+ // Throw when writing to negative offset
+ expect(() => b.write("a", -1)).toThrow(RangeError);
+ // Throw when writing past bounds from the pool
+ expect(() => b.write("a", 2048)).toThrow(RangeError);
+ // Throw when writing to negative offset
+ expect(() => b.write("a", -1)).toThrow(RangeError);
+ // Offset points to the end of the buffer and does not throw.
+ // (see https://github.com/nodejs/node/issues/8127).
+ Buffer.alloc(1).write("", 1, 0);
+});
+it("copy() beyond end of buffer", () => {
+ const b = Buffer.allocUnsafe(64);
// Try to copy 0 bytes worth of data into an empty buffer
b.copy(Buffer.alloc(0), 0, 0, 0);
-
// Try to copy 0 bytes past the end of the target buffer
b.copy(Buffer.alloc(0), 1, 1, 1);
b.copy(Buffer.alloc(1), 1, 1, 1);
-
// Try to copy 0 bytes from past the end of the source buffer
b.copy(Buffer.alloc(1), 0, 2048, 2048);
+});
- // Testing for smart defaults and ability to pass string values as offset
- {
- const writeTest = Buffer.from("abcdes");
- writeTest.write("n", "ascii");
- assert.throws(() => writeTest.write("o", "1", "ascii"), {
- code: "ERR_INVALID_ARG_TYPE",
- });
- writeTest.write("o", 1, "ascii");
- writeTest.write("d", 2, "ascii");
- writeTest.write("e", 3, "ascii");
- writeTest.write("j", 4, "ascii");
- assert.strictEqual(writeTest.toString(), "nodejs");
- }
-
- // Offset points to the end of the buffer and does not throw.
- // (see https://github.com/nodejs/node/issues/8127).
- Buffer.alloc(1).write("", 1, 0);
-
- // ASCII slice test
- {
- const asciiString = "hello world";
-
- for (let i = 0; i < asciiString.length; i++) {
- b[i] = asciiString.charCodeAt(i);
- }
- const asciiSlice = b.toString("ascii", 0, asciiString.length);
- assert.strictEqual(asciiString, asciiSlice);
- }
-
- {
- const asciiString = "hello world";
- const offset = 100;
+it("smart defaults and ability to pass string values as offset", () => {
+ const writeTest = Buffer.from("abcdes");
+ writeTest.write("n", "ascii");
+ expect(() => writeTest.write("o", "1", "ascii")).toThrow(/offset/);
+ writeTest.write("o", 1, "ascii");
+ writeTest.write("d", 2, "ascii");
+ writeTest.write("e", 3, "ascii");
+ writeTest.write("j", 4, "ascii");
+ expect(writeTest.toString()).toBe("nodejs");
+});
- assert.strictEqual(asciiString.length, b.write(asciiString, offset, "ascii"));
- const asciiSlice = b.toString("ascii", offset, offset + asciiString.length);
- assert.strictEqual(asciiString, asciiSlice);
+it("ASCII slice", () => {
+ const buf = Buffer.allocUnsafe(256);
+ const str = "hello world";
+ for (let i = 0; i < str.length; i++) {
+ buf[i] = str.charCodeAt(i);
}
+ expect(buf.toString("ascii", 0, str.length)).toBe(str);
- {
- const asciiString = "hello world";
- const offset = 100;
+ const offset = 100;
+ expect(buf.write(str, offset, "ascii")).toBe(str.length);
+ expect(buf.toString("ascii", offset, offset + str.length)).toBe(str);
- const sliceA = b.slice(offset, offset + asciiString.length);
- const sliceB = b.slice(offset, offset + asciiString.length);
- for (let i = 0; i < asciiString.length; i++) {
- assert.strictEqual(sliceA[i], sliceB[i]);
- }
+ const slice1 = buf.slice(offset, offset + str.length);
+ const slice2 = buf.slice(offset, offset + str.length);
+ for (let i = 0; i < str.length; i++) {
+ expect(slice1[i]).toBe(slice2[i]);
}
+});
- // UTF-8 slice test
- {
- const utf8String = "¡hέlló wôrld!";
- const offset = 100;
+it("UTF-8 slice", () => {
+ const b = Buffer.allocUnsafe(256);
+ const utf8String = "¡hέlló wôrld!";
+ const offset = 100;
- b.write(utf8String, 0, Buffer.byteLength(utf8String), "utf8");
- let utf8Slice = b.toString("utf8", 0, Buffer.byteLength(utf8String));
- assert.strictEqual(utf8String, utf8Slice);
+ b.write(utf8String, 0, Buffer.byteLength(utf8String), "utf8");
+ expect(b.toString("utf8", 0, Buffer.byteLength(utf8String))).toBe(utf8String);
- assert.strictEqual(Buffer.byteLength(utf8String), b.write(utf8String, offset, "utf8"));
- utf8Slice = b.toString("utf8", offset, offset + Buffer.byteLength(utf8String));
- assert.strictEqual(utf8String, utf8Slice);
+ expect(b.write(utf8String, offset, "utf8")).toBe(Buffer.byteLength(utf8String));
+ expect(b.toString("utf8", offset, offset + Buffer.byteLength(utf8String))).toBe(utf8String);
- const sliceA = b.slice(offset, offset + Buffer.byteLength(utf8String));
- const sliceB = b.slice(offset, offset + Buffer.byteLength(utf8String));
- for (let i = 0; i < Buffer.byteLength(utf8String); i++) {
- assert.strictEqual(sliceA[i], sliceB[i]);
- }
+ const sliceA = b.slice(offset, offset + Buffer.byteLength(utf8String));
+ const sliceB = b.slice(offset, offset + Buffer.byteLength(utf8String));
+ for (let i = 0; i < Buffer.byteLength(utf8String); i++) {
+ expect(sliceA[i]).toBe(sliceB[i]);
}
- {
- const slice = b.slice(100, 150);
- assert.strictEqual(slice.length, 50);
- for (let i = 0; i < 50; i++) {
- assert.strictEqual(b[100 + i], slice[i]);
- }
+ const slice = b.slice(100, 150);
+ expect(slice.length).toBe(50);
+ for (let i = 0; i < 50; i++) {
+ expect(b[100 + i]).toBe(slice[i]);
}
+});
- {
- // Make sure only top level parent propagates from allocPool
- const b = Buffer.allocUnsafe(5);
- const c = b.slice(0, 4);
- const d = c.slice(0, 2);
- assert.strictEqual(b.parent, c.parent);
- assert.strictEqual(b.parent, d.parent);
- }
+it("only top level parent propagates from allocPool", () => {
+ const b = Buffer.allocUnsafe(5);
+ const c = b.slice(0, 4);
+ const d = c.slice(0, 2);
+ expect(b.parent).toBe(c.parent);
+ expect(b.parent).toBe(d.parent);
+});
- {
- // Also from a non-pooled instance
- const b = Buffer.allocUnsafeSlow(5);
- const c = b.slice(0, 4);
- const d = c.slice(0, 2);
- assert.strictEqual(c.parent, d.parent);
- }
+it("only top level parent propagates from a non-pooled instance", () => {
+ const b = Buffer.allocUnsafeSlow(5);
+ const c = b.slice(0, 4);
+ const d = c.slice(0, 2);
+ expect(c.parent).toBe(d.parent);
+});
- {
- // Bug regression test
- const testValue = "\u00F6\u65E5\u672C\u8A9E"; // ö日本語
- const buffer = Buffer.allocUnsafe(32);
- const size = buffer.write(testValue, 0, "utf8");
- const slice = buffer.toString("utf8", 0, size);
- assert.strictEqual(slice, testValue);
- }
+it("UTF-8 write() & slice()", () => {
+ const testValue = "\u00F6\u65E5\u672C\u8A9E"; // ö日本語
+ const buffer = Buffer.allocUnsafe(32);
+ const size = buffer.write(testValue, 0, "utf8");
+ const slice = buffer.toString("utf8", 0, size);
+ expect(slice).toBe(testValue);
+});
- {
- // Test triple slice
- const a = Buffer.allocUnsafe(8);
- for (let i = 0; i < 8; i++) a[i] = i;
- const b = a.slice(4, 8);
- assert.strictEqual(b[0], 4);
- assert.strictEqual(b[1], 5);
- assert.strictEqual(b[2], 6);
- assert.strictEqual(b[3], 7);
- const c = b.slice(2, 4);
- assert.strictEqual(c[0], 6);
- assert.strictEqual(c[1], 7);
- }
+it("triple slice", () => {
+ const a = Buffer.allocUnsafe(8);
+ for (let i = 0; i < 8; i++) a[i] = i;
+ const b = a.slice(4, 8);
+ expect(b[0]).toBe(4);
+ expect(b[1]).toBe(5);
+ expect(b[2]).toBe(6);
+ expect(b[3]).toBe(7);
+ const c = b.slice(2, 4);
+ expect(c[0]).toBe(6);
+ expect(c[1]).toBe(7);
+});
- {
- const d = Buffer.from([23, 42, 255]);
- assert.strictEqual(d.length, 3);
- assert.strictEqual(d[0], 23);
- assert.strictEqual(d[1], 42);
- assert.strictEqual(d[2], 255);
- assert.deepStrictEqual(d, Buffer.from(d));
- }
+it("Buffer.from() with encoding", () => {
+ const b = Buffer.from([23, 42, 255]);
+ expect(b.length).toBe(3);
+ expect(b[0]).toBe(23);
+ expect(b[1]).toBe(42);
+ expect(b[2]).toBe(255);
+ expect(Buffer.from(b)).toStrictEqual(b);
- {
- // Test for proper UTF-8 Encoding
- const e = Buffer.from("über");
- assert.deepStrictEqual(e, Buffer.from([195, 188, 98, 101, 114]));
- }
+ // Test for proper UTF-8 Encoding
+ expect(Buffer.from("über")).toStrictEqual(Buffer.from([195, 188, 98, 101, 114]));
- {
- // Test for proper ascii Encoding, length should be 4
- const f = Buffer.from("über", "ascii");
- assert.deepStrictEqual(f, Buffer.from([252, 98, 101, 114]));
- }
+ // Test for proper ascii Encoding, length should be 4
+ expect(Buffer.from("über", "ascii")).toStrictEqual(Buffer.from([252, 98, 101, 114]));
["ucs2", "ucs-2", "utf16le", "utf-16le"].forEach(encoding => {
- {
- // Test for proper UTF16LE encoding, length should be 8
- const f = Buffer.from("über", encoding);
- assert.deepStrictEqual(f, Buffer.from([252, 0, 98, 0, 101, 0, 114, 0]));
- }
-
- {
- // Length should be 12
- const f = Buffer.from("привет", encoding);
- assert.deepStrictEqual(f, Buffer.from([63, 4, 64, 4, 56, 4, 50, 4, 53, 4, 66, 4]));
- assert.strictEqual(f.toString(encoding), "привет");
- }
-
- {
- const f = Buffer.from([0, 0, 0, 0, 0]);
- assert.strictEqual(f.length, 5);
- const size = f.write("あいうえお", encoding);
- assert.strictEqual(size, 4);
- assert.deepStrictEqual(f, Buffer.from([0x42, 0x30, 0x44, 0x30, 0x00]));
- }
+ // Test for proper UTF16LE encoding, length should be 8
+ expect(Buffer.from("über", encoding)).toStrictEqual(Buffer.from([252, 0, 98, 0, 101, 0, 114, 0]));
+
+ // Length should be 12
+ const b = Buffer.from("привет", encoding);
+ expect(b).toStrictEqual(Buffer.from([63, 4, 64, 4, 56, 4, 50, 4, 53, 4, 66, 4]));
+ expect(b.toString(encoding)).toBe("привет");
+
+ const c = Buffer.from([0, 0, 0, 0, 0]);
+ expect(c.length).toBe(5);
+ expect(c.write("あいうえお", encoding)).toBe(4);
+ expect(c).toStrictEqual(Buffer.from([0x42, 0x30, 0x44, 0x30, 0x00]));
});
- {
- const f = Buffer.from("\uD83D\uDC4D", "utf-16le"); // THUMBS UP SIGN (U+1F44D)
- assert.strictEqual(f.length, 4);
- assert.deepStrictEqual(f, Buffer.from("3DD84DDC", "hex"));
- }
+ const c = Buffer.from("\uD83D\uDC4D", "utf-16le"); // THUMBS UP SIGN (U+1F44D)
+ expect(c.length).toBe(4);
+ expect(c).toStrictEqual(Buffer.from("3DD84DDC", "hex"));
+});
- // Test construction from arrayish object
- {
- const arrayIsh = { 0: 0, 1: 1, 2: 2, 3: 3, length: 4 };
- let g = Buffer.from(arrayIsh);
- assert.deepStrictEqual(g, Buffer.from([0, 1, 2, 3]));
- const strArrayIsh = { 0: "0", 1: "1", 2: "2", 3: "3", length: 4 };
- g = Buffer.from(strArrayIsh);
- assert.deepStrictEqual(g, Buffer.from([0, 1, 2, 3]));
- }
+it("construction from arrayish object", () => {
+ const arrayIsh = { 0: 0, 1: 1, 2: 2, 3: 3, length: 4 };
+ expect(Buffer.from(arrayIsh)).toStrictEqual(Buffer.from([0, 1, 2, 3]));
+ const strArrayIsh = { 0: "0", 1: "1", 2: "2", 3: "3", length: 4 };
+ expect(Buffer.from(strArrayIsh)).toStrictEqual(Buffer.from([0, 1, 2, 3]));
+});
- //
- // Test toString('base64')
- //
- assert.strictEqual(Buffer.from("Man").toString("base64"), "TWFu");
- assert.strictEqual(Buffer.from("Woman").toString("base64"), "V29tYW4=");
+it("toString('base64')", () => {
+ expect(Buffer.from("Man").toString("base64")).toBe("TWFu");
+ expect(Buffer.from("Woman").toString("base64")).toBe("V29tYW4=");
+});
- //
- // Test toString('base64url')
- //
- assert.strictEqual(Buffer.from("Man").toString("base64url"), "TWFu");
- assert.strictEqual(Buffer.from("Woman").toString("base64url"), "V29tYW4");
+it("toString('base64url')", () => {
+ expect(Buffer.from("Man").toString("base64url")).toBe("TWFu");
+ expect(Buffer.from("Woman").toString("base64url")).toBe("V29tYW4");
+});
- {
- // Test that regular and URL-safe base64 both work both ways
- const expected = [0xff, 0xff, 0xbe, 0xff, 0xef, 0xbf, 0xfb, 0xef, 0xff];
- assert.deepStrictEqual(Buffer.from("//++/++/++//", "base64"), Buffer.from(expected));
- assert.deepStrictEqual(Buffer.from("__--_--_--__", "base64"), Buffer.from(expected));
- assert.deepStrictEqual(Buffer.from("//++/++/++//", "base64url"), Buffer.from(expected));
- assert.deepStrictEqual(Buffer.from("__--_--_--__", "base64url"), Buffer.from(expected));
- }
+it("regular and URL-safe base64 work both ways", () => {
+ const expected = [0xff, 0xff, 0xbe, 0xff, 0xef, 0xbf, 0xfb, 0xef, 0xff];
+ expect(Buffer.from("//++/++/++//", "base64")).toStrictEqual(Buffer.from(expected));
+ expect(Buffer.from("__--_--_--__", "base64")).toStrictEqual(Buffer.from(expected));
+ expect(Buffer.from("//++/++/++//", "base64url")).toStrictEqual(Buffer.from(expected));
+ expect(Buffer.from("__--_--_--__", "base64url")).toStrictEqual(Buffer.from(expected));
+});
- const base64flavors = ["base64", "base64url"];
+it("regular and URL-safe base64 work both ways with padding", () => {
+ const expected = [0xff, 0xff, 0xbe, 0xff, 0xef, 0xbf, 0xfb, 0xef, 0xff, 0xfb];
+ expect(Buffer.from("//++/++/++//+w==", "base64")).toStrictEqual(Buffer.from(expected));
+ expect(Buffer.from("//++/++/++//+w==", "base64")).toStrictEqual(Buffer.from(expected));
+ expect(Buffer.from("//++/++/++//+w==", "base64url")).toStrictEqual(Buffer.from(expected));
+ expect(Buffer.from("//++/++/++//+w==", "base64url")).toStrictEqual(Buffer.from(expected));
+});
- {
- // Test that regular and URL-safe base64 both work both ways with padding
- const expected = [0xff, 0xff, 0xbe, 0xff, 0xef, 0xbf, 0xfb, 0xef, 0xff, 0xfb];
- assert.deepStrictEqual(Buffer.from("//++/++/++//+w==", "base64"), Buffer.from(expected));
- assert.deepStrictEqual(Buffer.from("//++/++/++//+w==", "base64"), Buffer.from(expected));
- assert.deepStrictEqual(Buffer.from("//++/++/++//+w==", "base64url"), Buffer.from(expected));
- assert.deepStrictEqual(Buffer.from("//++/++/++//+w==", "base64url"), Buffer.from(expected));
- }
+it("big example (base64 & base64url)", () => {
+ const quote =
+ "Man is distinguished, not only by his reason, but by this " +
+ "singular passion from other animals, which is a lust " +
+ "of the mind, that by a perseverance of delight in the " +
+ "continued and indefatigable generation of knowledge, " +
+ "exceeds the short vehemence of any carnal pleasure.";
+ const expected =
+ "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb" +
+ "24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlci" +
+ "BhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQ" +
+ "gYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu" +
+ "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZ" +
+ "GdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm" +
+ "5hbCBwbGVhc3VyZS4=";
+
+ expect(Buffer.from(quote).toString("base64")).toBe(expected);
+ expect(Buffer.from(quote).toString("base64url")).toBe(
+ expected.replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", ""),
+ );
+});
- {
- // big example
- const quote =
- "Man is distinguished, not only by his reason, but by this " +
- "singular passion from other animals, which is a lust " +
- "of the mind, that by a perseverance of delight in the " +
- "continued and indefatigable generation of knowledge, " +
- "exceeds the short vehemence of any carnal pleasure.";
- const expected =
- "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb" +
- "24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlci" +
- "BhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQ" +
- "gYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu" +
- "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZ" +
- "GdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm" +
- "5hbCBwbGVhc3VyZS4=";
- assert.strictEqual(Buffer.from(quote).toString("base64"), expected);
- assert.strictEqual(
- Buffer.from(quote).toString("base64url"),
- expected.replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", ""),
- );
+function forEachBase64(label, test) {
+ ["base64", "base64url"].forEach(encoding => it(`${label} (${encoding})`, test.bind(null, encoding)));
+}
- base64flavors.forEach(encoding => {
- let b = Buffer.allocUnsafe(1024);
- let bytesWritten = b.write(expected, 0, encoding);
- assert.strictEqual(quote.length, bytesWritten);
- assert.strictEqual(quote, b.toString("ascii", 0, quote.length));
-
- // Check that the base64 decoder ignores whitespace
- const expectedWhite =
- `${expected.slice(0, 60)} \n` +
- `${expected.slice(60, 120)} \n` +
- `${expected.slice(120, 180)} \n` +
- `${expected.slice(180, 240)} \n` +
- `${expected.slice(240, 300)}\n` +
- `${expected.slice(300, 360)}\n`;
- b = Buffer.allocUnsafe(1024);
- bytesWritten = b.write(expectedWhite, 0, encoding);
- assert.strictEqual(quote.length, bytesWritten);
- assert.strictEqual(quote, b.toString("ascii", 0, quote.length));
-
- // Check that the base64 decoder on the constructor works
- // even in the presence of whitespace.
- b = Buffer.from(expectedWhite, encoding);
- assert.strictEqual(quote.length, b.length);
- assert.strictEqual(quote, b.toString("ascii", 0, quote.length));
-
- // Check that the base64 decoder ignores illegal chars
- const expectedIllegal =
- expected.slice(0, 60) +
- " \x80" +
- expected.slice(60, 120) +
- " \xff" +
- expected.slice(120, 180) +
- " \x00" +
- expected.slice(180, 240) +
- " \x98" +
- expected.slice(240, 300) +
- "\x03" +
- expected.slice(300, 360);
- b = Buffer.from(expectedIllegal, encoding);
- assert.strictEqual(quote.length, b.length);
- assert.strictEqual(quote, b.toString("ascii", 0, quote.length));
- });
- }
+forEachBase64("big example", encoding => {
+ const quote =
+ "Man is distinguished, not only by his reason, but by this " +
+ "singular passion from other animals, which is a lust " +
+ "of the mind, that by a perseverance of delight in the " +
+ "continued and indefatigable generation of knowledge, " +
+ "exceeds the short vehemence of any carnal pleasure.";
+ const expected =
+ "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb" +
+ "24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlci" +
+ "BhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQ" +
+ "gYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu" +
+ "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZ" +
+ "GdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm" +
+ "5hbCBwbGVhc3VyZS4=";
- base64flavors.forEach(encoding => {
- assert.strictEqual(Buffer.from("", encoding).toString(), "");
- assert.strictEqual(Buffer.from("K", encoding).toString(), "");
-
- // multiple-of-4 with padding
- assert.strictEqual(Buffer.from("Kg==", encoding).toString(), "*");
- assert.strictEqual(Buffer.from("Kio=", encoding).toString(), "*".repeat(2));
- assert.strictEqual(Buffer.from("Kioq", encoding).toString(), "*".repeat(3));
- assert.strictEqual(Buffer.from("KioqKg==", encoding).toString(), "*".repeat(4));
- assert.strictEqual(Buffer.from("KioqKio=", encoding).toString(), "*".repeat(5));
- assert.strictEqual(Buffer.from("KioqKioq", encoding).toString(), "*".repeat(6));
- assert.strictEqual(Buffer.from("KioqKioqKg==", encoding).toString(), "*".repeat(7));
- assert.strictEqual(Buffer.from("KioqKioqKio=", encoding).toString(), "*".repeat(8));
- assert.strictEqual(Buffer.from("KioqKioqKioq", encoding).toString(), "*".repeat(9));
- assert.strictEqual(Buffer.from("KioqKioqKioqKg==", encoding).toString(), "*".repeat(10));
- assert.strictEqual(Buffer.from("KioqKioqKioqKio=", encoding).toString(), "*".repeat(11));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioq", encoding).toString(), "*".repeat(12));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKg==", encoding).toString(), "*".repeat(13));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKio=", encoding).toString(), "*".repeat(14));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKioq", encoding).toString(), "*".repeat(15));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKioqKg==", encoding).toString(), "*".repeat(16));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKioqKio=", encoding).toString(), "*".repeat(17));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKioqKioq", encoding).toString(), "*".repeat(18));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKioqKioqKg==", encoding).toString(), "*".repeat(19));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKioqKioqKio=", encoding).toString(), "*".repeat(20));
-
- // No padding, not a multiple of 4
- assert.strictEqual(Buffer.from("Kg", encoding).toString(), "*");
- assert.strictEqual(Buffer.from("Kio", encoding).toString(), "*".repeat(2));
- assert.strictEqual(Buffer.from("KioqKg", encoding).toString(), "*".repeat(4));
- assert.strictEqual(Buffer.from("KioqKio", encoding).toString(), "*".repeat(5));
- assert.strictEqual(Buffer.from("KioqKioqKg", encoding).toString(), "*".repeat(7));
- assert.strictEqual(Buffer.from("KioqKioqKio", encoding).toString(), "*".repeat(8));
- assert.strictEqual(Buffer.from("KioqKioqKioqKg", encoding).toString(), "*".repeat(10));
- assert.strictEqual(Buffer.from("KioqKioqKioqKio", encoding).toString(), "*".repeat(11));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKg", encoding).toString(), "*".repeat(13));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKio", encoding).toString(), "*".repeat(14));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKioqKg", encoding).toString(), "*".repeat(16));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKioqKio", encoding).toString(), "*".repeat(17));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKioqKioqKg", encoding).toString(), "*".repeat(19));
- assert.strictEqual(Buffer.from("KioqKioqKioqKioqKioqKioqKio", encoding).toString(), "*".repeat(20));
- });
+ const b = Buffer.allocUnsafe(1024);
+ expect(b.write(expected, 0, encoding)).toBe(quote.length);
+ expect(b.toString("ascii", 0, quote.length)).toBe(quote);
+
+ // Check that the base64 decoder ignores whitespace
+ const white =
+ `${expected.slice(0, 60)} \n` +
+ `${expected.slice(60, 120)} \n` +
+ `${expected.slice(120, 180)} \n` +
+ `${expected.slice(180, 240)} \n` +
+ `${expected.slice(240, 300)}\n` +
+ `${expected.slice(300, 360)}\n`;
+ const c = Buffer.allocUnsafe(1024);
+ expect(c.write(white, 0, encoding)).toBe(quote.length);
+ expect(c.toString("ascii", 0, quote.length)).toBe(quote);
+
+ // Check that the base64 decoder on the constructor works
+ // even in the presence of whitespace.
+ const d = Buffer.from(white, encoding);
+ expect(d.length).toBe(quote.length);
+ expect(d.toString("ascii", 0, quote.length)).toBe(quote);
+
+ // Check that the base64 decoder ignores illegal chars
+ const illegal =
+ expected.slice(0, 60) +
+ " \x80" +
+ expected.slice(60, 120) +
+ " \xff" +
+ expected.slice(120, 180) +
+ " \x00" +
+ expected.slice(180, 240) +
+ " \x98" +
+ expected.slice(240, 300) +
+ "\x03" +
+ expected.slice(300, 360);
+ const e = Buffer.from(illegal, encoding);
+ expect(e.length).toBe(quote.length);
+ expect(e.toString("ascii", 0, quote.length)).toBe(quote);
+});
+forEachBase64("padding", encoding => {
+ expect(Buffer.from("", encoding).toString()).toBe("");
+ expect(Buffer.from("K", encoding).toString()).toBe("");
+ // multiple-of-4 with padding
+ expect(Buffer.from("Kg==", encoding).toString()).toBe("*");
+ expect(Buffer.from("Kio=", encoding).toString()).toBe("*".repeat(2));
+ expect(Buffer.from("Kioq", encoding).toString()).toBe("*".repeat(3));
+ expect(Buffer.from("KioqKg==", encoding).toString()).toBe("*".repeat(4));
+ expect(Buffer.from("KioqKio=", encoding).toString()).toBe("*".repeat(5));
+ expect(Buffer.from("KioqKioq", encoding).toString()).toBe("*".repeat(6));
+ expect(Buffer.from("KioqKioqKg==", encoding).toString()).toBe("*".repeat(7));
+ expect(Buffer.from("KioqKioqKio=", encoding).toString()).toBe("*".repeat(8));
+ expect(Buffer.from("KioqKioqKioq", encoding).toString()).toBe("*".repeat(9));
+ expect(Buffer.from("KioqKioqKioqKg==", encoding).toString()).toBe("*".repeat(10));
+ expect(Buffer.from("KioqKioqKioqKio=", encoding).toString()).toBe("*".repeat(11));
+ expect(Buffer.from("KioqKioqKioqKioq", encoding).toString()).toBe("*".repeat(12));
+ expect(Buffer.from("KioqKioqKioqKioqKg==", encoding).toString()).toBe("*".repeat(13));
+ expect(Buffer.from("KioqKioqKioqKioqKio=", encoding).toString()).toBe("*".repeat(14));
+ expect(Buffer.from("KioqKioqKioqKioqKioq", encoding).toString()).toBe("*".repeat(15));
+ expect(Buffer.from("KioqKioqKioqKioqKioqKg==", encoding).toString()).toBe("*".repeat(16));
+ expect(Buffer.from("KioqKioqKioqKioqKioqKio=", encoding).toString()).toBe("*".repeat(17));
+ expect(Buffer.from("KioqKioqKioqKioqKioqKioq", encoding).toString()).toBe("*".repeat(18));
+ expect(Buffer.from("KioqKioqKioqKioqKioqKioqKg==", encoding).toString()).toBe("*".repeat(19));
+ expect(Buffer.from("KioqKioqKioqKioqKioqKioqKio=", encoding).toString()).toBe("*".repeat(20));
+ // No padding, not a multiple of 4
+ expect(Buffer.from("Kg", encoding).toString()).toBe("*");
+ expect(Buffer.from("Kio", encoding).toString()).toBe("*".repeat(2));
+ expect(Buffer.from("KioqKg", encoding).toString()).toBe("*".repeat(4));
+ expect(Buffer.from("KioqKio", encoding).toString()).toBe("*".repeat(5));
+ expect(Buffer.from("KioqKioqKg", encoding).toString()).toBe("*".repeat(7));
+ expect(Buffer.from("KioqKioqKio", encoding).toString()).toBe("*".repeat(8));
+ expect(Buffer.from("KioqKioqKioqKg", encoding).toString()).toBe("*".repeat(10));
+ expect(Buffer.from("KioqKioqKioqKio", encoding).toString()).toBe("*".repeat(11));
+ expect(Buffer.from("KioqKioqKioqKioqKg", encoding).toString()).toBe("*".repeat(13));
+ expect(Buffer.from("KioqKioqKioqKioqKio", encoding).toString()).toBe("*".repeat(14));
+ expect(Buffer.from("KioqKioqKioqKioqKioqKg", encoding).toString()).toBe("*".repeat(16));
+ expect(Buffer.from("KioqKioqKioqKioqKioqKio", encoding).toString()).toBe("*".repeat(17));
+ expect(Buffer.from("KioqKioqKioqKioqKioqKioqKg", encoding).toString()).toBe("*".repeat(19));
+ expect(Buffer.from("KioqKioqKioqKioqKioqKioqKio", encoding).toString()).toBe("*".repeat(20));
// Handle padding graciously, multiple-of-4 or not
- assert.strictEqual(Buffer.from("72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw==", "base64").length, 32);
- assert.strictEqual(Buffer.from("72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw==", "base64url").length, 32);
- assert.strictEqual(Buffer.from("72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw=", "base64").length, 32);
- assert.strictEqual(Buffer.from("72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw=", "base64url").length, 32);
- assert.strictEqual(Buffer.from("72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw", "base64").length, 32);
- assert.strictEqual(Buffer.from("72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw", "base64url").length, 32);
- assert.strictEqual(Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==", "base64").length, 31);
- assert.strictEqual(Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==", "base64url").length, 31);
- assert.strictEqual(Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=", "base64").length, 31);
- assert.strictEqual(Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=", "base64url").length, 31);
- assert.strictEqual(Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg", "base64").length, 31);
- assert.strictEqual(Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg", "base64url").length, 31);
+ expect(Buffer.from("72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw==", encoding).length).toBe(32);
+ expect(Buffer.from("72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw==", encoding).length).toBe(32);
+ expect(Buffer.from("72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw=", encoding).length).toBe(32);
+ expect(Buffer.from("72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw=", encoding).length).toBe(32);
+ expect(Buffer.from("72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw", encoding).length).toBe(32);
+ expect(Buffer.from("72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw", encoding).length).toBe(32);
+ expect(Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==", encoding).length).toBe(31);
+ expect(Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=", encoding).length).toBe(31);
+ expect(Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg", encoding).length).toBe(31);
+});
- {
- // This string encodes single '.' character in UTF-16
- const dot = Buffer.from("//4uAA==", "base64");
- assert.strictEqual(dot[0], 0xff);
- assert.strictEqual(dot[1], 0xfe);
- assert.strictEqual(dot[2], 0x2e);
- assert.strictEqual(dot[3], 0x00);
- assert.strictEqual(dot.toString("base64"), "//4uAA==");
- }
+it("encodes single '.' character in UTF-16", () => {
+ const padded = Buffer.from("//4uAA==", "base64");
+ expect(padded[0]).toBe(0xff);
+ expect(padded[1]).toBe(0xfe);
+ expect(padded[2]).toBe(0x2e);
+ expect(padded[3]).toBe(0x00);
+ expect(padded.toString("base64")).toBe("//4uAA==");
+
+ const dot = Buffer.from("//4uAA", "base64url");
+ expect(dot[0]).toBe(0xff);
+ expect(dot[1]).toBe(0xfe);
+ expect(dot[2]).toBe(0x2e);
+ expect(dot[3]).toBe(0x00);
+ expect(dot.toString("base64url")).toBe("__4uAA");
+});
- {
- // This string encodes single '.' character in UTF-16
- const dot = Buffer.from("//4uAA", "base64url");
- assert.strictEqual(dot[0], 0xff);
- assert.strictEqual(dot[1], 0xfe);
- assert.strictEqual(dot[2], 0x2e);
- assert.strictEqual(dot[3], 0x00);
- assert.strictEqual(dot.toString("base64url"), "__4uAA");
- }
+// https://github.com/joyent/node/issues/402
+it("writing base64 at a position > 0 should not mangle the result", () => {
+ const segments = ["TWFkbmVzcz8h", "IFRoaXM=", "IGlz", "IG5vZGUuanMh"];
+ const b = Buffer.allocUnsafe(64);
+ let pos = 0;
- {
- // Writing base64 at a position > 0 should not mangle the result.
- //
- // https://github.com/joyent/node/issues/402
- const segments = ["TWFkbmVzcz8h", "IFRoaXM=", "IGlz", "IG5vZGUuanMh"];
- const b = Buffer.allocUnsafe(64);
- let pos = 0;
-
- for (let i = 0; i < segments.length; ++i) {
- pos += b.write(segments[i], pos, "base64");
- }
- assert.strictEqual(b.toString("latin1", 0, pos), "Madness?! This is node.js!");
+ for (let i = 0; i < segments.length; ++i) {
+ pos += b.write(segments[i], pos, "base64");
}
+ expect(b.toString("latin1", 0, pos)).toBe("Madness?! This is node.js!");
+});
- {
- // Writing base64url at a position > 0 should not mangle the result.
- //
- // https://github.com/joyent/node/issues/402
- const segments = ["TWFkbmVzcz8h", "IFRoaXM", "IGlz", "IG5vZGUuanMh"];
- const b = Buffer.allocUnsafe(64);
- let pos = 0;
-
- for (let i = 0; i < segments.length; ++i) {
- pos += b.write(segments[i], pos, "base64url");
- }
- assert.strictEqual(b.toString("latin1", 0, pos), "Madness?! This is node.js!");
+// https://github.com/joyent/node/issues/402
+it("writing base64url at a position > 0 should not mangle the result", () => {
+ const segments = ["TWFkbmVzcz8h", "IFRoaXM", "IGlz", "IG5vZGUuanMh"];
+ const b = Buffer.allocUnsafe(64);
+ let pos = 0;
+
+ for (let i = 0; i < segments.length; ++i) {
+ pos += b.write(segments[i], pos, "base64url");
}
+ expect(b.toString("latin1", 0, pos)).toBe("Madness?! This is node.js!");
+});
+it("regression tests from Node.js", () => {
// Regression test for https://github.com/nodejs/node/issues/3496.
- assert.strictEqual(Buffer.from("=bad".repeat(1e4), "base64").length, 0);
-
+ expect(Buffer.from("=bad".repeat(1e4), "base64").length).toBe(0);
// Regression test for https://github.com/nodejs/node/issues/11987.
- assert.deepStrictEqual(Buffer.from("w0 ", "base64"), Buffer.from("w0", "base64"));
-
+ expect(Buffer.from("w0 ", "base64")).toStrictEqual(Buffer.from("w0", "base64"));
// Regression test for https://github.com/nodejs/node/issues/13657.
- assert.deepStrictEqual(Buffer.from(" YWJvcnVtLg", "base64"), Buffer.from("YWJvcnVtLg", "base64"));
-
- {
- // Creating buffers larger than pool size.
- const l = Buffer.poolSize + 5;
- const s = "h".repeat(l);
- const b = Buffer.from(s);
+ expect(Buffer.from(" YWJvcnVtLg", "base64")).toStrictEqual(Buffer.from("YWJvcnVtLg", "base64"));
+ // issue GH-3416
+ Buffer.from(Buffer.allocUnsafe(0), 0, 0);
+ // Regression test for https://github.com/nodejs/node-v0.x-archive/issues/5482:
+ // should throw but not assert in C++ land.
+ expect(() => Buffer.from("", "buffer")).toThrow(/encoding/);
+});
- for (let i = 0; i < l; i++) {
- assert.strictEqual(b[i], "h".charCodeAt(0));
- }
+it("creating buffers larger than pool size", () => {
+ const l = Buffer.poolSize + 5;
+ const s = "h".repeat(l);
+ const b = Buffer.from(s);
- const sb = b.toString();
- assert.strictEqual(sb.length, s.length);
- assert.strictEqual(sb, s);
+ for (let i = 0; i < l; i++) {
+ expect(b[i]).toBe("h".charCodeAt(0));
}
- {
- // test hex toString
- const hexb = Buffer.allocUnsafe(256);
- for (let i = 0; i < 256; i++) {
- hexb[i] = i;
- }
- const hexStr = hexb.toString("hex");
- assert.strictEqual(
- hexStr,
- "000102030405060708090a0b0c0d0e0f" +
- "101112131415161718191a1b1c1d1e1f" +
- "202122232425262728292a2b2c2d2e2f" +
- "303132333435363738393a3b3c3d3e3f" +
- "404142434445464748494a4b4c4d4e4f" +
- "505152535455565758595a5b5c5d5e5f" +
- "606162636465666768696a6b6c6d6e6f" +
- "707172737475767778797a7b7c7d7e7f" +
- "808182838485868788898a8b8c8d8e8f" +
- "909192939495969798999a9b9c9d9e9f" +
- "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" +
- "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" +
- "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" +
- "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" +
- "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" +
- "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
- );
+ const sb = b.toString();
+ expect(sb.length).toBe(s.length);
+ expect(sb).toBe(s);
+});
- const hexb2 = Buffer.from(hexStr, "hex");
- for (let i = 0; i < 256; i++) {
- assert.strictEqual(hexb2[i], hexb[i]);
- }
+it("hex toString()", () => {
+ const hexb = Buffer.allocUnsafe(256);
+ for (let i = 0; i < 256; i++) {
+ hexb[i] = i;
+ }
+ const hexStr = hexb.toString("hex");
+ expect(hexStr).toBe(
+ "000102030405060708090a0b0c0d0e0f" +
+ "101112131415161718191a1b1c1d1e1f" +
+ "202122232425262728292a2b2c2d2e2f" +
+ "303132333435363738393a3b3c3d3e3f" +
+ "404142434445464748494a4b4c4d4e4f" +
+ "505152535455565758595a5b5c5d5e5f" +
+ "606162636465666768696a6b6c6d6e6f" +
+ "707172737475767778797a7b7c7d7e7f" +
+ "808182838485868788898a8b8c8d8e8f" +
+ "909192939495969798999a9b9c9d9e9f" +
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" +
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" +
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" +
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" +
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" +
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ );
+
+ const hexb2 = Buffer.from(hexStr, "hex");
+ for (let i = 0; i < 256; i++) {
+ expect(hexb2[i]).toBe(hexb[i]);
}
+});
- // Test single hex character is discarded.
- assert.strictEqual(Buffer.from("A", "hex").length, 0);
+it("single hex character is discarded", () => {
+ expect(Buffer.from("A", "hex").length).toBe(0);
+});
- // Test that if a trailing character is discarded, rest of string is processed.
- assert.deepStrictEqual(Buffer.from("Abx", "hex"), Buffer.from("Ab", "hex"));
+it("if a trailing character is discarded, rest of string is processed", () => {
+ expect(Buffer.from("Abx", "hex")).toEqual(Buffer.from("Ab", "hex"));
+});
- // Test single base64 char encodes as 0.
- assert.strictEqual(Buffer.from("A", "base64").length, 0);
+it("single base64 char encodes as 0", () => {
+ expect(Buffer.from("A", "base64").length).toBe(0);
+});
- {
- // Test an invalid slice end.
- const b = Buffer.from([1, 2, 3, 4, 5]);
- const b2 = b.toString("hex", 1, 10000);
- const b3 = b.toString("hex", 1, 5);
- const b4 = b.toString("hex", 1);
- assert.strictEqual(b2, b3);
- assert.strictEqual(b2, b4);
- }
+it("invalid slice end", () => {
+ const b = Buffer.from([1, 2, 3, 4, 5]);
+ const b2 = b.toString("hex", 1, 10000);
+ const b3 = b.toString("hex", 1, 5);
+ const b4 = b.toString("hex", 1);
+ expect(b2).toBe(b3);
+ expect(b2).toBe(b4);
+});
+it("slice()", () => {
function buildBuffer(data) {
if (Array.isArray(data)) {
const buffer = Buffer.allocUnsafe(data.length);
@@ -601,522 +542,419 @@ it("Buffer.alloc", () => {
}
const x = buildBuffer([0x81, 0xa3, 0x66, 0x6f, 0x6f, 0xa3, 0x62, 0x61, 0x72]);
+ expect(x).toStrictEqual(Buffer.from([0x81, 0xa3, 0x66, 0x6f, 0x6f, 0xa3, 0x62, 0x61, 0x72]));
+
+ const a = x.slice(4);
+ expect(a.length).toBe(5);
+ expect(a[0]).toBe(0x6f);
+ expect(a[1]).toBe(0xa3);
+ expect(a[2]).toBe(0x62);
+ expect(a[3]).toBe(0x61);
+ expect(a[4]).toBe(0x72);
+
+ const b = x.slice(0);
+ expect(b.length).toBe(x.length);
+
+ const c = x.slice(0, 4);
+ expect(c.length).toBe(4);
+ expect(c[0]).toBe(0x81);
+ expect(c[1]).toBe(0xa3);
+
+ const d = x.slice(0, 9);
+ expect(d.length).toBe(9);
+
+ const e = x.slice(1, 4);
+ expect(e.length).toBe(3);
+ expect(e[0]).toBe(0xa3);
+
+ const f = x.slice(2, 4);
+ expect(f.length).toBe(2);
+ expect(f[0]).toBe(0x66);
+ expect(f[1]).toBe(0x6f);
+});
- // assert.strictEqual(x.inspect(), "<Buffer 81 a3 66 6f 6f a3 62 61 72>");
+function forEachUnicode(label, test) {
+ ["ucs2", "ucs-2", "utf16le", "utf-16le"].forEach(encoding => it(`${label} (${encoding})`, test.bind(null, encoding)));
+}
- {
- const z = x.slice(4);
- assert.strictEqual(z.length, 5);
- assert.strictEqual(z[0], 0x6f);
- assert.strictEqual(z[1], 0xa3);
- assert.strictEqual(z[2], 0x62);
- assert.strictEqual(z[3], 0x61);
- assert.strictEqual(z[4], 0x72);
- }
+forEachUnicode("write()", encoding => {
+ const b = Buffer.allocUnsafe(10);
+ b.write("あいうえお", encoding);
+ expect(b.toString(encoding)).toBe("あいうえお");
+});
- {
- const z = x.slice(0);
- assert.strictEqual(z.length, x.length);
- }
+forEachUnicode("write() with offset", encoding => {
+ const b = Buffer.allocUnsafe(11);
+ b.write("あいうえお", 1, encoding);
+ expect(b.toString(encoding, 1)).toBe("あいうえお");
+});
- {
- const z = x.slice(0, 4);
- assert.strictEqual(z.length, 4);
- assert.strictEqual(z[0], 0x81);
- assert.strictEqual(z[1], 0xa3);
- }
+it("latin1 encoding should write only one byte per character", () => {
+ const b = Buffer.from([0xde, 0xad, 0xbe, 0xef]);
+ b.write(String.fromCharCode(0xffff), 0, "latin1");
+ expect(b[0]).toBe(0xff);
+ expect(b[1]).toBe(0xad);
+ expect(b[2]).toBe(0xbe);
+ expect(b[3]).toBe(0xef);
+ b.write(String.fromCharCode(0xaaee), 0, "latin1");
+ expect(b[0]).toBe(0xee);
+ expect(b[1]).toBe(0xad);
+ expect(b[2]).toBe(0xbe);
+ expect(b[3]).toBe(0xef);
+});
- {
- const z = x.slice(0, 9);
- assert.strictEqual(z.length, 9);
- }
+it("binary encoding should write only one byte per character", () => {
+ const b = Buffer.from([0xde, 0xad, 0xbe, 0xef]);
+ b.write(String.fromCharCode(0xffff), 0, "latin1");
+ expect(b[0]).toBe(0xff);
+ expect(b[1]).toBe(0xad);
+ expect(b[2]).toBe(0xbe);
+ expect(b[3]).toBe(0xef);
+ b.write(String.fromCharCode(0xaaee), 0, "latin1");
+ expect(b[0]).toBe(0xee);
+ expect(b[1]).toBe(0xad);
+ expect(b[2]).toBe(0xbe);
+ expect(b[3]).toBe(0xef);
+});
- {
- const z = x.slice(1, 4);
- assert.strictEqual(z.length, 3);
- assert.strictEqual(z[0], 0xa3);
- }
+it("UTF-8 string includes null character", () => {
+ // https://github.com/nodejs/node-v0.x-archive/pull/1210
+ expect(Buffer.from("\0").length).toBe(1);
+ expect(Buffer.from("\0\0").length).toBe(2);
+});
- {
- const z = x.slice(2, 4);
- assert.strictEqual(z.length, 2);
- assert.strictEqual(z[0], 0x66);
- assert.strictEqual(z[1], 0x6f);
- }
+it("truncate write() at character boundary", () => {
+ const buf = Buffer.allocUnsafe(2);
+ expect(buf.write("")).toBe(0); // 0bytes
+ expect(buf.write("\0")).toBe(1); // 1byte (v8 adds null terminator)
+ expect(buf.write("a\0")).toBe(2); // 1byte * 2
+ expect(buf.write("あ")).toBe(0); // 3bytes
+ expect(buf.write("\0あ")).toBe(1); // 1byte + 3bytes
+ expect(buf.write("\0\0あ")).toBe(2); // 1byte * 2 + 3bytes
+
+ const buf2 = Buffer.allocUnsafe(10);
+ expect(buf2.write("あいう")).toBe(9); // 3bytes * 3 (v8 adds null term.)
+ expect(buf2.write("あいう\0")).toBe(10); // 3bytes * 3 + 1byte
+});
- ["ucs2", "ucs-2", "utf16le", "utf-16le"].forEach(encoding => {
- const b = Buffer.allocUnsafe(10);
- b.write("あいうえお", encoding);
- assert.strictEqual(b.toString(encoding), "あいうえお");
- });
+it("write() with maxLength", () => {
+ // https://github.com/nodejs/node-v0.x-archive/issues/243
+ const buf = Buffer.allocUnsafe(4);
+ buf.fill(0xff);
+ expect(buf.write("abcd", 1, 2, "utf8")).toBe(2);
+ expect(buf[0]).toBe(0xff);
+ expect(buf[1]).toBe(0x61);
+ expect(buf[2]).toBe(0x62);
+ expect(buf[3]).toBe(0xff);
+
+ buf.fill(0xff);
+ expect(buf.write("abcd", 1, 4)).toBe(3);
+ expect(buf[0]).toBe(0xff);
+ expect(buf[1]).toBe(0x61);
+ expect(buf[2]).toBe(0x62);
+ expect(buf[3]).toBe(0x63);
+
+ buf.fill(0xff);
+ expect(buf.write("abcd", 1, 2, "utf8")).toBe(2);
+ expect(buf[0]).toBe(0xff);
+ expect(buf[1]).toBe(0x61);
+ expect(buf[2]).toBe(0x62);
+ expect(buf[3]).toBe(0xff);
+
+ buf.fill(0xff);
+ expect(buf.write("abcdef", 1, 2, "hex")).toBe(2);
+ expect(buf[0]).toBe(0xff);
+ expect(buf[1]).toBe(0xab);
+ expect(buf[2]).toBe(0xcd);
+ expect(buf[3]).toBe(0xff);
["ucs2", "ucs-2", "utf16le", "utf-16le"].forEach(encoding => {
- const b = Buffer.allocUnsafe(11);
- b.write("あいうえお", 1, encoding);
- assert.strictEqual(b.toString(encoding, 1), "あいうえお");
- });
-
- {
- // latin1 encoding should write only one byte per character.
- const b = Buffer.from([0xde, 0xad, 0xbe, 0xef]);
- let s = String.fromCharCode(0xffff);
- b.write(s, 0, "latin1");
- assert.strictEqual(b[0], 0xff);
- assert.strictEqual(b[1], 0xad);
- assert.strictEqual(b[2], 0xbe);
- assert.strictEqual(b[3], 0xef);
- s = String.fromCharCode(0xaaee);
- b.write(s, 0, "latin1");
- assert.strictEqual(b[0], 0xee);
- assert.strictEqual(b[1], 0xad);
- assert.strictEqual(b[2], 0xbe);
- assert.strictEqual(b[3], 0xef);
- }
-
- {
- // Binary encoding should write only one byte per character.
- const b = Buffer.from([0xde, 0xad, 0xbe, 0xef]);
- let s = String.fromCharCode(0xffff);
- b.write(s, 0, "latin1");
- assert.strictEqual(b[0], 0xff);
- assert.strictEqual(b[1], 0xad);
- assert.strictEqual(b[2], 0xbe);
- assert.strictEqual(b[3], 0xef);
- s = String.fromCharCode(0xaaee);
- b.write(s, 0, "latin1");
- assert.strictEqual(b[0], 0xee);
- assert.strictEqual(b[1], 0xad);
- assert.strictEqual(b[2], 0xbe);
- assert.strictEqual(b[3], 0xef);
- }
-
- {
- // https://github.com/nodejs/node-v0.x-archive/pull/1210
- // Test UTF-8 string includes null character
- let buf = Buffer.from("\0");
- assert.strictEqual(buf.length, 1);
- buf = Buffer.from("\0\0");
- assert.strictEqual(buf.length, 2);
- }
-
- {
- const buf = Buffer.allocUnsafe(2);
- assert.strictEqual(buf.write(""), 0); // 0bytes
- assert.strictEqual(buf.write("\0"), 1); // 1byte (v8 adds null terminator)
- assert.strictEqual(buf.write("a\0"), 2); // 1byte * 2
- assert.strictEqual(buf.write("あ"), 0); // 3bytes
- assert.strictEqual(buf.write("\0あ"), 1); // 1byte + 3bytes
- assert.strictEqual(buf.write("\0\0あ"), 2); // 1byte * 2 + 3bytes
- }
-
- {
- const buf = Buffer.allocUnsafe(10);
- assert.strictEqual(buf.write("あいう"), 9); // 3bytes * 3 (v8 adds null term.)
- assert.strictEqual(buf.write("あいう\0"), 10); // 3bytes * 3 + 1byte
- }
-
- {
- // https://github.com/nodejs/node-v0.x-archive/issues/243
- // Test write() with maxLength
- const buf = Buffer.allocUnsafe(4);
- buf.fill(0xff);
- assert.strictEqual(buf.write("abcd", 1, 2, "utf8"), 2);
- assert.strictEqual(buf[0], 0xff);
- assert.strictEqual(buf[1], 0x61);
- assert.strictEqual(buf[2], 0x62);
- assert.strictEqual(buf[3], 0xff);
-
- buf.fill(0xff);
- assert.strictEqual(buf.write("abcd", 1, 4), 3);
- assert.strictEqual(buf[0], 0xff);
- assert.strictEqual(buf[1], 0x61);
- assert.strictEqual(buf[2], 0x62);
- assert.strictEqual(buf[3], 0x63);
-
- buf.fill(0xff);
- assert.strictEqual(buf.write("abcd", 1, 2, "utf8"), 2);
- assert.strictEqual(buf[0], 0xff);
- assert.strictEqual(buf[1], 0x61);
- assert.strictEqual(buf[2], 0x62);
- assert.strictEqual(buf[3], 0xff);
-
buf.fill(0xff);
- assert.strictEqual(buf.write("abcdef", 1, 2, "hex"), 2);
- assert.strictEqual(buf[0], 0xff);
- assert.strictEqual(buf[1], 0xab);
- assert.strictEqual(buf[2], 0xcd);
- assert.strictEqual(buf[3], 0xff);
-
- ["ucs2", "ucs-2", "utf16le", "utf-16le"].forEach(encoding => {
- buf.fill(0xff);
- assert.strictEqual(buf.write("abcd", 0, 2, encoding), 2);
- assert.strictEqual(buf[0], 0x61);
- assert.strictEqual(buf[1], 0x00);
- assert.strictEqual(buf[2], 0xff);
- assert.strictEqual(buf[3], 0xff);
- });
- }
-
- {
- // Test offset returns are correct
- const b = Buffer.allocUnsafe(16);
- assert.strictEqual(b.writeUInt32LE(0, 0), 4);
- assert.strictEqual(b.writeUInt16LE(0, 4), 6);
- assert.strictEqual(b.writeUInt8(0, 6), 7);
- assert.strictEqual(b.writeInt8(0, 7), 8);
- assert.strictEqual(b.writeDoubleLE(0, 8), 16);
- }
-
- {
- // Test unmatched surrogates not producing invalid utf8 output
- // ef bf bd = utf-8 representation of unicode replacement character
- // see https://codereview.chromium.org/121173009/
- let buf = Buffer.from("ab\ud800cd", "utf8");
- assert.strictEqual(buf[0], 0x61);
- assert.strictEqual(buf[1], 0x62);
- assert.strictEqual(buf[2], 0xef);
- assert.strictEqual(buf[3], 0xbf);
- assert.strictEqual(buf[4], 0xbd);
- assert.strictEqual(buf[5], 0x63);
- assert.strictEqual(buf[6], 0x64);
-
- buf = Buffer.from("abcd\ud800", "utf8");
+ expect(buf.write("abcd", 0, 2, encoding)).toBe(2);
expect(buf[0]).toBe(0x61);
- expect(buf[1]).toBe(0x62);
- expect(buf[2]).toBe(0x63);
- expect(buf[3]).toBe(0x64);
- expect(buf[4]).toBe(0xef);
- expect(buf[5]).toBe(0xbf);
- expect(buf[6]).toBe(0xbd);
-
- buf = Buffer.from("\ud800abcd", "utf8");
- expect(buf[0]).toBe(0xef);
- expect(buf[1]).toBe(0xbf);
- expect(buf[2]).toBe(0xbd);
- expect(buf[3]).toBe(0x61);
- expect(buf[4]).toBe(0x62);
- expect(buf[5]).toBe(0x63);
- expect(buf[6]).toBe(0x64);
- }
+ expect(buf[1]).toBe(0x00);
+ expect(buf[2]).toBe(0xff);
+ expect(buf[3]).toBe(0xff);
+ });
+});
- {
- // Test for buffer overrun
- const buf = Buffer.from([0, 0, 0, 0, 0]); // length: 5
- const sub = buf.slice(0, 4); // length: 4
- assert.strictEqual(sub.write("12345", "latin1"), 4);
- assert.strictEqual(buf[4], 0);
- assert.strictEqual(sub.write("12345", "binary"), 4);
- assert.strictEqual(buf[4], 0);
- }
+it("offset returns are correct", () => {
+ const b = Buffer.allocUnsafe(16);
+ expect(b.writeUInt32LE(0, 0)).toBe(4);
+ expect(b.writeUInt16LE(0, 4)).toBe(6);
+ expect(b.writeUInt8(0, 6)).toBe(7);
+ expect(b.writeInt8(0, 7)).toBe(8);
+ expect(b.writeDoubleLE(0, 8)).toBe(16);
+});
- {
- // Test alloc with fill option
- const buf = Buffer.alloc(5, "800A", "hex");
- assert.strictEqual(buf[0], 128);
- assert.strictEqual(buf[1], 10);
- assert.strictEqual(buf[2], 128);
- assert.strictEqual(buf[3], 10);
- assert.strictEqual(buf[4], 128);
- }
+it("unmatched surrogates should not produce invalid utf8 output", () => {
+ // ef bf bd = utf-8 representation of unicode replacement character
+ // see https://codereview.chromium.org/121173009/
+ let buf = Buffer.from("ab\ud800cd", "utf8");
+ expect(buf[0]).toBe(0x61);
+ expect(buf[1]).toBe(0x62);
+ expect(buf[2]).toBe(0xef);
+ expect(buf[3]).toBe(0xbf);
+ expect(buf[4]).toBe(0xbd);
+ expect(buf[5]).toBe(0x63);
+ expect(buf[6]).toBe(0x64);
+
+ buf = Buffer.from("abcd\ud800", "utf8");
+ expect(buf[0]).toBe(0x61);
+ expect(buf[1]).toBe(0x62);
+ expect(buf[2]).toBe(0x63);
+ expect(buf[3]).toBe(0x64);
+ expect(buf[4]).toBe(0xef);
+ expect(buf[5]).toBe(0xbf);
+ expect(buf[6]).toBe(0xbd);
+
+ buf = Buffer.from("\ud800abcd", "utf8");
+ expect(buf[0]).toBe(0xef);
+ expect(buf[1]).toBe(0xbf);
+ expect(buf[2]).toBe(0xbd);
+ expect(buf[3]).toBe(0x61);
+ expect(buf[4]).toBe(0x62);
+ expect(buf[5]).toBe(0x63);
+ expect(buf[6]).toBe(0x64);
+});
- // Check for fractional length args, junk length args, etc.
- // https://github.com/joyent/node/issues/1758
+it("buffer overrun", () => {
+ const buf = Buffer.from([0, 0, 0, 0, 0]); // length: 5
+ const sub = buf.slice(0, 4); // length: 4
+ expect(sub.write("12345", "latin1")).toBe(4);
+ expect(buf[4]).toBe(0);
+ expect(sub.write("12345", "binary")).toBe(4);
+ expect(buf[4]).toBe(0);
+});
+it("alloc with fill option", () => {
+ const buf = Buffer.alloc(5, "800A", "hex");
+ expect(buf[0]).toBe(128);
+ expect(buf[1]).toBe(10);
+ expect(buf[2]).toBe(128);
+ expect(buf[3]).toBe(10);
+ expect(buf[4]).toBe(128);
+});
+
+// https://github.com/joyent/node/issues/1758
+it("check for fractional length args, junk length args, etc.", () => {
// Call .fill() first, stops valgrind warning about uninitialized memory reads.
Buffer.allocUnsafe(3.3).fill().toString();
// Throws bad argument error in commit 43cb4ec
Buffer.alloc(3.3).fill().toString();
- assert.strictEqual(Buffer.allocUnsafe(3.3).length, 3);
- assert.strictEqual(Buffer.from({ length: 3.3 }).length, 3);
- assert.strictEqual(Buffer.from({ length: "BAM" }).length, 0);
-
+ expect(Buffer.allocUnsafe(3.3).length).toBe(3);
+ expect(Buffer.from({ length: 3.3 }).length).toBe(3);
+ expect(Buffer.from({ length: "BAM" }).length).toBe(0);
// Make sure that strings are not coerced to numbers.
- assert.strictEqual(Buffer.from("99").length, 2);
- assert.strictEqual(Buffer.from("13.37").length, 5);
-
+ expect(Buffer.from("99").length).toBe(2);
+ expect(Buffer.from("13.37").length).toBe(5);
// Ensure that the length argument is respected.
["ascii", "utf8", "hex", "base64", "latin1", "binary"].forEach(enc => {
- assert.strictEqual(Buffer.allocUnsafe(1).write("aaaaaa", 0, 1, enc), 1);
+ expect(Buffer.allocUnsafe(1).write("aaaaaa", 0, 1, enc)).toBe(1);
});
+ // Regression test, guard against buffer overrun in the base64 decoder.
+ const a = Buffer.allocUnsafe(3);
+ const b = Buffer.from("xxx");
+ a.write("aaaaaaaa", "base64");
+ expect(b.toString()).toBe("xxx");
+});
- {
- // Regression test, guard against buffer overrun in the base64 decoder.
- const a = Buffer.allocUnsafe(3);
- const b = Buffer.from("xxx");
- a.write("aaaaaaaa", "base64");
- assert.strictEqual(b.toString(), "xxx");
- }
-
- // issue GH-3416
- Buffer.from(Buffer.allocUnsafe(0), 0, 0);
-
+it("buffer overflow", () => {
// issue GH-5587
- assert.throws(() => Buffer.alloc(8).writeFloatLE(0, 5), outOfRangeError);
- assert.throws(() => Buffer.alloc(16).writeDoubleLE(0, 9), outOfRangeError);
-
+ expect(() => Buffer.alloc(8).writeFloatLE(0, 5)).toThrow(RangeError);
+ expect(() => Buffer.alloc(16).writeDoubleLE(0, 9)).toThrow(RangeError);
// Attempt to overflow buffers, similar to previous bug in array buffers
- assert.throws(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, 0xffffffff), outOfRangeError);
- assert.throws(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, 0xffffffff), outOfRangeError);
-
+ expect(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, 0xffffffff)).toThrow(RangeError);
+ expect(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, 0xffffffff)).toThrow(RangeError);
// Ensure negative values can't get past offset
- assert.throws(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, -1), outOfRangeError);
- assert.throws(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, -1), outOfRangeError);
-
- // Test for common write(U)IntLE/BE
- {
- let buf = Buffer.allocUnsafe(3);
- buf.writeUIntLE(0x123456, 0, 3);
- assert.deepStrictEqual(buf.toJSON().data, [0x56, 0x34, 0x12]);
- assert.strictEqual(buf.readUIntLE(0, 3), 0x123456);
-
- buf.fill(0xff);
- buf.writeUIntBE(0x123456, 0, 3);
- assert.deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56]);
- assert.strictEqual(buf.readUIntBE(0, 3), 0x123456);
-
- buf.fill(0xff);
- buf.writeIntLE(0x123456, 0, 3);
- assert.deepStrictEqual(buf.toJSON().data, [0x56, 0x34, 0x12]);
- assert.strictEqual(buf.readIntLE(0, 3), 0x123456);
-
- buf.fill(0xff);
- buf.writeIntBE(0x123456, 0, 3);
- assert.deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56]);
- assert.strictEqual(buf.readIntBE(0, 3), 0x123456);
-
- buf.fill(0xff);
- buf.writeIntLE(-0x123456, 0, 3);
- assert.deepStrictEqual(buf.toJSON().data, [0xaa, 0xcb, 0xed]);
- assert.strictEqual(buf.readIntLE(0, 3), -0x123456);
-
- buf.fill(0xff);
- buf.writeIntBE(-0x123456, 0, 3);
- assert.deepStrictEqual(buf.toJSON().data, [0xed, 0xcb, 0xaa]);
- assert.strictEqual(buf.readIntBE(0, 3), -0x123456);
-
- buf.fill(0xff);
- buf.writeIntLE(-0x123400, 0, 3);
- assert.deepStrictEqual(buf.toJSON().data, [0x00, 0xcc, 0xed]);
- assert.strictEqual(buf.readIntLE(0, 3), -0x123400);
-
- buf.fill(0xff);
- buf.writeIntBE(-0x123400, 0, 3);
- assert.deepStrictEqual(buf.toJSON().data, [0xed, 0xcc, 0x00]);
- assert.strictEqual(buf.readIntBE(0, 3), -0x123400);
-
- buf.fill(0xff);
- buf.writeIntLE(-0x120000, 0, 3);
- assert.deepStrictEqual(buf.toJSON().data, [0x00, 0x00, 0xee]);
- assert.strictEqual(buf.readIntLE(0, 3), -0x120000);
-
- buf.fill(0xff);
- buf.writeIntBE(-0x120000, 0, 3);
- assert.deepStrictEqual(buf.toJSON().data, [0xee, 0x00, 0x00]);
- assert.strictEqual(buf.readIntBE(0, 3), -0x120000);
-
- buf = Buffer.allocUnsafe(5);
- buf.writeUIntLE(0x1234567890, 0, 5);
- assert.deepStrictEqual(buf.toJSON().data, [0x90, 0x78, 0x56, 0x34, 0x12]);
- assert.strictEqual(buf.readUIntLE(0, 5), 0x1234567890);
-
- buf.fill(0xff);
- buf.writeUIntBE(0x1234567890, 0, 5);
- assert.deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56, 0x78, 0x90]);
- assert.strictEqual(buf.readUIntBE(0, 5), 0x1234567890);
-
- buf.fill(0xff);
- buf.writeIntLE(0x1234567890, 0, 5);
- assert.deepStrictEqual(buf.toJSON().data, [0x90, 0x78, 0x56, 0x34, 0x12]);
- assert.strictEqual(buf.readIntLE(0, 5), 0x1234567890);
-
- buf.fill(0xff);
- buf.writeIntBE(0x1234567890, 0, 5);
- assert.deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56, 0x78, 0x90]);
- assert.strictEqual(buf.readIntBE(0, 5), 0x1234567890);
-
- buf.fill(0xff);
- buf.writeIntLE(-0x1234567890, 0, 5);
- assert.deepStrictEqual(buf.toJSON().data, [0x70, 0x87, 0xa9, 0xcb, 0xed]);
- assert.strictEqual(buf.readIntLE(0, 5), -0x1234567890);
-
- buf.fill(0xff);
- buf.writeIntBE(-0x1234567890, 0, 5);
- assert.deepStrictEqual(buf.toJSON().data, [0xed, 0xcb, 0xa9, 0x87, 0x70]);
- assert.strictEqual(buf.readIntBE(0, 5), -0x1234567890);
-
- buf.fill(0xff);
- buf.writeIntLE(-0x0012000000, 0, 5);
- assert.deepStrictEqual(buf.toJSON().data, [0x00, 0x00, 0x00, 0xee, 0xff]);
- assert.strictEqual(buf.readIntLE(0, 5), -0x0012000000);
-
- buf.fill(0xff);
- buf.writeIntBE(-0x0012000000, 0, 5);
- assert.deepStrictEqual(buf.toJSON().data, [0xff, 0xee, 0x00, 0x00, 0x00]);
- assert.strictEqual(buf.readIntBE(0, 5), -0x0012000000);
- }
+ expect(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, -1)).toThrow(RangeError);
+ expect(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, -1)).toThrow(RangeError);
+});
- // Regression test for https://github.com/nodejs/node-v0.x-archive/issues/5482:
- // should throw but not assert in C++ land.
- assert.throws(() => Buffer.from("", "buffer"), {
- code: "ERR_UNKNOWN_ENCODING",
- name: "TypeError",
- message: "Unknown encoding: buffer",
- });
+it("common write{U}IntLE/BE()", () => {
+ let buf = Buffer.allocUnsafe(3);
+ buf.writeUIntLE(0x123456, 0, 3);
+ expect(buf.toJSON().data).toEqual([0x56, 0x34, 0x12]);
+ expect(buf.readUIntLE(0, 3)).toBe(0x123456);
+
+ buf.fill(0xff);
+ buf.writeUIntBE(0x123456, 0, 3);
+ expect(buf.toJSON().data).toEqual([0x12, 0x34, 0x56]);
+ expect(buf.readUIntBE(0, 3)).toBe(0x123456);
+
+ buf.fill(0xff);
+ buf.writeIntLE(0x123456, 0, 3);
+ expect(buf.toJSON().data).toEqual([0x56, 0x34, 0x12]);
+ expect(buf.readIntLE(0, 3)).toBe(0x123456);
+
+ buf.fill(0xff);
+ buf.writeIntBE(0x123456, 0, 3);
+ expect(buf.toJSON().data).toEqual([0x12, 0x34, 0x56]);
+ expect(buf.readIntBE(0, 3)).toBe(0x123456);
+
+ buf.fill(0xff);
+ buf.writeIntLE(-0x123456, 0, 3);
+ expect(buf.toJSON().data).toEqual([0xaa, 0xcb, 0xed]);
+ expect(buf.readIntLE(0, 3)).toBe(-0x123456);
+
+ buf.fill(0xff);
+ buf.writeIntBE(-0x123456, 0, 3);
+ expect(buf.toJSON().data).toEqual([0xed, 0xcb, 0xaa]);
+ expect(buf.readIntBE(0, 3)).toBe(-0x123456);
+
+ buf.fill(0xff);
+ buf.writeIntLE(-0x123400, 0, 3);
+ expect(buf.toJSON().data).toEqual([0x00, 0xcc, 0xed]);
+ expect(buf.readIntLE(0, 3)).toBe(-0x123400);
+
+ buf.fill(0xff);
+ buf.writeIntBE(-0x123400, 0, 3);
+ expect(buf.toJSON().data).toEqual([0xed, 0xcc, 0x00]);
+ expect(buf.readIntBE(0, 3)).toBe(-0x123400);
+
+ buf.fill(0xff);
+ buf.writeIntLE(-0x120000, 0, 3);
+ expect(buf.toJSON().data).toEqual([0x00, 0x00, 0xee]);
+ expect(buf.readIntLE(0, 3)).toBe(-0x120000);
+
+ buf.fill(0xff);
+ buf.writeIntBE(-0x120000, 0, 3);
+ expect(buf.toJSON().data).toEqual([0xee, 0x00, 0x00]);
+ expect(buf.readIntBE(0, 3)).toBe(-0x120000);
+
+ buf = Buffer.allocUnsafe(5);
+ buf.writeUIntLE(0x1234567890, 0, 5);
+ expect(buf.toJSON().data).toEqual([0x90, 0x78, 0x56, 0x34, 0x12]);
+ expect(buf.readUIntLE(0, 5)).toBe(0x1234567890);
+
+ buf.fill(0xff);
+ buf.writeUIntBE(0x1234567890, 0, 5);
+ expect(buf.toJSON().data).toEqual([0x12, 0x34, 0x56, 0x78, 0x90]);
+ expect(buf.readUIntBE(0, 5)).toBe(0x1234567890);
+
+ buf.fill(0xff);
+ buf.writeIntLE(0x1234567890, 0, 5);
+ expect(buf.toJSON().data).toEqual([0x90, 0x78, 0x56, 0x34, 0x12]);
+ expect(buf.readIntLE(0, 5)).toBe(0x1234567890);
+
+ buf.fill(0xff);
+ buf.writeIntBE(0x1234567890, 0, 5);
+ expect(buf.toJSON().data).toEqual([0x12, 0x34, 0x56, 0x78, 0x90]);
+ expect(buf.readIntBE(0, 5)).toBe(0x1234567890);
+
+ buf.fill(0xff);
+ buf.writeIntLE(-0x1234567890, 0, 5);
+ expect(buf.toJSON().data).toEqual([0x70, 0x87, 0xa9, 0xcb, 0xed]);
+ expect(buf.readIntLE(0, 5)).toBe(-0x1234567890);
+
+ buf.fill(0xff);
+ buf.writeIntBE(-0x1234567890, 0, 5);
+ expect(buf.toJSON().data).toEqual([0xed, 0xcb, 0xa9, 0x87, 0x70]);
+ expect(buf.readIntBE(0, 5)).toBe(-0x1234567890);
+
+ buf.fill(0xff);
+ buf.writeIntLE(-0x0012000000, 0, 5);
+ expect(buf.toJSON().data).toEqual([0x00, 0x00, 0x00, 0xee, 0xff]);
+ expect(buf.readIntLE(0, 5)).toBe(-0x0012000000);
+
+ buf.fill(0xff);
+ buf.writeIntBE(-0x0012000000, 0, 5);
+ expect(buf.toJSON().data).toEqual([0xff, 0xee, 0x00, 0x00, 0x00]);
+ expect(buf.readIntBE(0, 5)).toBe(-0x0012000000);
+});
+it("construct buffer from buffer", () => {
// Regression test for https://github.com/nodejs/node-v0.x-archive/issues/6111.
// Constructing a buffer from another buffer should a) work, and b) not corrupt
// the source buffer.
- {
- const a = [...Array(128).keys()]; // [0, 1, 2, 3, ... 126, 127]
- const b = Buffer.from(a);
- const c = Buffer.from(b);
- assert.strictEqual(b.length, a.length);
- assert.strictEqual(c.length, a.length);
- for (let i = 0, k = a.length; i < k; ++i) {
- assert.strictEqual(a[i], i);
- assert.strictEqual(b[i], i);
- assert.strictEqual(c[i], i);
- }
+ const a = [...Array(128).keys()]; // [0, 1, 2, 3, ... 126, 127]
+ const b = Buffer.from(a);
+ const c = Buffer.from(b);
+ expect(b.length).toBe(a.length);
+ expect(c.length).toBe(a.length);
+ for (let i = 0, k = a.length; i < k; ++i) {
+ expect(a[i]).toBe(i);
+ expect(b[i]).toBe(i);
+ expect(c[i]).toBe(i);
}
+});
- // if (common.hasCrypto) {
- // eslint-disable-line node-core/crypto-check
- // Test truncation after decode
+it("truncation after decode", () => {
const crypto = require("crypto");
- const b1 = Buffer.from("YW55=======", "base64");
- const b2 = Buffer.from("YW55", "base64");
-
- assert.strictEqual(
- crypto.createHash("sha1").update(b1).digest("hex"),
- crypto.createHash("sha1").update(b2).digest("hex"),
+ expect(crypto.createHash("sha1").update(Buffer.from("YW55=======", "base64")).digest("hex")).toBe(
+ crypto.createHash("sha1").update(Buffer.from("YW55", "base64")).digest("hex"),
);
- // } else {
- // common.printSkipMessage("missing crypto");
- // }
+});
+it("Buffer,poolSize", () => {
const ps = Buffer.poolSize;
Buffer.poolSize = 0;
- assert(Buffer.allocUnsafe(1).parent instanceof ArrayBuffer);
+ expect(Buffer.allocUnsafe(1).parent instanceof ArrayBuffer).toBe(true);
Buffer.poolSize = ps;
- assert.throws(() => Buffer.allocUnsafe(10).copy(), {
- code: "ERR_INVALID_ARG_TYPE",
- name: "TypeError",
- message: 'The "target" argument must be an instance of Buffer or ' + "Uint8Array. Received undefined",
- });
+ expect(() => Buffer.allocUnsafe(10).copy()).toThrow(TypeError);
- assert.throws(() => Buffer.from(), {
- name: "TypeError",
- message:
- "The first argument must be of type string or an instance of " +
- "Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined",
- });
- assert.throws(() => Buffer.from(null), {
- name: "TypeError",
- message:
- "The first argument must be of type string or an instance of " +
- "Buffer, ArrayBuffer, or Array or an Array-like Object. Received null",
- });
+ expect(() => Buffer.from()).toThrow(TypeError);
+ expect(() => Buffer.from(null)).toThrow(TypeError);
+});
- // Test prototype getters don't throw
- assert.strictEqual(Buffer.prototype.parent, undefined);
- assert.strictEqual(Buffer.prototype.offset, undefined);
- assert.strictEqual(SlowBuffer.prototype.parent, undefined);
- assert.strictEqual(SlowBuffer.prototype.offset, undefined);
+it("prototype getters should not throw", () => {
+ expect(Buffer.prototype.parent).toBeUndefined();
+ expect(Buffer.prototype.offset).toBeUndefined();
+ expect(SlowBuffer.prototype.parent).toBeUndefined();
+ expect(SlowBuffer.prototype.offset).toBeUndefined();
+});
- {
- // Test that large negative Buffer length inputs don't affect the pool offset.
- // Use the fromArrayLike() variant here because it's more lenient
- // about its input and passes the length directly to allocate().
- assert.deepStrictEqual(Buffer.from({ length: -Buffer.poolSize }), Buffer.from(""));
- assert.deepStrictEqual(Buffer.from({ length: -100 }), Buffer.from(""));
-
- // Check pool offset after that by trying to write string into the pool.
- Buffer.from("abc");
- }
+it("large negative Buffer length inputs should not affect pool offset", () => {
+ // Use the fromArrayLike() variant here because it's more lenient
+ // about its input and passes the length directly to allocate().
+ expect(Buffer.from({ length: -Buffer.poolSize })).toStrictEqual(Buffer.from(""));
+ expect(Buffer.from({ length: -100 })).toStrictEqual(Buffer.from(""));
- // Test that ParseArrayIndex handles full uint32
- {
- const errMsg = common.expectsError({
- code: "ERR_BUFFER_OUT_OF_BOUNDS",
- name: "RangeError",
- message: '"offset" is outside of buffer bounds',
- });
- assert.throws(() => Buffer.from(new ArrayBuffer(0), -1 >>> 0), errMsg);
- }
+ // Check pool offset after that by trying to write string into the pool.
+ Buffer.from("abc");
+});
+
+it("ParseArrayIndex() should handle full uint32", () => {
+ expect(() => Buffer.from(new ArrayBuffer(0), -1 >>> 0)).toThrow(RangeError);
+});
- // ParseArrayIndex() should reject values that don't fit in a 32 bits size_t.
- assert.throws(() => {
+it("ParseArrayIndex() should reject values that don't fit in a 32 bits size_t", () => {
+ expect(() => {
const a = Buffer.alloc(1);
const b = Buffer.alloc(1);
a.copy(b, 0, 0x100000000, 0x100000001);
- }, outOfRangeError);
+ }).toThrow(RangeError);
+});
- // Unpooled buffer (replaces SlowBuffer)
- {
- const ubuf = Buffer.allocUnsafeSlow(10);
- assert(ubuf);
- assert(ubuf.buffer);
- assert.strictEqual(ubuf.buffer.byteLength, 10);
- }
+it("unpooled buffer (replaces SlowBuffer)", () => {
+ const ubuf = Buffer.allocUnsafeSlow(10);
+ expect(ubuf).toBeTruthy();
+ expect(ubuf.buffer).toBeTruthy();
+ expect(ubuf.buffer.byteLength).toBe(10);
+});
- // Regression test to verify that an empty ArrayBuffer does not throw.
+it("verify that an empty ArrayBuffer does not throw", () => {
Buffer.from(new ArrayBuffer());
+});
- // Test that ArrayBuffer from a different context is detected correctly.
- // const arrayBuf = vm.runInNewContext("new ArrayBuffer()");
- // Buffer.from(arrayBuf);
- // Buffer.from({ buffer: arrayBuf });
-
- assert.throws(() => Buffer.alloc({ valueOf: () => 1 }), /"size" argument must be of type number/);
- assert.throws(() => Buffer.alloc({ valueOf: () => -1 }), /"size" argument must be of type number/);
-
- assert.strictEqual(Buffer.prototype.toLocaleString, Buffer.prototype.toString);
- {
- const buf = Buffer.from("test");
- assert.strictEqual(buf.toLocaleString(), buf.toString());
- }
-
- assert.throws(
- () => {
- Buffer.alloc(0x1000, "This is not correctly encoded", "hex");
- },
- {
- code: "ERR_INVALID_ARG_VALUE",
- name: "TypeError",
- },
- );
-
- assert.throws(
- () => {
- Buffer.alloc(0x1000, "c", "hex");
- },
- {
- code: "ERR_INVALID_ARG_VALUE",
- name: "TypeError",
- },
- );
+it("alloc() should throw on non-numeric size", () => {
+ expect(() => Buffer.alloc({ valueOf: () => 1 })).toThrow(TypeError);
+ expect(() => Buffer.alloc({ valueOf: () => -1 })).toThrow(TypeError);
+});
- assert.throws(
- () => {
- Buffer.alloc(1, Buffer.alloc(0));
- },
- {
- code: "ERR_INVALID_ARG_VALUE",
- name: "TypeError",
- },
- );
+it("toLocaleString()", () => {
+ const buf = Buffer.from("test");
+ expect(buf.toLocaleString()).toBe(buf.toString());
+ // expect(Buffer.prototype.toLocaleString).toBe(Buffer.prototype.toString);
+});
- assert.throws(
- () => {
- Buffer.alloc(40, "x", 20);
- },
- {
- code: "ERR_INVALID_ARG_TYPE",
- name: "TypeError",
- },
- );
+it("alloc() should throw on invalid data", () => {
+ expect(() => Buffer.alloc(0x1000, "This is not correctly encoded", "hex")).toThrow(TypeError);
+ expect(() => Buffer.alloc(0x1000, "c", "hex")).toThrow(TypeError);
+ expect(() => Buffer.alloc(1, Buffer.alloc(0))).toThrow(TypeError);
+ expect(() => Buffer.alloc(40, "x", 20)).toThrow(TypeError);
});
it("Buffer.toJSON()", () => {
@@ -2064,8 +1902,58 @@ it("Buffer.fill (Node.js tests)", () => {
const buf1 = Buffer.allocUnsafe(SIZE);
const buf2 = Buffer.allocUnsafe(SIZE);
- function assertEqual(a, b) {
- expect(a).toEqual(b);
+ function bufReset() {
+ buf1.fill(0);
+ buf2.fill(0);
+ }
+
+ // This is mostly accurate. Except write() won't write partial bytes to the
+ // string while fill() blindly copies bytes into memory. To account for that an
+ // error will be thrown if not all the data can be written, and the SIZE has
+ // been massaged to work with the input characters.
+ function writeToFill(string, offset, end, encoding) {
+ if (typeof offset === "string") {
+ encoding = offset;
+ offset = 0;
+ end = buf2.length;
+ } else if (typeof end === "string") {
+ encoding = end;
+ end = buf2.length;
+ } else if (end === undefined) {
+ end = buf2.length;
+ }
+
+ // Should never be reached.
+ if (offset < 0 || end > buf2.length) throw new ERR_OUT_OF_RANGE();
+
+ if (end <= offset) return buf2;
+
+ offset >>>= 0;
+ end >>>= 0;
+ expect(offset <= buf2.length).toBe(true);
+
+ // Convert "end" to "length" (which write understands).
+ const length = end - offset < 0 ? 0 : end - offset;
+
+ let wasZero = false;
+ do {
+ const written = buf2.write(string, offset, length, encoding);
+ offset += written;
+ // Safety check in case write falls into infinite loop.
+ if (written === 0) {
+ if (wasZero) throw new Error("Could not write all data to Buffer at " + offset);
+ else wasZero = true;
+ }
+ } while (offset < buf2.length);
+
+ return buf2;
+ }
+
+ function testBufs(string, offset, length, encoding) {
+ bufReset();
+ buf1.fill.apply(buf1, arguments);
+ // Swap bytes on BE archs for ucs2 encoding.
+ expect(buf1.fill.apply(buf1, arguments)).toStrictEqual(writeToFill.apply(null, arguments));
}
// Default encoding
@@ -2101,7 +1989,7 @@ it("Buffer.fill (Node.js tests)", () => {
testBufs("\u0222aa", 8, 1, "utf8");
testBufs("a\u0234b\u0235c\u0236", 4, 1, "utf8");
testBufs("a\u0234b\u0235c\u0236", 12, 1, "utf8");
- assertEqual(Buffer.allocUnsafe(1).fill(0).fill("\u0222")[0], 0xc8);
+ expect(Buffer.allocUnsafe(1).fill(0).fill("\u0222")[0]).toBe(0xc8);
// BINARY
testBufs("abc", "binary");
@@ -2152,7 +2040,7 @@ it("Buffer.fill (Node.js tests)", () => {
testBufs("\u0222aa", 8, 1, "ucs2");
testBufs("a\u0234b\u0235c\u0236", 4, 1, "ucs2");
testBufs("a\u0234b\u0235c\u0236", 12, 1, "ucs2");
- assertEqual(Buffer.allocUnsafe(1).fill("\u0222", "ucs2")[0], 0x22);
+ expect(Buffer.allocUnsafe(1).fill("\u0222", "ucs2")[0]).toBe(0x22);
// HEX
testBufs("616263", "hex");
@@ -2214,199 +2102,136 @@ it("Buffer.fill (Node.js tests)", () => {
testBufs("yKJhYQ", 8, 1, "base64url");
testBufs("Yci0Ysi1Y8i2", 4, 1, "base64url");
testBufs("Yci0Ysi1Y8i2", 12, 1, "base64url");
+});
- // Buffer
- function deepStrictEqualValues(buf, arr) {
- for (const [index, value] of buf.entries()) {
- expect(value).toStrictEqual(arr[index]);
- }
- }
-
- const buf2Fill = Buffer.allocUnsafe(1).fill(2);
- deepStrictEqualValues(genBuffer(4, [buf2Fill]), [2, 2, 2, 2]);
- deepStrictEqualValues(genBuffer(4, [buf2Fill, 1]), [0, 2, 2, 2]);
- deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 3]), [0, 2, 2, 0]);
- deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 1]), [0, 0, 0, 0]);
- const hexBufFill = Buffer.allocUnsafe(2).fill(0).fill("0102", "hex");
- deepStrictEqualValues(genBuffer(4, [hexBufFill]), [1, 2, 1, 2]);
- deepStrictEqualValues(genBuffer(4, [hexBufFill, 1]), [0, 1, 2, 1]);
- deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 3]), [0, 1, 2, 0]);
- deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 1]), [0, 0, 0, 0]);
-
- // Check exceptions
- [
- [0, -1],
- [0, 0, buf1.length + 1],
- ["", -1],
- ["", 0, buf1.length + 1],
- ["", 1, -1],
- ].forEach(args => {
- expect(() => buf1.fill(...args)).toThrow();
- });
-
- expect(() => buf1.fill("a", 0, buf1.length, "node rocks!")).toThrow();
-
- [
- ["a", 0, 0, NaN],
- ["a", 0, 0, false],
- ].forEach(args => {
- expect(() => buf1.fill(...args)).toThrow();
- });
-
- expect(() => buf1.fill("a", 0, 0, "foo")).toThrow();
-
+it("fill() repeat pattern", () => {
function genBuffer(size, args) {
const b = Buffer.allocUnsafe(size);
return b.fill(0).fill.apply(b, args);
}
- function bufReset() {
- buf1.fill(0);
- buf2.fill(0);
- }
-
- // This is mostly accurate. Except write() won't write partial bytes to the
- // string while fill() blindly copies bytes into memory. To account for that an
- // error will be thrown if not all the data can be written, and the SIZE has
- // been massaged to work with the input characters.
- function writeToFill(string, offset, end, encoding) {
- if (typeof offset === "string") {
- encoding = offset;
- offset = 0;
- end = buf2.length;
- } else if (typeof end === "string") {
- encoding = end;
- end = buf2.length;
- } else if (end === undefined) {
- end = buf2.length;
- }
-
- // Should never be reached.
- if (offset < 0 || end > buf2.length) throw new ERR_OUT_OF_RANGE();
-
- if (end <= offset) return buf2;
-
- offset >>>= 0;
- end >>>= 0;
- expect(offset <= buf2.length).toBe(true);
-
- // Convert "end" to "length" (which write understands).
- const length = end - offset < 0 ? 0 : end - offset;
-
- let wasZero = false;
- do {
- const written = buf2.write(string, offset, length, encoding);
- offset += written;
- // Safety check in case write falls into infinite loop.
- if (written === 0) {
- if (wasZero) throw new Error("Could not write all data to Buffer at " + offset);
- else wasZero = true;
- }
- } while (offset < buf2.length);
-
- return buf2;
- }
+ const buf2Fill = Buffer.allocUnsafe(1).fill(2);
+ expect(genBuffer(4, [buf2Fill])).toStrictEqual(Buffer.from([2, 2, 2, 2]));
+ expect(genBuffer(4, [buf2Fill, 1])).toStrictEqual(Buffer.from([0, 2, 2, 2]));
+ expect(genBuffer(4, [buf2Fill, 1, 3])).toStrictEqual(Buffer.from([0, 2, 2, 0]));
+ expect(genBuffer(4, [buf2Fill, 1, 1])).toStrictEqual(Buffer.from([0, 0, 0, 0]));
+ const hexBufFill = Buffer.allocUnsafe(2).fill(0).fill("0102", "hex");
+ expect(genBuffer(4, [hexBufFill])).toStrictEqual(Buffer.from([1, 2, 1, 2]));
+ expect(genBuffer(4, [hexBufFill, 1])).toStrictEqual(Buffer.from([0, 1, 2, 1]));
+ expect(genBuffer(4, [hexBufFill, 1, 3])).toStrictEqual(Buffer.from([0, 1, 2, 0]));
+ expect(genBuffer(4, [hexBufFill, 1, 1])).toStrictEqual(Buffer.from([0, 0, 0, 0]));
+});
- function testBufs(string, offset, length, encoding) {
- bufReset();
- buf1.fill.apply(buf1, arguments);
- // Swap bytes on BE archs for ucs2 encoding.
- expect(buf1.fill.apply(buf1, arguments)).toStrictEqual(writeToFill.apply(null, arguments));
- }
+it("fill() should throw on invalid arguments", () => {
+ // Check exceptions
+ const buf = Buffer.allocUnsafe(16);
+ expect(() => buf.fill(0, -1)).toThrow(RangeError);
+ expect(() => buf.fill(0, 0, buf.length + 1)).toThrow(RangeError);
+ expect(() => buf.fill("", -1)).toThrow(RangeError);
+ expect(() => buf.fill("", 0, buf.length + 1)).toThrow(RangeError);
+ expect(() => buf.fill("", 1, -1)).toThrow(RangeError);
+ expect(() => buf.fill("a", 0, buf.length, "node rocks!")).toThrow(TypeError);
+ expect(() => buf.fill("a", 0, 0, NaN)).toThrow(TypeError);
+ expect(() => buf.fill("a", 0, 0, false)).toThrow(TypeError);
+ expect(() => buf.fill("a", 0, 0, "foo")).toThrow(TypeError);
// Make sure these throw.
expect(() => Buffer.allocUnsafe(8).fill("a", -1)).toThrow();
expect(() => Buffer.allocUnsafe(8).fill("a", 0, 9)).toThrow();
+});
+it("fill() should not hang indefinitely", () => {
// Make sure this doesn't hang indefinitely.
Buffer.allocUnsafe(8).fill("");
Buffer.alloc(8, "");
+});
- {
- const buf = Buffer.alloc(64, 10);
- for (let i = 0; i < buf.length; i++) assertEqual(buf[i], 10);
+it("fill() repeat byte", () => {
+ const buf = Buffer.alloc(64, 10);
+ for (let i = 0; i < buf.length; i++) expect(buf[i]).toBe(10);
- buf.fill(11, 0, buf.length >> 1);
- for (let i = 0; i < buf.length >> 1; i++) assertEqual(buf[i], 11);
- for (let i = (buf.length >> 1) + 1; i < buf.length; i++) assertEqual(buf[i], 10);
+ buf.fill(11, 0, buf.length >> 1);
+ for (let i = 0; i < buf.length >> 1; i++) expect(buf[i]).toBe(11);
+ for (let i = (buf.length >> 1) + 1; i < buf.length; i++) expect(buf[i]).toBe(10);
- buf.fill("h");
- for (let i = 0; i < buf.length; i++) assertEqual(buf[i], "h".charCodeAt(0));
+ buf.fill("h");
+ for (let i = 0; i < buf.length; i++) expect(buf[i]).toBe("h".charCodeAt(0));
- buf.fill(0);
- for (let i = 0; i < buf.length; i++) assertEqual(buf[i], 0);
+ buf.fill(0);
+ for (let i = 0; i < buf.length; i++) expect(buf[i]).toBe(0);
- buf.fill(null);
- for (let i = 0; i < buf.length; i++) assertEqual(buf[i], 0);
+ buf.fill(null);
+ for (let i = 0; i < buf.length; i++) expect(buf[i]).toBe(0);
- buf.fill(1, 16, 32);
- for (let i = 0; i < 16; i++) assertEqual(buf[i], 0);
- for (let i = 16; i < 32; i++) assertEqual(buf[i], 1);
- for (let i = 32; i < buf.length; i++) assertEqual(buf[i], 0);
- }
+ buf.fill(1, 16, 32);
+ for (let i = 0; i < 16; i++) expect(buf[i]).toBe(0);
+ for (let i = 16; i < 32; i++) expect(buf[i]).toBe(1);
+ for (let i = 32; i < buf.length; i++) expect(buf[i]).toBe(0);
+});
- {
- const buf = Buffer.alloc(10, "abc");
- assertEqual(buf.toString(), "abcabcabca");
- buf.fill("է");
- assertEqual(buf.toString(), "էէէէէ");
- }
+it("alloc() repeat pattern", () => {
+ const buf = Buffer.alloc(10, "abc");
+ expect(buf.toString()).toBe("abcabcabca");
+ buf.fill("է");
+ expect(buf.toString()).toBe("էէէէէ");
+});
+it("fill() should properly check `start` & `end`", () => {
// // Testing process.binding. Make sure "start" is properly checked for range
// // errors.
- // assert.throws(
- // () => {
- // internalBinding("buffer").fill(Buffer.alloc(1), 1, -1, 0, 1);
- // },
- // { code: "ERR_OUT_OF_RANGE" },
- // );
+ // expect(() => internalBinding("buffer").fill(Buffer.alloc(1), 1, -1, 0, 1)).toThrow(RangeError);
// Make sure "end" is properly checked, even if it's magically mangled using
// Symbol.toPrimitive.
- {
- expect(() => {
- const end = {
- [Symbol.toPrimitive]() {
- return 1;
- },
- };
- Buffer.alloc(1).fill(Buffer.alloc(1), 0, end);
- }).toThrow();
- }
+ expect(() => {
+ const end = {
+ [Symbol.toPrimitive]() {
+ return 1;
+ },
+ };
+ Buffer.alloc(1).fill(Buffer.alloc(1), 0, end);
+ }).toThrow(TypeError);
// Testing process.binding. Make sure "end" is properly checked for range
// errors.
- // assert.throws(
- // () => {
- // internalBinding("buffer").fill(Buffer.alloc(1), 1, 1, -2, 1);
- // },
- // { code: "ERR_OUT_OF_RANGE" },
- // );
-
- // Test that bypassing 'length' won't cause an abort.
- expect(() => {
- const buf = Buffer.from("w00t");
- Object.defineProperty(buf, "length", {
- value: 1337,
- enumerable: true,
- });
- buf.fill("");
- }).toThrow();
+ // expect(() => internalBinding("buffer").fill(Buffer.alloc(1), 1, 1, -2, 1)).toThrow(RangeError);
+});
+
+it("bypassing `length` should not cause an abort", () => {
+ const buf = Buffer.from("w00t");
+ expect(buf).toStrictEqual(Buffer.from([119, 48, 48, 116]));
+ Object.defineProperty(buf, "length", {
+ value: 1337,
+ enumerable: true,
+ });
+ // Node.js throws here, but we can handle it just fine
+ buf.fill("");
+ expect(buf).toStrictEqual(Buffer.from([0, 0, 0, 0]));
+});
- assertEqual(Buffer.allocUnsafeSlow(16).fill("ab", "utf16le"), Buffer.from("61006200610062006100620061006200", "hex"));
+it("allocUnsafeSlow().fill()", () => {
+ expect(Buffer.allocUnsafeSlow(16).fill("ab", "utf16le")).toStrictEqual(
+ Buffer.from("61006200610062006100620061006200", "hex"),
+ );
- assertEqual(Buffer.allocUnsafeSlow(15).fill("ab", "utf16le"), Buffer.from("610062006100620061006200610062", "hex"));
+ expect(Buffer.allocUnsafeSlow(15).fill("ab", "utf16le")).toStrictEqual(
+ Buffer.from("610062006100620061006200610062", "hex"),
+ );
- assertEqual(Buffer.allocUnsafeSlow(16).fill("ab", "utf16le"), Buffer.from("61006200610062006100620061006200", "hex"));
- assertEqual(Buffer.allocUnsafeSlow(16).fill("a", "utf16le"), Buffer.from("61006100610061006100610061006100", "hex"));
+ expect(Buffer.allocUnsafeSlow(16).fill("ab", "utf16le")).toStrictEqual(
+ Buffer.from("61006200610062006100620061006200", "hex"),
+ );
+ expect(Buffer.allocUnsafeSlow(16).fill("a", "utf16le")).toStrictEqual(
+ Buffer.from("61006100610061006100610061006100", "hex"),
+ );
- assertEqual(Buffer.allocUnsafeSlow(16).fill("a", "utf16le").toString("utf16le"), "a".repeat(8));
- assertEqual(Buffer.allocUnsafeSlow(16).fill("a", "latin1").toString("latin1"), "a".repeat(16));
- assertEqual(Buffer.allocUnsafeSlow(16).fill("a", "utf8").toString("utf8"), "a".repeat(16));
+ expect(Buffer.allocUnsafeSlow(16).fill("a", "utf16le").toString("utf16le")).toBe("a".repeat(8));
+ expect(Buffer.allocUnsafeSlow(16).fill("a", "latin1").toString("latin1")).toBe("a".repeat(16));
+ expect(Buffer.allocUnsafeSlow(16).fill("a", "utf8").toString("utf8")).toBe("a".repeat(16));
- assertEqual(Buffer.allocUnsafeSlow(16).fill("Љ", "utf16le").toString("utf16le"), "Љ".repeat(8));
- assertEqual(Buffer.allocUnsafeSlow(16).fill("Љ", "latin1").toString("latin1"), "\t".repeat(16));
- assertEqual(Buffer.allocUnsafeSlow(16).fill("Љ", "utf8").toString("utf8"), "Љ".repeat(8));
+ expect(Buffer.allocUnsafeSlow(16).fill("Љ", "utf16le").toString("utf16le")).toBe("Љ".repeat(8));
+ expect(Buffer.allocUnsafeSlow(16).fill("Љ", "latin1").toString("latin1")).toBe("\t".repeat(16));
+ expect(Buffer.allocUnsafeSlow(16).fill("Љ", "utf8").toString("utf8")).toBe("Љ".repeat(8));
expect(() => {
const buf = Buffer.from("a".repeat(1000));
@@ -2415,115 +2240,116 @@ it("Buffer.fill (Node.js tests)", () => {
}).toThrow();
});
-test("Buffer.byteLength", () => {
- const SlowBuffer = require("buffer").SlowBuffer;
-
- [[32, "latin1"], [NaN, "utf8"], [{}, "latin1"], []].forEach(args => {
- assert.throws(() => Buffer.byteLength(...args));
- });
+it("ArrayBuffer.isView()", () => {
+ expect(ArrayBuffer.isView(new Buffer(10))).toBe(true);
+ expect(ArrayBuffer.isView(new SlowBuffer(10))).toBe(true);
+ expect(ArrayBuffer.isView(Buffer.alloc(10))).toBe(true);
+ expect(ArrayBuffer.isView(Buffer.allocUnsafe(10))).toBe(true);
+ expect(ArrayBuffer.isView(Buffer.allocUnsafeSlow(10))).toBe(true);
+ expect(ArrayBuffer.isView(Buffer.from(""))).toBe(true);
+});
- assert.strictEqual(Buffer.byteLength("", undefined, true), 0);
+it("Buffer.byteLength()", () => {
+ expect(() => Buffer.byteLength(32, "latin1")).toThrow(TypeError);
+ expect(() => Buffer.byteLength(NaN, "utf8")).toThrow(TypeError);
+ expect(() => Buffer.byteLength({}, "latin1")).toThrow(TypeError);
+ expect(() => Buffer.byteLength()).toThrow(TypeError);
- assert(ArrayBuffer.isView(new Buffer(10)));
- assert(ArrayBuffer.isView(new SlowBuffer(10)));
- assert(ArrayBuffer.isView(Buffer.alloc(10)));
- assert(ArrayBuffer.isView(Buffer.allocUnsafe(10)));
- assert(ArrayBuffer.isView(Buffer.allocUnsafeSlow(10)));
- assert(ArrayBuffer.isView(Buffer.from("")));
+ expect(Buffer.byteLength("", undefined, true)).toBe(0);
// buffer
const incomplete = Buffer.from([0xe4, 0xb8, 0xad, 0xe6, 0x96]);
- assert.strictEqual(Buffer.byteLength(incomplete), 5);
+ expect(Buffer.byteLength(incomplete)).toBe(5);
const ascii = Buffer.from("abc");
- assert.strictEqual(Buffer.byteLength(ascii), 3);
+ expect(Buffer.byteLength(ascii)).toBe(3);
// ArrayBuffer
const buffer = new ArrayBuffer(8);
- assert.strictEqual(Buffer.byteLength(buffer), 8);
+ expect(Buffer.byteLength(buffer)).toBe(8);
// TypedArray
const int8 = new Int8Array(8);
- assert.strictEqual(Buffer.byteLength(int8), 8);
+ expect(Buffer.byteLength(int8)).toBe(8);
const uint8 = new Uint8Array(8);
- assert.strictEqual(Buffer.byteLength(uint8), 8);
+ expect(Buffer.byteLength(uint8)).toBe(8);
const uintc8 = new Uint8ClampedArray(2);
- assert.strictEqual(Buffer.byteLength(uintc8), 2);
+ expect(Buffer.byteLength(uintc8)).toBe(2);
const int16 = new Int16Array(8);
- assert.strictEqual(Buffer.byteLength(int16), 16);
+ expect(Buffer.byteLength(int16)).toBe(16);
const uint16 = new Uint16Array(8);
- assert.strictEqual(Buffer.byteLength(uint16), 16);
+ expect(Buffer.byteLength(uint16)).toBe(16);
const int32 = new Int32Array(8);
- assert.strictEqual(Buffer.byteLength(int32), 32);
+ expect(Buffer.byteLength(int32)).toBe(32);
const uint32 = new Uint32Array(8);
- assert.strictEqual(Buffer.byteLength(uint32), 32);
+ expect(Buffer.byteLength(uint32)).toBe(32);
const float32 = new Float32Array(8);
- assert.strictEqual(Buffer.byteLength(float32), 32);
+ expect(Buffer.byteLength(float32)).toBe(32);
const float64 = new Float64Array(8);
- assert.strictEqual(Buffer.byteLength(float64), 64);
+ expect(Buffer.byteLength(float64)).toBe(64);
// DataView
const dv = new DataView(new ArrayBuffer(2));
- assert.strictEqual(Buffer.byteLength(dv), 2);
+ expect(Buffer.byteLength(dv)).toBe(2);
// Special case: zero length string
- assert.strictEqual(Buffer.byteLength("", "ascii"), 0);
- assert.strictEqual(Buffer.byteLength("", "HeX"), 0);
+ expect(Buffer.byteLength("", "ascii")).toBe(0);
+ expect(Buffer.byteLength("", "HeX")).toBe(0);
// utf8
- assert.strictEqual(Buffer.byteLength("∑éllö wørl∂!", "utf-8"), 19);
- assert.strictEqual(Buffer.byteLength("κλμνξο", "utf8"), 12);
- assert.strictEqual(Buffer.byteLength("挵挶挷挸挹", "utf-8"), 15);
- assert.strictEqual(Buffer.byteLength("𠝹𠱓𠱸", "UTF8"), 12);
+ expect(Buffer.byteLength("∑éllö wørl∂!", "utf-8")).toBe(19);
+ expect(Buffer.byteLength("κλμνξο", "utf8")).toBe(12);
+ expect(Buffer.byteLength("挵挶挷挸挹", "utf-8")).toBe(15);
+ expect(Buffer.byteLength("𠝹𠱓𠱸", "UTF8")).toBe(12);
// Without an encoding, utf8 should be assumed
- assert.strictEqual(Buffer.byteLength("hey there"), 9);
- assert.strictEqual(Buffer.byteLength("𠱸挶νξ#xx :)"), 17);
- assert.strictEqual(Buffer.byteLength("hello world", ""), 11);
+ expect(Buffer.byteLength("hey there")).toBe(9);
+ expect(Buffer.byteLength("𠱸挶νξ#xx :)")).toBe(17);
+ expect(Buffer.byteLength("hello world", "")).toBe(11);
// It should also be assumed with unrecognized encoding
- assert.strictEqual(Buffer.byteLength("hello world", "abc"), 11);
- assert.strictEqual(Buffer.byteLength("ßœ∑≈", "unkn0wn enc0ding"), 10);
+ expect(Buffer.byteLength("hello world", "abc")).toBe(11);
+ expect(Buffer.byteLength("ßœ∑≈", "unkn0wn enc0ding")).toBe(10);
// base64
- assert.strictEqual(Buffer.byteLength("aGVsbG8gd29ybGQ=", "base64"), 11);
- assert.strictEqual(Buffer.byteLength("aGVsbG8gd29ybGQ=", "BASE64"), 11);
- assert.strictEqual(Buffer.byteLength("bm9kZS5qcyByb2NrcyE=", "base64"), 14);
- assert.strictEqual(Buffer.byteLength("aGkk", "base64"), 3);
- assert.strictEqual(Buffer.byteLength("bHNrZGZsa3NqZmtsc2xrZmFqc2RsZmtqcw==", "base64"), 25);
+ expect(Buffer.byteLength("aGVsbG8gd29ybGQ=", "base64")).toBe(11);
+ expect(Buffer.byteLength("aGVsbG8gd29ybGQ=", "BASE64")).toBe(11);
+ expect(Buffer.byteLength("bm9kZS5qcyByb2NrcyE=", "base64")).toBe(14);
+ expect(Buffer.byteLength("aGkk", "base64")).toBe(3);
+ expect(Buffer.byteLength("bHNrZGZsa3NqZmtsc2xrZmFqc2RsZmtqcw==", "base64")).toBe(25);
// base64url
- assert.strictEqual(Buffer.byteLength("aGVsbG8gd29ybGQ", "base64url"), 11);
- assert.strictEqual(Buffer.byteLength("aGVsbG8gd29ybGQ", "BASE64URL"), 11);
- assert.strictEqual(Buffer.byteLength("bm9kZS5qcyByb2NrcyE", "base64url"), 14);
- assert.strictEqual(Buffer.byteLength("aGkk", "base64url"), 3);
- assert.strictEqual(Buffer.byteLength("bHNrZGZsa3NqZmtsc2xrZmFqc2RsZmtqcw", "base64url"), 25);
+ expect(Buffer.byteLength("aGVsbG8gd29ybGQ", "base64url")).toBe(11);
+ expect(Buffer.byteLength("aGVsbG8gd29ybGQ", "BASE64URL")).toBe(11);
+ expect(Buffer.byteLength("bm9kZS5qcyByb2NrcyE", "base64url")).toBe(14);
+ expect(Buffer.byteLength("aGkk", "base64url")).toBe(3);
+ expect(Buffer.byteLength("bHNrZGZsa3NqZmtsc2xrZmFqc2RsZmtqcw", "base64url")).toBe(25);
// special padding
- assert.strictEqual(Buffer.byteLength("aaa=", "base64"), 2);
- assert.strictEqual(Buffer.byteLength("aaaa==", "base64"), 3);
- assert.strictEqual(Buffer.byteLength("aaa=", "base64url"), 2);
- assert.strictEqual(Buffer.byteLength("aaaa==", "base64url"), 3);
- assert.strictEqual(Buffer.byteLength("Il était tué", "utf8"), 14);
- assert.strictEqual(Buffer.byteLength("Il était tué"), 14);
+ expect(Buffer.byteLength("aaa=", "base64")).toBe(2);
+ expect(Buffer.byteLength("aaaa==", "base64")).toBe(3);
+ expect(Buffer.byteLength("aaa=", "base64url")).toBe(2);
+ expect(Buffer.byteLength("aaaa==", "base64url")).toBe(3);
+ expect(Buffer.byteLength("Il était tué", "utf8")).toBe(14);
+ expect(Buffer.byteLength("Il était tué")).toBe(14);
["ascii", "latin1", "binary"]
.reduce((es, e) => es.concat(e, e.toUpperCase()), [])
.forEach(encoding => {
- assert.strictEqual(Buffer.byteLength("Il était tué", encoding), 12);
+ expect(Buffer.byteLength("Il était tué", encoding)).toBe(12);
});
["ucs2", "ucs-2", "utf16le", "utf-16le"]
.reduce((es, e) => es.concat(e, e.toUpperCase()), [])
.forEach(encoding => {
- assert.strictEqual(Buffer.byteLength("Il était tué", encoding), 24);
+ expect(Buffer.byteLength("Il était tué", encoding)).toBe(24);
});
// Test that ArrayBuffer from a different context is detected correctly
// const arrayBuf = vm.runInNewContext("new ArrayBuffer()");
- // assert.strictEqual(Buffer.byteLength(arrayBuf), 0);
+ // expect(Buffer.byteLength(arrayBuf)).toBe(0);
// Verify that invalid encodings are treated as utf8
for (let i = 1; i < 10; i++) {
const encoding = String(i).repeat(i);
- assert.ok(!Buffer.isEncoding(encoding));
- assert.strictEqual(Buffer.byteLength("foo", encoding), Buffer.byteLength("foo", "utf8"));
+ expect(Buffer.isEncoding(encoding)).toBe(false);
+ expect(Buffer.byteLength("foo", encoding)).toBe(Buffer.byteLength("foo", "utf8"));
}
});