mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Compare commits
51 Commits
bun-v1.3.3
...
nektro-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a22eb7b24 | ||
|
|
c052ebfddf | ||
|
|
ab1e149cc7 | ||
|
|
8b17029b06 | ||
|
|
9201b88dcf | ||
|
|
fc3a95d834 | ||
|
|
4d49408ea3 | ||
|
|
37d3472b27 | ||
|
|
48eff0f334 | ||
|
|
befcab8421 | ||
|
|
4a332e6317 | ||
|
|
b692263c6f | ||
|
|
eeb2803a54 | ||
|
|
15c43040df | ||
|
|
e49cc4dcbf | ||
|
|
1cf31b8488 | ||
|
|
18b29695f5 | ||
|
|
9dff935580 | ||
|
|
7a911c12cb | ||
|
|
3778be8605 | ||
|
|
58b7515f3e | ||
|
|
d0eb4a6a6a | ||
|
|
d45c4d8bfb | ||
|
|
d56586eec6 | ||
|
|
d13a47f3be | ||
|
|
3b3c29e0d2 | ||
|
|
8fd46d40d3 | ||
|
|
72e5b7e60f | ||
|
|
3f810a3b2e | ||
|
|
af0fd9d318 | ||
|
|
db74f9c224 | ||
|
|
ba86ff19ed | ||
|
|
f108c3c6b6 | ||
|
|
5b650bc2e5 | ||
|
|
237e4df38c | ||
|
|
89795bfe35 | ||
|
|
eef6fc8496 | ||
|
|
28a7c40e29 | ||
|
|
8a9b9f5eb2 | ||
|
|
bdb97724aa | ||
|
|
ba777b8b76 | ||
|
|
814ac87c8a | ||
|
|
7535c58462 | ||
|
|
158c581be8 | ||
|
|
0168fa8593 | ||
|
|
fde51e72fd | ||
|
|
b2077dd113 | ||
|
|
975a339830 | ||
|
|
5d00fcde4c | ||
|
|
2699eda438 | ||
|
|
2a1a431c86 |
@@ -789,7 +789,6 @@ pub const FormatOptions = struct {
|
||||
if (try arg1.getBooleanLoose(globalThis, "sorted")) |opt| {
|
||||
formatOptions.ordered_properties = opt;
|
||||
}
|
||||
|
||||
if (try arg1.getBooleanLoose(globalThis, "compact")) |opt| {
|
||||
formatOptions.single_line = opt;
|
||||
}
|
||||
@@ -2262,7 +2261,7 @@ pub const Formatter = struct {
|
||||
this.addForNewLine(description.len + "()".len);
|
||||
writer.print(comptime Output.prettyFmt("<r><blue>Symbol({any})<r>", enable_ansi_colors), .{description});
|
||||
} else {
|
||||
writer.print(comptime Output.prettyFmt("<r><blue>Symbol<r>", enable_ansi_colors), .{});
|
||||
writer.print(comptime Output.prettyFmt("<r><blue>Symbol()<r>", enable_ansi_colors), .{});
|
||||
}
|
||||
},
|
||||
.Error => {
|
||||
|
||||
@@ -205,7 +205,6 @@ JSObject* createError(Zig::JSGlobalObject* globalObject, ErrorCode code, JSC::JS
|
||||
// export fn Bun__inspect(globalThis: *JSGlobalObject, value: JSValue) ZigString
|
||||
extern "C" ZigString Bun__inspect(JSC::JSGlobalObject* globalObject, JSValue value);
|
||||
|
||||
//
|
||||
WTF::String JSValueToStringSafe(JSC::JSGlobalObject* globalObject, JSValue arg)
|
||||
{
|
||||
ASSERT(!arg.isEmpty());
|
||||
@@ -379,13 +378,17 @@ WTF::String ERR_INVALID_ARG_TYPE(JSC::ThrowScope& scope, JSC::JSGlobalObject* gl
|
||||
unsigned length = expected_types.size();
|
||||
if (length == 1) {
|
||||
result.append(expected_types.at(0).toWTFString(globalObject));
|
||||
} else if (length == 2) {
|
||||
result.append(expected_types.at(0).toWTFString(globalObject));
|
||||
result.append(", or "_s);
|
||||
result.append(expected_types.at(1).toWTFString(globalObject));
|
||||
} else {
|
||||
for (unsigned i = 0; i < length - 1; i++) {
|
||||
JSValue expected_type = expected_types.at(i);
|
||||
if (i > 0) result.append(", "_s);
|
||||
result.append(expected_type.toWTFString(globalObject));
|
||||
}
|
||||
result.append(" or "_s);
|
||||
result.append(", or "_s);
|
||||
result.append(expected_types.at(length - 1).toWTFString(globalObject));
|
||||
}
|
||||
|
||||
@@ -434,6 +437,12 @@ WTF::String ERR_OUT_OF_RANGE(JSC::ThrowScope& scope, JSC::JSGlobalObject* global
|
||||
|
||||
namespace ERR {
|
||||
|
||||
JSC::EncodedJSValue throwCode(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, ErrorCode code, const WTF::String& message)
|
||||
{
|
||||
throwScope.throwException(globalObject, createError(globalObject, code, message));
|
||||
return {};
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue INVALID_ARG_TYPE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& arg_name, const WTF::String& expected_type, JSC::JSValue val_actual_value)
|
||||
{
|
||||
auto arg_kind = arg_name.contains('.') ? "property"_s : "argument"_s;
|
||||
@@ -529,7 +538,7 @@ JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObjec
|
||||
return {};
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue INVALID_ARG_VALUE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, WTF::ASCIILiteral name, JSC::JSValue value, const WTF::String& reason)
|
||||
JSC::EncodedJSValue INVALID_ARG_VALUE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& name, JSC::JSValue value, const WTF::String& reason)
|
||||
{
|
||||
ASCIILiteral type = String(name).contains('.') ? "property"_s : "argument"_s;
|
||||
|
||||
@@ -614,8 +623,12 @@ JSC::EncodedJSValue STRING_TOO_LONG(JSC::ThrowScope& throwScope, JSC::JSGlobalOb
|
||||
return {};
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue BUFFER_OUT_OF_BOUNDS(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject)
|
||||
JSC::EncodedJSValue BUFFER_OUT_OF_BOUNDS(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& name)
|
||||
{
|
||||
if (!name.isEmpty()) {
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_BUFFER_OUT_OF_BOUNDS, makeString("\""_s, name, "\" is outside of buffer bounds"_s)));
|
||||
return {};
|
||||
}
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_BUFFER_OUT_OF_BOUNDS, "Attempt to access memory outside buffer bounds"_s));
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -65,11 +65,13 @@ enum Bound {
|
||||
|
||||
namespace ERR {
|
||||
|
||||
JSC::EncodedJSValue throwCode(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, ErrorCode code, const WTF::String& message);
|
||||
|
||||
JSC::EncodedJSValue INVALID_ARG_TYPE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& arg_name, const WTF::String& expected_type, JSC::JSValue val_actual_value);
|
||||
JSC::EncodedJSValue INVALID_ARG_TYPE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue arg_name, const WTF::String& expected_type, JSC::JSValue val_actual_value);
|
||||
JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& arg_name, double lower, double upper, JSC::JSValue actual);
|
||||
JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue arg_name, double lower, double upper, JSC::JSValue actual);
|
||||
JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue arg_name_val, double bound_num, Bound bound, JSC::JSValue actual);
|
||||
JSC::EncodedJSValue INVALID_ARG_TYPE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue val_arg_name, const WTF::String& val_expected_type, JSC::JSValue val_actual_value);
|
||||
JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& arg_name, size_t lower, size_t upper, JSC::JSValue actual);
|
||||
JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue arg_name, size_t lower, size_t upper, JSC::JSValue actual);
|
||||
JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue arg_name_val, size_t bound_num, Bound bound, JSC::JSValue actual);
|
||||
JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue arg_name_val, const WTF::String& msg, JSC::JSValue actual);
|
||||
JSC::EncodedJSValue OUT_OF_RANGE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& arg_name_val, const WTF::String& msg, JSC::JSValue actual);
|
||||
JSC::EncodedJSValue INVALID_ARG_VALUE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, WTF::ASCIILiteral name, JSC::JSValue value, const WTF::String& reason = "is invalid"_s);
|
||||
@@ -78,7 +80,7 @@ JSC::EncodedJSValue INVALID_ARG_VALUE(JSC::ThrowScope& throwScope, JSC::JSGlobal
|
||||
JSC::EncodedJSValue UNKNOWN_ENCODING(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::StringView encoding);
|
||||
JSC::EncodedJSValue INVALID_STATE(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& statemsg);
|
||||
JSC::EncodedJSValue STRING_TOO_LONG(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject);
|
||||
JSC::EncodedJSValue BUFFER_OUT_OF_BOUNDS(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject);
|
||||
JSC::EncodedJSValue BUFFER_OUT_OF_BOUNDS(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, const WTF::String& name);
|
||||
JSC::EncodedJSValue UNKNOWN_SIGNAL(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue signal, bool triedUppercase = false);
|
||||
JSC::EncodedJSValue SOCKET_BAD_PORT(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject, JSC::JSValue name, JSC::JSValue port, bool allowZero);
|
||||
JSC::EncodedJSValue UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* globalObject);
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
// #include <JavaScriptCore/JSTypedArrayViewPrototype.h>
|
||||
#include <JavaScriptCore/JSArrayBufferViewInlines.h>
|
||||
|
||||
extern "C" bool Bun__Node__ZeroFillBuffers;
|
||||
|
||||
using namespace JSC;
|
||||
using namespace WebCore;
|
||||
|
||||
@@ -229,6 +231,7 @@ static JSUint8Array* allocBuffer(JSC::JSGlobalObject* lexicalGlobalObject, size_
|
||||
|
||||
return uint8Array;
|
||||
}
|
||||
|
||||
static JSUint8Array* allocBufferUnsafe(JSC::JSGlobalObject* lexicalGlobalObject, size_t byteLength)
|
||||
{
|
||||
|
||||
@@ -267,7 +270,7 @@ static int normalizeCompareVal(int val, size_t a_length, size_t b_length)
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline WebCore::BufferEncodingType parseEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSC::ThrowScope& scope, JSValue arg)
|
||||
static WebCore::BufferEncodingType parseEncoding(JSC::ThrowScope& scope, JSC::JSGlobalObject* lexicalGlobalObject, JSValue arg, bool validateUnknown)
|
||||
{
|
||||
auto arg_ = arg.toStringOrNull(lexicalGlobalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
@@ -275,6 +278,10 @@ static inline WebCore::BufferEncodingType parseEncoding(JSC::JSGlobalObject* lex
|
||||
|
||||
std::optional<BufferEncodingType> encoded = parseEnumeration2(*lexicalGlobalObject, view);
|
||||
if (UNLIKELY(!encoded)) {
|
||||
if (validateUnknown) {
|
||||
Bun::V::validateString(scope, lexicalGlobalObject, arg, "encoding"_s);
|
||||
RETURN_IF_EXCEPTION(scope, WebCore::BufferEncodingType::utf8);
|
||||
}
|
||||
Bun::ERR::UNKNOWN_ENCODING(scope, lexicalGlobalObject, view);
|
||||
return WebCore::BufferEncodingType::utf8;
|
||||
}
|
||||
@@ -282,6 +289,19 @@ static inline WebCore::BufferEncodingType parseEncoding(JSC::JSGlobalObject* lex
|
||||
return encoded.value();
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue validateOffset(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, JSC::JSValue name, JSC::JSValue min, JSC::JSValue max)
|
||||
{
|
||||
if (min.isUndefined()) min = jsDoubleNumber(0);
|
||||
if (max.isUndefined()) max = jsDoubleNumber(Bun::Buffer::kMaxLength);
|
||||
return Bun::V::validateInteger(scope, globalObject, value, name, min, max);
|
||||
}
|
||||
JSC::EncodedJSValue validateOffset(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, const WTF::String& name, JSC::JSValue min, JSC::JSValue max)
|
||||
{
|
||||
if (min.isUndefined()) min = jsDoubleNumber(0);
|
||||
if (max.isUndefined()) max = jsDoubleNumber(Bun::Buffer::kMaxLength);
|
||||
return Bun::V::validateInteger(scope, globalObject, value, name, min, max);
|
||||
}
|
||||
|
||||
namespace WebCore {
|
||||
using namespace JSC;
|
||||
|
||||
@@ -456,6 +476,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocUnsafeBody(JS
|
||||
size_t length = lengthValue.toLength(lexicalGlobalObject);
|
||||
auto result = allocBufferUnsafe(lexicalGlobalObject, length);
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
if (Bun__Node__ZeroFillBuffers) memset(result->typedVector(), 0, length);
|
||||
RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
|
||||
}
|
||||
|
||||
@@ -467,7 +488,7 @@ static inline JSC::EncodedJSValue constructBufferEmpty(JSGlobalObject* lexicalGl
|
||||
|
||||
static JSC::EncodedJSValue constructFromEncoding(JSGlobalObject* lexicalGlobalObject, JSString* str, WebCore::BufferEncodingType encoding)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
// Use ->view() here instead of ->value() as that will avoid flattening ropestrings from .slice()
|
||||
@@ -540,7 +561,7 @@ static JSC::EncodedJSValue constructFromEncoding(JSGlobalObject* lexicalGlobalOb
|
||||
|
||||
static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSValue arg0, JSValue arg1)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
|
||||
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
@@ -580,6 +601,12 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
size_t length = lengthValue.toLength(lexicalGlobalObject);
|
||||
|
||||
if (length == 0) {
|
||||
auto* uint8Array = createEmptyBuffer(lexicalGlobalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
RELEASE_AND_RETURN(scope, JSC::JSValue::encode(uint8Array));
|
||||
}
|
||||
|
||||
// fill argument
|
||||
if (UNLIKELY(callFrame->argumentCount() > 1)) {
|
||||
auto* uint8Array = createUninitializedBuffer(lexicalGlobalObject, length);
|
||||
@@ -595,7 +622,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG
|
||||
if (callFrame->argumentCount() > 2) {
|
||||
EnsureStillAliveScope arg2 = callFrame->uncheckedArgument(2);
|
||||
if (!arg2.value().isUndefined()) {
|
||||
encoding = parseEncoding(lexicalGlobalObject, scope, arg2.value());
|
||||
encoding = parseEncoding(scope, lexicalGlobalObject, arg2.value(), true);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
}
|
||||
}
|
||||
@@ -611,8 +638,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG
|
||||
ZigString str = Zig::toZigString(view);
|
||||
|
||||
if (UNLIKELY(!Bun__Buffer_fill(&str, startPtr, end - start, encoding))) {
|
||||
throwTypeError(lexicalGlobalObject, scope, "Failed to decode value"_s);
|
||||
return {};
|
||||
return Bun::ERR::throwCode(scope, lexicalGlobalObject, Bun::ErrorCode::ERR_INVALID_ARG_VALUE, "Failed to decode value"_s);
|
||||
}
|
||||
} else if (auto* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value)) {
|
||||
if (UNLIKELY(view->isDetached())) {
|
||||
@@ -622,8 +648,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG
|
||||
|
||||
size_t length = view->byteLength();
|
||||
if (UNLIKELY(length == 0)) {
|
||||
throwTypeError(lexicalGlobalObject, scope, "Buffer cannot be empty"_s);
|
||||
return {};
|
||||
return Bun::ERR::throwCode(scope, lexicalGlobalObject, Bun::ErrorCode::ERR_INVALID_ARG_VALUE, "Buffer cannot be empty"_s);
|
||||
}
|
||||
|
||||
auto* start = uint8Array->typedVector();
|
||||
@@ -692,9 +717,10 @@ static inline JSC::EncodedJSValue jsBufferByteLengthFromStringAndEncoding(JSC::J
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferConstructorFunction_byteLengthBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
|
||||
WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
|
||||
|
||||
@@ -732,7 +758,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_byteLengthBody(JSC
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferConstructorFunction_compareBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto castedThisValue = callFrame->argument(0);
|
||||
@@ -780,20 +806,15 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_compareBody(JSC::J
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
if (callFrame->argumentCount() < 1) {
|
||||
return constructBufferEmpty(lexicalGlobalObject);
|
||||
}
|
||||
|
||||
auto arrayValue = callFrame->uncheckedArgument(0);
|
||||
auto array = JSC::jsDynamicCast<JSC::JSArray*>(arrayValue);
|
||||
if (!array) {
|
||||
throwTypeError(lexicalGlobalObject, throwScope, "Argument must be an array"_s);
|
||||
return {};
|
||||
}
|
||||
auto listValue = callFrame->argument(0);
|
||||
|
||||
Bun::V::validateArray(throwScope, lexicalGlobalObject, listValue, "list"_s, jsUndefined());
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
auto array = JSC::jsDynamicCast<JSC::JSArray*>(listValue);
|
||||
size_t arrayLength = array->length();
|
||||
if (arrayLength < 1) {
|
||||
RELEASE_AND_RETURN(throwScope, constructBufferEmpty(lexicalGlobalObject));
|
||||
@@ -816,22 +837,20 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JS
|
||||
JSValue element = array->getIndex(lexicalGlobalObject, i);
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
if (auto* bufferView = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(element)) {
|
||||
if (UNLIKELY(bufferView->isDetached())) {
|
||||
throwVMTypeError(lexicalGlobalObject, throwScope, "ArrayBufferView is detached"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
auto length = bufferView->byteLength();
|
||||
|
||||
if (length > 0)
|
||||
args.append(element);
|
||||
|
||||
byteLength += length;
|
||||
} else {
|
||||
throwTypeError(lexicalGlobalObject, throwScope, "Buffer.concat expects Buffer or Uint8Array"_s);
|
||||
return {};
|
||||
auto* typedArray = JSC::jsDynamicCast<JSC::JSUint8Array*>(element);
|
||||
if (!typedArray) {
|
||||
return Bun::ERR::INVALID_ARG_TYPE(throwScope, lexicalGlobalObject, makeString("list["_s, i, "]"_s), "Buffer or Uint8Array"_s, element);
|
||||
}
|
||||
if (UNLIKELY(typedArray->isDetached())) {
|
||||
return throwVMTypeError(lexicalGlobalObject, throwScope, "ArrayBufferView is detached"_s);
|
||||
}
|
||||
|
||||
auto length = typedArray->byteLength();
|
||||
|
||||
if (length > 0)
|
||||
args.append(element);
|
||||
|
||||
byteLength += length;
|
||||
}
|
||||
|
||||
size_t availableLength = byteLength;
|
||||
@@ -866,7 +885,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JS
|
||||
|
||||
size_t remain = byteLength;
|
||||
auto* head = outBuffer->typedVector();
|
||||
const int arrayLengthI = arrayLength;
|
||||
const int arrayLengthI = args.size();
|
||||
for (int i = 0; i < arrayLengthI && remain > 0; i++) {
|
||||
auto* bufferView = JSC::jsCast<JSC::JSArrayBufferView*>(args.at(i));
|
||||
size_t length = std::min(remain, bufferView->byteLength());
|
||||
@@ -887,7 +906,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JS
|
||||
// https://github.com/nodejs/node/blob/v22.9.0/lib/buffer.js#L337
|
||||
static inline JSC::EncodedJSValue jsBufferConstructorFunction_copyBytesFromBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto viewValue = callFrame->argument(0);
|
||||
@@ -991,7 +1010,7 @@ STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBufferPrototype, JSBufferPrototype::Base);
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_compareBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto arg0 = callFrame->argument(0);
|
||||
@@ -1103,7 +1122,7 @@ static double toInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObjec
|
||||
// https://github.com/nodejs/node/blob/v22.9.0/lib/buffer.js#L205
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_copyBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto targetValue = callFrame->argument(0);
|
||||
@@ -1169,7 +1188,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_copyBody(JSC::JSGlob
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_equalsBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
if (callFrame->argumentCount() < 1) {
|
||||
throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
|
||||
@@ -1201,9 +1220,10 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_equalsBody(JSC::JSGl
|
||||
|
||||
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsBoolean(normalizeCompareVal(result, a_length, b_length) == 0)));
|
||||
}
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
if (callFrame->argumentCount() < 1) {
|
||||
@@ -1242,8 +1262,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob
|
||||
}
|
||||
|
||||
if (!encodingValue.isUndefined() && value.isString()) {
|
||||
if (!encodingValue.isString()) return Bun::ERR::INVALID_ARG_TYPE(scope, lexicalGlobalObject, "encoding"_s, "string"_s, encodingValue);
|
||||
encoding = parseEncoding(lexicalGlobalObject, scope, encodingValue);
|
||||
encoding = parseEncoding(scope, lexicalGlobalObject, encodingValue, true);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
}
|
||||
|
||||
@@ -1286,8 +1305,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob
|
||||
|
||||
size_t length = view->byteLength();
|
||||
if (UNLIKELY(length == 0)) {
|
||||
throwTypeError(lexicalGlobalObject, scope, "Buffer cannot be empty"_s);
|
||||
return {};
|
||||
return Bun::ERR::throwCode(scope, lexicalGlobalObject, Bun::ErrorCode::ERR_INVALID_ARG_VALUE, "Buffer cannot be empty"_s);
|
||||
}
|
||||
|
||||
length = std::min(length, remain);
|
||||
@@ -1339,6 +1357,28 @@ static int64_t indexOf(const uint8_t* thisPtr, int64_t thisLength, const uint8_t
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int64_t indexOf16(const uint8_t* thisPtr, int64_t thisLength, const uint8_t* valuePtr, int64_t valueLength, int64_t byteOffset)
|
||||
{
|
||||
size_t finalresult = 0;
|
||||
if (thisLength == 1) return -1;
|
||||
thisLength = thisLength / 2 * 2;
|
||||
if (valueLength == 1) return -1;
|
||||
valueLength = valueLength / 2 * 2;
|
||||
byteOffset = byteOffset / 2 * 2;
|
||||
while (true) {
|
||||
auto res = indexOf(thisPtr, thisLength, valuePtr, valueLength, byteOffset);
|
||||
if (res == -1) return -1;
|
||||
if (res % 2 == 1) {
|
||||
thisPtr += res + 1;
|
||||
thisLength -= res + 1;
|
||||
finalresult += res + 1;
|
||||
continue;
|
||||
}
|
||||
finalresult += res;
|
||||
return finalresult;
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t lastIndexOf(const uint8_t* thisPtr, int64_t thisLength, const uint8_t* valuePtr, int64_t valueLength, int64_t byteOffset)
|
||||
{
|
||||
auto start = thisPtr;
|
||||
@@ -1350,108 +1390,128 @@ static int64_t lastIndexOf(const uint8_t* thisPtr, int64_t thisLength, const uin
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int64_t indexOf(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis, bool last)
|
||||
static ssize_t indexOfOffset(size_t length, ssize_t offset_i64, ssize_t needle_length, bool is_forward)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
ssize_t length_i64 = static_cast<ssize_t>(length);
|
||||
if (offset_i64 < 0) {
|
||||
if (offset_i64 + length_i64 >= 0) {
|
||||
// Negative offsets count backwards from the end of the buffer.
|
||||
return length_i64 + offset_i64;
|
||||
} else if (is_forward || needle_length == 0) {
|
||||
// indexOf from before the start of the buffer: search the whole buffer.
|
||||
return 0;
|
||||
} else {
|
||||
// lastIndexOf from before the start of the buffer: no match.
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (offset_i64 + needle_length <= length_i64) {
|
||||
// Valid positive offset.
|
||||
return offset_i64;
|
||||
} else if (needle_length == 0) {
|
||||
// Out of buffer bounds, but empty needle: point to end of buffer.
|
||||
return length_i64;
|
||||
} else if (is_forward) {
|
||||
// indexOf from past the end of the buffer: no match.
|
||||
return -1;
|
||||
} else {
|
||||
// lastIndexOf from past the end of the buffer: search the whole buffer.
|
||||
return length_i64 - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t indexOf(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter buffer, bool last)
|
||||
{
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
if (callFrame->argumentCount() < 1) {
|
||||
throwVMError(lexicalGlobalObject, scope, createNotEnoughArgumentsError(lexicalGlobalObject));
|
||||
bool dir = !last;
|
||||
const uint8_t* typedVector = buffer->typedVector();
|
||||
size_t byteLength = buffer->byteLength();
|
||||
std::optional<BufferEncodingType> encoding = std::nullopt;
|
||||
|
||||
if (byteLength == 0) return -1;
|
||||
|
||||
auto valueValue = callFrame->argument(0);
|
||||
auto byteOffsetValue = callFrame->argument(1);
|
||||
auto encodingValue = callFrame->argument(2);
|
||||
|
||||
if (byteOffsetValue.isString()) {
|
||||
encodingValue = byteOffsetValue;
|
||||
byteOffsetValue = jsUndefined();
|
||||
} else {
|
||||
double byteOffset = byteOffsetValue.toNumber(lexicalGlobalObject);
|
||||
RETURN_IF_EXCEPTION(scope, -1);
|
||||
if (byteOffset > 0x7fffffffp0f) byteOffsetValue = jsDoubleNumber(0x7fffffffp0f);
|
||||
if (byteOffset < -0x80000000p0f) byteOffsetValue = jsDoubleNumber(-0x80000000p0f);
|
||||
}
|
||||
|
||||
byteOffsetValue = jsDoubleNumber(byteOffsetValue.toNumber(lexicalGlobalObject));
|
||||
RETURN_IF_EXCEPTION(scope, -1);
|
||||
if (std::isnan(byteOffsetValue.asNumber())) byteOffsetValue = jsNumber(dir ? 0 : byteLength);
|
||||
|
||||
if (valueValue.isNumber()) {
|
||||
ssize_t byteOffset = indexOfOffset(byteLength, byteOffsetValue.asNumber(), 1, dir);
|
||||
if (byteOffset == -1) return -1;
|
||||
uint8_t byteValue = (valueValue.toInt32(lexicalGlobalObject)) % 256;
|
||||
RETURN_IF_EXCEPTION(scope, -1);
|
||||
if (last) {
|
||||
for (int64_t i = byteOffset; i >= 0; --i) {
|
||||
if (byteValue == typedVector[i]) return i;
|
||||
}
|
||||
} else {
|
||||
const void* offset = memchr(reinterpret_cast<const void*>(typedVector + byteOffset), byteValue, byteLength - byteOffset);
|
||||
if (offset != NULL) return static_cast<const uint8_t*>(offset) - typedVector;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto value = callFrame->uncheckedArgument(0);
|
||||
WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
|
||||
|
||||
int64_t length = static_cast<int64_t>(castedThis->byteLength());
|
||||
const uint8_t* typedVector = castedThis->typedVector();
|
||||
|
||||
int64_t byteOffset = last ? length - 1 : 0;
|
||||
|
||||
if (callFrame->argumentCount() > 1) {
|
||||
EnsureStillAliveScope arg1 = callFrame->uncheckedArgument(1);
|
||||
if (arg1.value().isString()) {
|
||||
encoding = parseEncoding(lexicalGlobalObject, scope, arg1.value());
|
||||
RETURN_IF_EXCEPTION(scope, -1);
|
||||
} else {
|
||||
auto byteOffset_ = arg1.value().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_);
|
||||
} else {
|
||||
byteOffset = static_cast<int64_t>(byteOffset_);
|
||||
}
|
||||
|
||||
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 (callFrame->argumentCount() > 2) {
|
||||
EnsureStillAliveScope encodingValue = callFrame->uncheckedArgument(2);
|
||||
if (!encodingValue.value().isUndefined()) {
|
||||
encoding = parseEncoding(lexicalGlobalObject, scope, encodingValue.value());
|
||||
RETURN_IF_EXCEPTION(scope, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
WTF::String encodingString;
|
||||
if (!encodingValue.isUndefined()) {
|
||||
encodingString = encodingValue.toWTFString(lexicalGlobalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
encoding = parseEnumeration2(*lexicalGlobalObject, encodingString);
|
||||
} else {
|
||||
encoding = BufferEncodingType::utf8;
|
||||
}
|
||||
|
||||
if (value.isString()) {
|
||||
auto* str = value.toStringOrNull(lexicalGlobalObject);
|
||||
if (valueValue.isString()) {
|
||||
if (!encoding.has_value()) {
|
||||
return Bun::ERR::UNKNOWN_ENCODING(scope, lexicalGlobalObject, encodingString);
|
||||
}
|
||||
auto* str = valueValue.toStringOrNull(lexicalGlobalObject);
|
||||
RETURN_IF_EXCEPTION(scope, -1);
|
||||
|
||||
JSC::EncodedJSValue encodedBuffer = constructFromEncoding(lexicalGlobalObject, str, encoding);
|
||||
ssize_t byteOffset = indexOfOffset(byteLength, byteOffsetValue.asNumber(), str->length(), dir);
|
||||
if (byteOffset == -1) return -1;
|
||||
if (str->length() == 0) return byteOffset;
|
||||
JSC::EncodedJSValue encodedBuffer = constructFromEncoding(lexicalGlobalObject, str, encoding.value());
|
||||
auto* arrayValue = JSC::jsDynamicCast<JSC::JSUint8Array*>(JSC::JSValue::decode(encodedBuffer));
|
||||
int64_t lengthValue = static_cast<int64_t>(arrayValue->byteLength());
|
||||
const uint8_t* typedVectorValue = arrayValue->typedVector();
|
||||
if (last) {
|
||||
return lastIndexOf(typedVector, length, typedVectorValue, lengthValue, byteOffset);
|
||||
return lastIndexOf(typedVector, byteLength, typedVectorValue, lengthValue, byteOffset);
|
||||
} else {
|
||||
return indexOf(typedVector, length, typedVectorValue, lengthValue, byteOffset);
|
||||
if (encoding.value() == BufferEncodingType::ucs2) return indexOf16(typedVector, byteLength, typedVectorValue, lengthValue, byteOffset);
|
||||
return indexOf(typedVector, byteLength, typedVectorValue, lengthValue, byteOffset);
|
||||
}
|
||||
} else if (value.isNumber()) {
|
||||
uint8_t byteValue = static_cast<uint8_t>((value.toInt32(lexicalGlobalObject)) % 256);
|
||||
RETURN_IF_EXCEPTION(scope, -1);
|
||||
|
||||
if (last) {
|
||||
for (int64_t i = byteOffset; i >= 0; --i) {
|
||||
if (byteValue == typedVector[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const void* offset = memchr(reinterpret_cast<const void*>(typedVector + byteOffset), byteValue, length - byteOffset);
|
||||
if (offset != NULL) {
|
||||
return static_cast<int64_t>(static_cast<const uint8_t*>(offset) - typedVector);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
} else if (auto* arrayValue = JSC::jsDynamicCast<JSC::JSUint8Array*>(value)) {
|
||||
size_t lengthValue = arrayValue->byteLength();
|
||||
const uint8_t* typedVectorValue = arrayValue->typedVector();
|
||||
if (last) {
|
||||
return lastIndexOf(typedVector, length, typedVectorValue, lengthValue, byteOffset);
|
||||
} else {
|
||||
return indexOf(typedVector, length, typedVectorValue, lengthValue, byteOffset);
|
||||
}
|
||||
} else {
|
||||
throwTypeError(lexicalGlobalObject, scope, "Invalid value type"_s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (auto* array = JSC::jsDynamicCast<JSC::JSUint8Array*>(valueValue)) {
|
||||
if (!encoding.has_value()) encoding = BufferEncodingType::utf8;
|
||||
size_t lengthValue = array->byteLength();
|
||||
ssize_t byteOffset = indexOfOffset(byteLength, byteOffsetValue.asNumber(), lengthValue, dir);
|
||||
if (byteOffset == -1) return -1;
|
||||
if (lengthValue == 0) return byteOffset;
|
||||
const uint8_t* typedVectorValue = array->typedVector();
|
||||
if (last) {
|
||||
return lastIndexOf(typedVector, byteLength, typedVectorValue, lengthValue, byteOffset);
|
||||
} else {
|
||||
if (encoding.value() == BufferEncodingType::ucs2) return indexOf16(typedVector, byteLength, typedVectorValue, lengthValue, byteOffset);
|
||||
return indexOf(typedVector, byteLength, typedVectorValue, lengthValue, byteOffset);
|
||||
}
|
||||
}
|
||||
|
||||
Bun::ERR::INVALID_ARG_TYPE(scope, lexicalGlobalObject, "value"_s, "number, string, Buffer, or Uint8Array"_s, valueValue);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1460,19 +1520,22 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_includesBody(JSC::JS
|
||||
auto index = indexOf(lexicalGlobalObject, callFrame, castedThis, false);
|
||||
return JSC::JSValue::encode(jsBoolean(index != -1));
|
||||
}
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_indexOfBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto index = indexOf(lexicalGlobalObject, callFrame, castedThis, false);
|
||||
return JSC::JSValue::encode(jsNumber(index));
|
||||
}
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_lastIndexOfBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto index = indexOf(lexicalGlobalObject, callFrame, castedThis, true);
|
||||
return JSC::JSValue::encode(jsNumber(index));
|
||||
}
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap16Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
constexpr int elemSize = 2;
|
||||
@@ -1499,9 +1562,10 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap16Body(JSC::JSGl
|
||||
|
||||
return JSC::JSValue::encode(castedThis);
|
||||
}
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap32Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
constexpr int elemSize = 4;
|
||||
@@ -1533,9 +1597,10 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap32Body(JSC::JSGl
|
||||
|
||||
return JSC::JSValue::encode(castedThis);
|
||||
}
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap64Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
constexpr size_t elemSize = 8;
|
||||
@@ -1662,7 +1727,7 @@ bool inline parseArrayIndex(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalO
|
||||
// using byteLength and byte offsets here is intentional
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
uint32_t start = 0;
|
||||
uint32_t end = castedThis->byteLength();
|
||||
@@ -1682,7 +1747,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS
|
||||
return jsBufferToString(vm, lexicalGlobalObject, castedThis, start, end, encoding);
|
||||
|
||||
if (!arg1.isUndefined()) {
|
||||
encoding = parseEncoding(lexicalGlobalObject, scope, arg1);
|
||||
encoding = parseEncoding(scope, lexicalGlobalObject, arg1, false);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
}
|
||||
|
||||
@@ -1716,7 +1781,7 @@ lstart:
|
||||
template<BufferEncodingType encoding>
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_SliceWithEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto* castedThis = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(callFrame->thisValue());
|
||||
const JSValue startValue = callFrame->argument(0);
|
||||
@@ -1808,7 +1873,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeEncodingBody(JS
|
||||
template<BufferEncodingType encoding>
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunctionWriteWithEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto* castedThis = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(callFrame->thisValue());
|
||||
|
||||
@@ -1833,93 +1898,64 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunctionWriteWithEncoding(JSC
|
||||
|
||||
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSArrayBufferView>::ClassParameter castedThis)
|
||||
{
|
||||
auto& vm = JSC::getVM(lexicalGlobalObject);
|
||||
uint32_t offset = 0;
|
||||
uint32_t length = castedThis->byteLength();
|
||||
uint32_t max = length;
|
||||
WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8;
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
if (UNLIKELY(callFrame->argumentCount() == 0)) {
|
||||
throwTypeError(lexicalGlobalObject, scope, "Not enough arguments"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
EnsureStillAliveScope arg0 = callFrame->argument(0);
|
||||
auto* str = arg0.value().toStringOrNull(lexicalGlobalObject);
|
||||
if (!str) {
|
||||
throwTypeError(lexicalGlobalObject, scope, "write() expects a string"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
JSValue offsetValue = jsUndefined();
|
||||
JSValue lengthValue = jsUndefined();
|
||||
JSValue encodingValue = jsUndefined();
|
||||
|
||||
switch (callFrame->argumentCount()) {
|
||||
case 4:
|
||||
encodingValue = callFrame->uncheckedArgument(3);
|
||||
FALLTHROUGH;
|
||||
case 3:
|
||||
lengthValue = callFrame->uncheckedArgument(2);
|
||||
FALLTHROUGH;
|
||||
case 2:
|
||||
offsetValue = callFrame->uncheckedArgument(1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
auto setEncoding = [&]() {
|
||||
if (!encodingValue.isUndefined()) {
|
||||
encoding = parseEncoding(lexicalGlobalObject, scope, encodingValue);
|
||||
}
|
||||
};
|
||||
auto stringValue = callFrame->argument(0);
|
||||
auto offsetValue = callFrame->argument(1);
|
||||
auto lengthValue = callFrame->argument(2);
|
||||
auto encodingValue = callFrame->argument(3);
|
||||
|
||||
if (offsetValue.isUndefined()) {
|
||||
// https://github.com/nodejs/node/blob/e676942f814915b2d24fc899bb42dc71ae6c8226/lib/buffer.js#L1053
|
||||
RELEASE_AND_RETURN(scope, writeToBuffer(lexicalGlobalObject, castedThis, str, offset, length, encoding));
|
||||
Bun::V::validateString(scope, lexicalGlobalObject, stringValue, "string"_s);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto* str = stringValue.toString(lexicalGlobalObject);
|
||||
uint32_t offset = 0;
|
||||
uint32_t length = castedThis->byteLength();
|
||||
RELEASE_AND_RETURN(scope, writeToBuffer(lexicalGlobalObject, castedThis, str, offset, length, WebCore::BufferEncodingType::utf8));
|
||||
}
|
||||
|
||||
if (lengthValue.isUndefined() && offsetValue.isString()) {
|
||||
// https://github.com/nodejs/node/blob/e676942f814915b2d24fc899bb42dc71ae6c8226/lib/buffer.js#L1056
|
||||
encodingValue = offsetValue;
|
||||
setEncoding();
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
RELEASE_AND_RETURN(scope, writeToBuffer(lexicalGlobalObject, castedThis, str, offset, length, encoding));
|
||||
}
|
||||
|
||||
if (UNLIKELY(!offsetValue.isNumber())) {
|
||||
throwTypeError(lexicalGlobalObject, scope, "Invalid offset"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
int32_t userOffset = offsetValue.toInt32(lexicalGlobalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
if (userOffset < 0 || userOffset > max) {
|
||||
throwNodeRangeError(lexicalGlobalObject, scope, "Offset is out of bounds"_s);
|
||||
return {};
|
||||
}
|
||||
offset = static_cast<uint32_t>(userOffset);
|
||||
uint32_t remaining = max - static_cast<uint32_t>(userOffset);
|
||||
|
||||
// https://github.com/nodejs/node/blob/e676942f814915b2d24fc899bb42dc71ae6c8226/lib/buffer.js#L1062-L1077
|
||||
if (lengthValue.isUndefined()) {
|
||||
length = remaining;
|
||||
} else if (lengthValue.isString()) {
|
||||
encodingValue = lengthValue;
|
||||
setEncoding();
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
length = remaining;
|
||||
lengthValue = jsNumber(castedThis->byteLength());
|
||||
offsetValue = jsNumber(0);
|
||||
} else {
|
||||
setEncoding();
|
||||
|
||||
int32_t userLength = lengthValue.toInt32(lexicalGlobalObject);
|
||||
uint32_t length = castedThis->byteLength();
|
||||
validateOffset(scope, lexicalGlobalObject, offsetValue, "offset"_s, jsNumber(0), jsNumber(length));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
length = std::min(static_cast<uint32_t>(userLength), remaining);
|
||||
uint32_t offset = offsetValue.toUInt32(lexicalGlobalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
uint32_t remaining = castedThis->byteLength() - offset;
|
||||
|
||||
if (lengthValue.isUndefined()) {
|
||||
lengthValue = jsNumber(remaining);
|
||||
} else if (lengthValue.isString()) {
|
||||
encodingValue = lengthValue;
|
||||
lengthValue = jsNumber(remaining);
|
||||
} else {
|
||||
validateOffset(scope, lexicalGlobalObject, lengthValue, "length"_s, jsNumber(0), jsNumber(length));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
length = lengthValue.toUInt32(lexicalGlobalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
if (length > remaining) lengthValue = jsNumber(remaining);
|
||||
}
|
||||
}
|
||||
|
||||
Bun::V::validateString(scope, lexicalGlobalObject, stringValue, "string"_s);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto* str = stringValue.toString(lexicalGlobalObject);
|
||||
uint32_t offset = offsetValue.toUInt32(lexicalGlobalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
uint32_t length = lengthValue.toUInt32(lexicalGlobalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
if (!encodingValue.toBoolean(lexicalGlobalObject)) {
|
||||
RELEASE_AND_RETURN(scope, writeToBuffer(lexicalGlobalObject, castedThis, str, offset, length, WebCore::BufferEncodingType::utf8));
|
||||
}
|
||||
|
||||
auto encoding = parseEncoding(scope, lexicalGlobalObject, encodingValue, false);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
RELEASE_AND_RETURN(scope, writeToBuffer(lexicalGlobalObject, castedThis, str, offset, length, encoding));
|
||||
}
|
||||
|
||||
@@ -2249,7 +2285,6 @@ 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::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_utf16leSlice, 2 } },
|
||||
{ "ucs2Write"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_utf16leWrite, 3 } },
|
||||
@@ -2301,6 +2336,8 @@ void JSBufferPrototype::finishCreation(VM& vm, JSC::JSGlobalObject* globalThis)
|
||||
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
|
||||
reifyStaticProperties(vm, JSBuffer::info(), JSBufferPrototypeTableValues, *this);
|
||||
|
||||
ALIAS("toLocaleString", "toString");
|
||||
|
||||
ALIAS("readUintBE", "readUIntBE");
|
||||
ALIAS("readUintLE", "readUIntLE");
|
||||
ALIAS("readUint8", "readUInt8");
|
||||
@@ -2378,6 +2415,128 @@ JSC::JSObject* createBufferConstructor(JSC::VM& vm, JSC::JSGlobalObject* globalO
|
||||
|
||||
} // namespace WebCore
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsFunction_BufferFrom_Array, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto arrayValue = callFrame->argument(0);
|
||||
|
||||
return constructBufferFromArray(throwScope, lexicalGlobalObject, arrayValue);
|
||||
}
|
||||
EncodedJSValue constructBufferFromArray(JSC::ThrowScope& throwScope, JSGlobalObject* lexicalGlobalObject, JSValue arrayValue)
|
||||
{
|
||||
auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
|
||||
|
||||
auto* constructor = lexicalGlobalObject->m_typedArrayUint8.constructor(lexicalGlobalObject);
|
||||
MarkedArgumentBuffer argsBuffer;
|
||||
argsBuffer.append(arrayValue);
|
||||
JSValue target = globalObject->JSBufferConstructor();
|
||||
// TODO: I wish we could avoid this - it adds ~30ns of overhead just using JSC::construct.
|
||||
auto* object = JSC::construct(lexicalGlobalObject, constructor, target, argsBuffer, "Buffer failed to construct"_s);
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(object));
|
||||
}
|
||||
JSC_DEFINE_HOST_FUNCTION(jsFunction_BufferFrom_ArrayBuffer, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
auto argsCount = callFrame->argumentCount();
|
||||
|
||||
auto arrayBufferValue = callFrame->argument(0);
|
||||
auto offsetValue = callFrame->argument(1);
|
||||
auto lengthValue = callFrame->argument(2);
|
||||
|
||||
return constructBufferFromArrayBuffer(throwScope, lexicalGlobalObject, argsCount, arrayBufferValue, offsetValue, lengthValue);
|
||||
}
|
||||
EncodedJSValue constructBufferFromArrayBuffer(JSC::ThrowScope& throwScope, JSGlobalObject* lexicalGlobalObject, size_t argsCount, JSValue arrayBufferValue, JSValue offsetValue, JSValue lengthValue)
|
||||
{
|
||||
auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
|
||||
|
||||
auto* jsBuffer = jsCast<JSC::JSArrayBuffer*>(arrayBufferValue.asCell());
|
||||
RefPtr<ArrayBuffer> buffer = jsBuffer->impl();
|
||||
if (buffer->isDetached()) {
|
||||
// TOOD: return Node.js error
|
||||
throwTypeError(globalObject, throwScope, "Buffer is detached"_s);
|
||||
return {};
|
||||
}
|
||||
size_t byteLength = buffer->byteLength();
|
||||
double byteLengthD = byteLength;
|
||||
|
||||
// This closely matches `new Uint8Array(buffer, byteOffset, length)` in JavaScriptCore's implementation.
|
||||
// See Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h
|
||||
size_t offset = 0;
|
||||
std::optional<size_t> length;
|
||||
size_t maxLength = byteLength;
|
||||
if (argsCount > 1) {
|
||||
|
||||
if (!offsetValue.isUndefined()) {
|
||||
offsetValue = jsDoubleNumber(offsetValue.toNumber(lexicalGlobalObject));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
if (std::isnan(offsetValue.asNumber())) offsetValue = jsNumber(0);
|
||||
if ((byteLengthD - offsetValue.asNumber()) < 0) return Bun::ERR::BUFFER_OUT_OF_BOUNDS(throwScope, lexicalGlobalObject, "offset"_s);
|
||||
maxLength = byteLengthD - offsetValue.asNumber();
|
||||
offset = offsetValue.asNumber();
|
||||
}
|
||||
|
||||
if (!lengthValue.isUndefined()) {
|
||||
lengthValue = jsDoubleNumber(lengthValue.toNumber(lexicalGlobalObject));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
if (std::isnan(lengthValue.asNumber())) lengthValue = jsNumber(0);
|
||||
length = lengthValue.asNumber();
|
||||
if (length > 0) {
|
||||
if (length > maxLength) {
|
||||
return Bun::ERR::BUFFER_OUT_OF_BOUNDS(throwScope, lexicalGlobalObject, "length"_s);
|
||||
}
|
||||
} else {
|
||||
length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (offset > byteLength) {
|
||||
return Bun::ERR::BUFFER_OUT_OF_BOUNDS(throwScope, globalObject, "offset"_s);
|
||||
}
|
||||
|
||||
if (!length) {
|
||||
if (buffer->isResizableOrGrowableShared()) {
|
||||
if (UNLIKELY(offset > byteLength)) {
|
||||
return Bun::ERR::BUFFER_OUT_OF_BOUNDS(throwScope, globalObject, "byteOffset"_s);
|
||||
}
|
||||
} else {
|
||||
length = (byteLength - offset);
|
||||
}
|
||||
}
|
||||
if (offset + length.value() > byteLength) {
|
||||
return Bun::ERR::BUFFER_OUT_OF_BOUNDS(throwScope, globalObject, "length"_s);
|
||||
}
|
||||
|
||||
auto* subclassStructure = globalObject->JSBufferSubclassStructure();
|
||||
auto* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, WTFMove(buffer), offset, length);
|
||||
if (UNLIKELY(!uint8Array)) {
|
||||
throwOutOfMemoryError(globalObject, throwScope);
|
||||
return JSC::JSValue::encode({});
|
||||
}
|
||||
|
||||
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array));
|
||||
}
|
||||
JSC_DEFINE_HOST_FUNCTION(jsFunction_BufferFrom_Size, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = lexicalGlobalObject->vm();
|
||||
auto throwScope = DECLARE_THROW_SCOPE(vm);
|
||||
auto lengthValue = callFrame->argument(0);
|
||||
Bun::V::validateNumber(throwScope, lexicalGlobalObject, lengthValue, "size"_s, jsNumber(0), jsNumber(Bun::Buffer::kMaxLength));
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
size_t length = lengthValue.toLength(lexicalGlobalObject);
|
||||
return JSBuffer__bufferFromLength(lexicalGlobalObject, length);
|
||||
}
|
||||
JSC_DEFINE_HOST_FUNCTION(jsFunction_BufferFrom_String, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto stringValue = callFrame->argument(0);
|
||||
auto encodingValue = callFrame->argument(1);
|
||||
return constructBufferFromStringAndEncoding(lexicalGlobalObject, stringValue, encodingValue);
|
||||
}
|
||||
|
||||
static inline JSC::EncodedJSValue createJSBufferFromJS(JSC::JSGlobalObject* lexicalGlobalObject, JSValue newTarget, ArgList args)
|
||||
{
|
||||
VM& vm = lexicalGlobalObject->vm();
|
||||
@@ -2474,56 +2633,7 @@ static inline JSC::EncodedJSValue createJSBufferFromJS(JSC::JSGlobalObject* lexi
|
||||
case ArrayBufferType: {
|
||||
// This closely matches `new Uint8Array(buffer, byteOffset, length)` in JavaScriptCore's implementation.
|
||||
// See Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h
|
||||
size_t offset = 0;
|
||||
std::optional<size_t> length;
|
||||
if (argsCount > 1) {
|
||||
|
||||
offset = args.at(1).toTypedArrayIndex(globalObject, "byteOffset"_s);
|
||||
|
||||
// TOOD: return Node.js error
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
|
||||
if (argsCount > 2) {
|
||||
// If the length value is present but undefined, treat it as missing.
|
||||
JSValue lengthValue = args.at(2);
|
||||
if (!lengthValue.isUndefined()) {
|
||||
length = lengthValue.toTypedArrayIndex(globalObject, "length"_s);
|
||||
|
||||
// TOOD: return Node.js error
|
||||
RETURN_IF_EXCEPTION(throwScope, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto* jsBuffer = jsCast<JSC::JSArrayBuffer*>(distinguishingArg.asCell());
|
||||
RefPtr<ArrayBuffer> buffer = jsBuffer->impl();
|
||||
if (buffer->isDetached()) {
|
||||
// TOOD: return Node.js error
|
||||
throwTypeError(globalObject, throwScope, "Buffer is detached"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!length) {
|
||||
size_t byteLength = buffer->byteLength();
|
||||
if (buffer->isResizableOrGrowableShared()) {
|
||||
if (UNLIKELY(offset > byteLength)) {
|
||||
// TOOD: return Node.js error
|
||||
throwNodeRangeError(globalObject, throwScope, "byteOffset exceeds source ArrayBuffer byteLength"_s);
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
length = (byteLength - offset);
|
||||
}
|
||||
}
|
||||
|
||||
auto* subclassStructure = globalObject->JSBufferSubclassStructure();
|
||||
auto* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, WTFMove(buffer), offset, length);
|
||||
if (UNLIKELY(!uint8Array)) {
|
||||
throwOutOfMemoryError(globalObject, throwScope);
|
||||
return JSC::JSValue::encode({});
|
||||
}
|
||||
|
||||
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array));
|
||||
return constructBufferFromArrayBuffer(throwScope, lexicalGlobalObject, args.size(), distinguishingArg, args.at(1), args.at(2));
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
@@ -2531,24 +2641,7 @@ static inline JSC::EncodedJSValue createJSBufferFromJS(JSC::JSGlobalObject* lexi
|
||||
}
|
||||
}
|
||||
|
||||
JSC::JSObject* constructor = lexicalGlobalObject->m_typedArrayUint8.constructor(lexicalGlobalObject);
|
||||
|
||||
MarkedArgumentBuffer argsBuffer;
|
||||
argsBuffer.append(distinguishingArg);
|
||||
for (size_t i = 1; i < argsCount; ++i)
|
||||
argsBuffer.append(args.at(i));
|
||||
|
||||
JSValue target = newTarget;
|
||||
if (!target || !target.isCell()) {
|
||||
target = globalObject->JSBufferConstructor();
|
||||
}
|
||||
|
||||
JSC::JSObject* object = JSC::construct(lexicalGlobalObject, constructor, target, args, "Buffer failed to construct"_s);
|
||||
if (!object) {
|
||||
return JSC::JSValue::encode({});
|
||||
}
|
||||
|
||||
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(object));
|
||||
return constructBufferFromArray(throwScope, lexicalGlobalObject, distinguishingArg);
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(callJSBuffer, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame))
|
||||
|
||||
@@ -67,3 +67,11 @@ JSC::Structure* createBufferStructure(JSC::VM&, JSC::JSGlobalObject*, JSC::JSVal
|
||||
JSC::JSObject* createBufferConstructor(JSC::VM&, JSC::JSGlobalObject*, JSC::JSObject* bufferPrototype);
|
||||
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsFunction_BufferFrom_Array, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame));
|
||||
JSC_DEFINE_HOST_FUNCTION(jsFunction_BufferFrom_ArrayBuffer, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame));
|
||||
JSC_DEFINE_HOST_FUNCTION(jsFunction_BufferFrom_Size, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame));
|
||||
JSC_DEFINE_HOST_FUNCTION(jsFunction_BufferFrom_String, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame));
|
||||
|
||||
JSC::EncodedJSValue constructBufferFromArrayBuffer(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* lexicalGlobalObject, size_t argsCount, JSC::JSValue arrayBufferValue, JSC::JSValue offsetValue, JSC::JSValue lengthValue);
|
||||
JSC::EncodedJSValue constructBufferFromArray(JSC::ThrowScope& throwScope, JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSValue arrayValue);
|
||||
|
||||
@@ -100,7 +100,27 @@ JSC::EncodedJSValue V::validateNumber(JSC::ThrowScope& scope, JSC::JSGlobalObjec
|
||||
if (max_isnonnull) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, max_num, Bun::UPPER, value);
|
||||
return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, ""_s, value);
|
||||
}
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
JSC::EncodedJSValue V::validateNumber(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, const WTF::String& name, JSValue min, JSValue max)
|
||||
{
|
||||
if (!value.isNumber()) return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, name, "number"_s, value);
|
||||
|
||||
auto value_num = value.asNumber();
|
||||
auto min_num = min.toNumber(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto max_num = max.toNumber(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
auto min_isnonnull = !min.isUndefinedOrNull();
|
||||
auto max_isnonnull = !max.isUndefinedOrNull();
|
||||
|
||||
if ((min_isnonnull && value_num < min_num) || (max_isnonnull && value_num > max_num) || ((min_isnonnull || max_isnonnull) && std::isnan(value_num))) {
|
||||
if (min_isnonnull && max_isnonnull) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, min_num, max_num, value);
|
||||
if (min_isnonnull) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, min_num, Bun::LOWER, value);
|
||||
if (max_isnonnull) return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, max_num, Bun::UPPER, value);
|
||||
return Bun::ERR::OUT_OF_RANGE(scope, globalObject, name, ""_s, value);
|
||||
}
|
||||
return JSValue::encode(jsUndefined());
|
||||
}
|
||||
JSC::EncodedJSValue V::validateNumber(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, ASCIILiteral name, JSValue min, JSValue max)
|
||||
@@ -533,6 +553,12 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateBuffer, (JSC::JSGlobalObject * globa
|
||||
|
||||
auto buffer = callFrame->argument(0);
|
||||
auto name = callFrame->argument(1);
|
||||
return V::validateBuffer(scope, globalObject, buffer, name);
|
||||
}
|
||||
JSC::EncodedJSValue V::validateBuffer(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue buffer, JSValue nameValue)
|
||||
{
|
||||
auto name = nameValue.isUndefined() ? "buffer"_s : nameValue.toWTFString(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
if (!buffer.isCell()) return JSValue::encode(jsUndefined());
|
||||
auto ty = buffer.asCell()->type();
|
||||
|
||||
@@ -26,6 +26,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateBuffer, (JSC::JSGlobalObject * globa
|
||||
|
||||
namespace V {
|
||||
|
||||
JSC::EncodedJSValue validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, const WTF::String& name, JSC::JSValue min, JSC::JSValue max);
|
||||
JSC::EncodedJSValue validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, JSC::JSValue name, JSC::JSValue min, JSC::JSValue max);
|
||||
JSC::EncodedJSValue validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, ASCIILiteral name, JSC::JSValue min, JSC::JSValue max);
|
||||
JSC::EncodedJSValue validateNumber(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSC::JSValue value, JSC::JSValue name, JSC::JSValue min, JSC::JSValue max);
|
||||
@@ -34,6 +35,7 @@ JSC::EncodedJSValue validateFiniteNumber(JSC::ThrowScope& scope, JSC::JSGlobalOb
|
||||
JSC::EncodedJSValue validateString(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name);
|
||||
JSC::EncodedJSValue validateString(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, ASCIILiteral name);
|
||||
JSC::EncodedJSValue validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name, JSValue minLength);
|
||||
JSC::EncodedJSValue validateBuffer(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue buffer, JSValue name);
|
||||
JSC::EncodedJSValue validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, ASCIILiteral name, JSValue minLength);
|
||||
JSC::EncodedJSValue validateUint32(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name, JSValue positive);
|
||||
JSC::EncodedJSValue validateUint32(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, ASCIILiteral name, JSValue positive);
|
||||
|
||||
@@ -687,7 +687,7 @@ pub const ZigString = extern struct {
|
||||
return (@intFromPtr(this._unsafe_ptr_do_not_use) & (1 << 63)) != 0;
|
||||
}
|
||||
|
||||
pub inline fn utf16Slice(this: *const ZigString) []align(1) const u16 {
|
||||
pub fn utf16Slice(this: *const ZigString) []align(1) const u16 {
|
||||
if (comptime bun.Environment.allow_assert) {
|
||||
if (this.len > 0 and !this.is16Bit()) {
|
||||
@panic("ZigString.utf16Slice() called on a latin1 string.\nPlease use .toSlice() instead or carefully check that .is16Bit() is false first.");
|
||||
@@ -697,7 +697,7 @@ pub const ZigString = extern struct {
|
||||
return @as([*]align(1) const u16, @ptrCast(untagged(this._unsafe_ptr_do_not_use)))[0..this.len];
|
||||
}
|
||||
|
||||
pub inline fn utf16SliceAligned(this: *const ZigString) []const u16 {
|
||||
pub fn utf16SliceAligned(this: *const ZigString) []const u16 {
|
||||
if (comptime bun.Environment.allow_assert) {
|
||||
if (this.len > 0 and !this.is16Bit()) {
|
||||
@panic("ZigString.utf16SliceAligned() called on a latin1 string.\nPlease use .toSlice() instead or carefully check that .is16Bit() is false first.");
|
||||
|
||||
@@ -49,6 +49,8 @@ pub const BufferVectorized = struct {
|
||||
Encoder.writeU8(str.slice().ptr, str.slice().len, buf.ptr, buf.len, .hex),
|
||||
} catch return false;
|
||||
|
||||
if (written == 0 and str.length() > 0) return false;
|
||||
|
||||
switch (written) {
|
||||
0 => return true,
|
||||
1 => {
|
||||
|
||||
@@ -1248,7 +1248,7 @@ pub const Encoder = struct {
|
||||
},
|
||||
|
||||
.hex => {
|
||||
return strings.decodeHexToBytes(to_ptr[0..to_len], u8, input[0..len]);
|
||||
return strings.decodeHexToBytesTruncate(to_ptr[0..to_len], u8, input[0..len]);
|
||||
},
|
||||
|
||||
.base64, .base64url => {
|
||||
@@ -1327,7 +1327,7 @@ pub const Encoder = struct {
|
||||
},
|
||||
|
||||
.hex => {
|
||||
return strings.decodeHexToBytes(to[0..to_len], u16, input[0..len]);
|
||||
return strings.decodeHexToBytesTruncate(to[0..to_len], u16, input[0..len]);
|
||||
},
|
||||
|
||||
.base64, .base64url => {
|
||||
|
||||
@@ -47,6 +47,7 @@ pub var start_time: i128 = undefined;
|
||||
const Bunfig = @import("./bunfig.zig").Bunfig;
|
||||
const OOM = bun.OOM;
|
||||
|
||||
export var Bun__Node__ZeroFillBuffers = false;
|
||||
export var Bun__Node__ProcessNoDeprecation = false;
|
||||
export var Bun__Node__ProcessThrowDeprecation = false;
|
||||
|
||||
@@ -236,6 +237,8 @@ pub const Arguments = struct {
|
||||
clap.parseParam("--conditions <STR>... Pass custom conditions to resolve") catch unreachable,
|
||||
clap.parseParam("--fetch-preconnect <STR>... Preconnect to a URL while code is loading") catch unreachable,
|
||||
clap.parseParam("--max-http-header-size <INT> Set the maximum size of HTTP headers in bytes. Default is 16KiB") catch unreachable,
|
||||
clap.parseParam("--expose-internals Expose internals used for testing Bun itself. Usage of these APIs are completely unsupported.") catch unreachable,
|
||||
clap.parseParam("--zero-fill-buffers Boolean to force Buffer.allocUnsafe(size) to be zero-filled.") catch unreachable,
|
||||
clap.parseParam("--dns-result-order <STR> Set the default order of DNS lookup results. Valid orders: verbatim (default), ipv4first, ipv6first") catch unreachable,
|
||||
clap.parseParam("--expose-gc Expose gc() on the global object. Has no effect on Bun.gc().") catch unreachable,
|
||||
clap.parseParam("--no-deprecation Suppress all reporting of the custom deprecation.") catch unreachable,
|
||||
@@ -813,6 +816,9 @@ pub const Arguments = struct {
|
||||
if (args.option("--title")) |title| {
|
||||
Bun__Node__ProcessTitle = title;
|
||||
}
|
||||
if (args.flag("--zero-fill-buffers")) {
|
||||
Bun__Node__ZeroFillBuffers = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.port != null and opts.origin == null) {
|
||||
|
||||
6
src/js/builtins.d.ts
vendored
6
src/js/builtins.d.ts
vendored
@@ -582,7 +582,11 @@ interface String {
|
||||
}
|
||||
|
||||
declare var $Buffer: {
|
||||
new (a: any, b?: any, c?: any): Buffer;
|
||||
new (array: Array): Buffer;
|
||||
new (arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;
|
||||
new (buffer: Buffer): Buffer;
|
||||
new (size: number): Buffer;
|
||||
new (string: string, encoding?: BufferEncoding): Buffer;
|
||||
};
|
||||
|
||||
declare interface Error {
|
||||
|
||||
@@ -1,78 +1,37 @@
|
||||
// This is marked as a constructor because Node.js allows `new Buffer.from`,
|
||||
// Some legacy dependencies depend on this, see #3638
|
||||
$constructor;
|
||||
export function from(items) {
|
||||
if ($isUndefinedOrNull(items)) {
|
||||
throw new TypeError(
|
||||
"The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object.",
|
||||
);
|
||||
}
|
||||
export function from(value, encodingOrOffset, length) {
|
||||
const { fromString, fromArrayBuffer, fromObject } = require("internal/buffer");
|
||||
const { isAnyArrayBuffer } = require("node:util/types");
|
||||
|
||||
// TODO: figure out why private symbol not found
|
||||
if (
|
||||
typeof items === "string" ||
|
||||
(typeof items === "object" &&
|
||||
($isTypedArrayView(items) ||
|
||||
items instanceof ArrayBuffer ||
|
||||
items instanceof SharedArrayBuffer ||
|
||||
items instanceof String))
|
||||
) {
|
||||
switch ($argumentCount()) {
|
||||
case 1: {
|
||||
return new $Buffer(items);
|
||||
}
|
||||
case 2: {
|
||||
return new $Buffer(items, $argument(1));
|
||||
}
|
||||
default: {
|
||||
return new $Buffer(items, $argument(1), $argument(2));
|
||||
}
|
||||
if (typeof value === "string") return fromString(value, encodingOrOffset);
|
||||
|
||||
if (typeof value === "object" && value !== null) {
|
||||
if (isAnyArrayBuffer(value)) return fromArrayBuffer(value, encodingOrOffset, length);
|
||||
|
||||
const valueOf = value.valueOf && value.valueOf();
|
||||
if (valueOf != null && valueOf !== value && (typeof valueOf === "string" || typeof valueOf === "object")) {
|
||||
return Buffer.from(valueOf, encodingOrOffset, length);
|
||||
}
|
||||
}
|
||||
if (typeof items === "object") {
|
||||
const data = items.data;
|
||||
if (items.type === "Buffer" && Array.isArray(data)) {
|
||||
return new $Buffer(data);
|
||||
}
|
||||
}
|
||||
|
||||
var arrayLike = $toObject(
|
||||
items,
|
||||
"The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object.",
|
||||
) as ArrayLike<any>;
|
||||
|
||||
if (!$isJSArray(arrayLike)) {
|
||||
const toPrimitive = $tryGetByIdWithWellKnownSymbol(items, "toPrimitive");
|
||||
|
||||
if (toPrimitive) {
|
||||
const primitive = toPrimitive.$call(items, "string");
|
||||
const b = fromObject(value);
|
||||
if (b) return b;
|
||||
|
||||
const toPrimitive = $tryGetByIdWithWellKnownSymbol(value, "toPrimitive");
|
||||
if (typeof toPrimitive === "function") {
|
||||
const primitive = toPrimitive.$call(value, "string");
|
||||
if (typeof primitive === "string") {
|
||||
switch ($argumentCount()) {
|
||||
case 1: {
|
||||
return new $Buffer(primitive);
|
||||
}
|
||||
case 2: {
|
||||
return new $Buffer(primitive, $argument(1));
|
||||
}
|
||||
default: {
|
||||
return new $Buffer(primitive, $argument(1), $argument(2));
|
||||
}
|
||||
}
|
||||
return fromString(primitive, encodingOrOffset);
|
||||
}
|
||||
}
|
||||
|
||||
if (!("length" in arrayLike) || $isCallable(arrayLike)) {
|
||||
throw new TypeError(
|
||||
"The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't pass the second argument because Node's Buffer.from doesn't accept
|
||||
// a function and Uint8Array.from requires it if it exists
|
||||
// That means we cannot use $tailCallFowrardArguments here, sadly
|
||||
return new $Buffer(Uint8Array.from(arrayLike).buffer);
|
||||
throw $ERR_INVALID_ARG_TYPE(
|
||||
"first argument",
|
||||
["string", "Buffer", "ArrayBuffer", "Array", "Array-like Object"],
|
||||
value,
|
||||
);
|
||||
}
|
||||
|
||||
export function isBuffer(bufferlike) {
|
||||
|
||||
@@ -8,46 +8,93 @@ interface BufferExt extends Buffer {
|
||||
toString(offset: number, length: number, encoding?: BufferEncoding): string;
|
||||
}
|
||||
|
||||
export function setBigUint64(this: BufferExt, offset, value, le) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setBigUint64(
|
||||
offset,
|
||||
value,
|
||||
le,
|
||||
);
|
||||
}
|
||||
export function readInt8(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getInt8(offset);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 1);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getInt8(offset);
|
||||
}
|
||||
|
||||
export function readUInt8(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getUint8(offset);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 1);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getUint8(offset);
|
||||
}
|
||||
|
||||
export function readInt16LE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getInt16(offset, true);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 2);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getInt16(offset, true);
|
||||
}
|
||||
|
||||
export function readInt16BE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getInt16(offset, false);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 2);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getInt16(offset, false);
|
||||
}
|
||||
|
||||
export function readUInt16LE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getUint16(offset, true);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 2);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getUint16(offset, true);
|
||||
}
|
||||
|
||||
export function readUInt16BE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getUint16(offset, false);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 2);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getUint16(offset, false);
|
||||
}
|
||||
|
||||
export function readInt32LE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getInt32(offset, true);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 4);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getInt32(offset, true);
|
||||
}
|
||||
|
||||
export function readInt32BE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getInt32(offset, false);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 4);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getInt32(offset, false);
|
||||
}
|
||||
|
||||
export function readUInt32LE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getUint32(offset, true);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 4);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getUint32(offset, true);
|
||||
}
|
||||
|
||||
export function readUInt32BE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getUint32(offset, false);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 4);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getUint32(offset, false);
|
||||
}
|
||||
|
||||
export function readIntLE(this: BufferExt, offset, byteLength) {
|
||||
const { ERR_INVALID_ARG_TYPE, validateInteger, boundsError } = require("internal/buffer");
|
||||
if (offset === undefined) throw ERR_INVALID_ARG_TYPE("offset", "number", offset);
|
||||
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
|
||||
switch (byteLength) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
validateInteger(offset, "offset");
|
||||
if (!(offset >= 0 && offset <= this.length - byteLength)) boundsError(offset, this.length - byteLength);
|
||||
break;
|
||||
}
|
||||
switch (byteLength) {
|
||||
case 1: {
|
||||
return view.getInt8(offset);
|
||||
@@ -71,10 +118,26 @@ export function readIntLE(this: BufferExt, offset, byteLength) {
|
||||
return (last | ((last & (2 ** 15)) * 0x1fffe)) * 2 ** 32 + view.getUint32(offset, true);
|
||||
}
|
||||
}
|
||||
throw new RangeError("byteLength must be >= 1 and <= 6");
|
||||
boundsError(byteLength, 6, "byteLength");
|
||||
}
|
||||
|
||||
export function readIntBE(this: BufferExt, offset, byteLength) {
|
||||
const { ERR_INVALID_ARG_TYPE, validateInteger, boundsError } = require("internal/buffer");
|
||||
if (offset === undefined) throw ERR_INVALID_ARG_TYPE("offset", "number", offset);
|
||||
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
|
||||
switch (byteLength) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
validateInteger(offset, "offset");
|
||||
if (!(offset >= 0 && offset <= this.length - byteLength)) boundsError(offset, this.length - byteLength);
|
||||
break;
|
||||
}
|
||||
switch (byteLength) {
|
||||
case 1: {
|
||||
return view.getInt8(offset);
|
||||
@@ -98,10 +161,26 @@ export function readIntBE(this: BufferExt, offset, byteLength) {
|
||||
return (last | ((last & (2 ** 15)) * 0x1fffe)) * 2 ** 32 + view.getUint32(offset + 2, false);
|
||||
}
|
||||
}
|
||||
throw new RangeError("byteLength must be >= 1 and <= 6");
|
||||
boundsError(byteLength, 6, "byteLength");
|
||||
}
|
||||
|
||||
export function readUIntLE(this: BufferExt, offset, byteLength) {
|
||||
const { ERR_INVALID_ARG_TYPE, validateInteger, boundsError } = require("internal/buffer");
|
||||
if (offset === undefined) throw ERR_INVALID_ARG_TYPE("offset", "number", offset);
|
||||
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
|
||||
switch (byteLength) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
validateInteger(offset, "offset");
|
||||
if (!(offset >= 0 && offset <= this.length - byteLength)) boundsError(offset, this.length - byteLength);
|
||||
break;
|
||||
}
|
||||
switch (byteLength) {
|
||||
case 1: {
|
||||
return view.getUint8(offset);
|
||||
@@ -122,10 +201,26 @@ export function readUIntLE(this: BufferExt, offset, byteLength) {
|
||||
return view.getUint16(offset + 4, true) * 2 ** 32 + view.getUint32(offset, true);
|
||||
}
|
||||
}
|
||||
throw new RangeError("byteLength must be >= 1 and <= 6");
|
||||
boundsError(byteLength, 6, "byteLength");
|
||||
}
|
||||
|
||||
export function readUIntBE(this: BufferExt, offset, byteLength) {
|
||||
const { ERR_INVALID_ARG_TYPE, validateInteger, boundsError } = require("internal/buffer");
|
||||
if (offset === undefined) throw ERR_INVALID_ARG_TYPE("offset", "number", offset);
|
||||
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
|
||||
switch (byteLength) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
validateInteger(offset, "offset");
|
||||
if (!(offset >= 0 && offset <= this.length - byteLength)) boundsError(offset, this.length - byteLength);
|
||||
break;
|
||||
}
|
||||
switch (byteLength) {
|
||||
case 1: {
|
||||
return view.getUint8(offset);
|
||||
@@ -146,331 +241,404 @@ export function readUIntBE(this: BufferExt, offset, byteLength) {
|
||||
return view.getUint16(offset, false) * 2 ** 32 + view.getUint32(offset + 2, false);
|
||||
}
|
||||
}
|
||||
throw new RangeError("byteLength must be >= 1 and <= 6");
|
||||
boundsError(byteLength, 6, "byteLength");
|
||||
}
|
||||
|
||||
export function readFloatLE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getFloat32(offset, true);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 4);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getFloat32(offset, true);
|
||||
}
|
||||
|
||||
export function readFloatBE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getFloat32(offset, false);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 4);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getFloat32(offset, false);
|
||||
}
|
||||
|
||||
export function readDoubleLE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getFloat64(offset, true);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 8);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getFloat64(offset, true);
|
||||
}
|
||||
|
||||
export function readDoubleBE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getFloat64(offset, false);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 8);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getFloat64(offset, false);
|
||||
}
|
||||
|
||||
export function readBigInt64LE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getBigInt64(offset, true);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 8);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getBigInt64(offset, true);
|
||||
}
|
||||
|
||||
export function readBigInt64BE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getBigInt64(offset, false);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 8);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getBigInt64(offset, false);
|
||||
}
|
||||
|
||||
export function readBigUInt64LE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getBigUint64(offset, true);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 8);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getBigUint64(offset, true);
|
||||
}
|
||||
|
||||
export function readBigUInt64BE(this: BufferExt, offset) {
|
||||
return (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).getBigUint64(offset, false);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_read(this, offset, 8);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
return view.getBigUint64(offset, false);
|
||||
}
|
||||
|
||||
export function writeInt8(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setInt8(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").check_int8(this, value, offset, -0x80, 0x7f);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setInt8(offset, value);
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
export function writeUInt8(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setUint8(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").check_int8(this, value, offset, 0, 0xff);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setUint8(offset, value);
|
||||
return offset + 1;
|
||||
}
|
||||
|
||||
export function writeInt16LE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setInt16(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").check_int16(this, value, offset, -0x8000, 0x7fff);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setInt16(offset, value, true);
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
export function writeInt16BE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setInt16(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
false,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").check_int16(this, value, offset, -0x8000, 0x7fff);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setInt16(offset, value, false);
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
export function writeUInt16LE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setUint16(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").check_int16(this, value, offset, 0, 0xffff);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setUint16(offset, value, true);
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
export function writeUInt16BE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setUint16(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
false,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").check_int16(this, value, offset, 0, 0xffff);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setUint16(offset, value, false);
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
export function writeInt32LE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setInt32(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").check_int32(this, value, offset, -0x80000000, 0x7fffffff);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setInt32(offset, value, true);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
export function writeInt32BE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setInt32(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
false,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").check_int32(this, value, offset, -0x80000000, 0x7fffffff);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setInt32(offset, value, false);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
export function writeUInt32LE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setUint32(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").check_int32(this, value, offset, 0, 0xffffffff);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setUint32(offset, value, true);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
export function writeUInt32BE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setUint32(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
false,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").check_int32(this, value, offset, 0, 0xffffffff);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setUint32(offset, value, false);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
export function writeIntLE(this: BufferExt, value, offset, byteLength) {
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
value = +value;
|
||||
|
||||
switch (byteLength) {
|
||||
case 1: {
|
||||
require("internal/buffer").check_int8(this, value, offset, -0x80, 0x7f);
|
||||
view.setInt8(offset, value);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
require("internal/buffer").check_int16(this, value, offset, -0x8000, 0x7fff);
|
||||
view.setInt16(offset, value, true);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
require("internal/buffer").check_int24(this, value, offset, -0x800000, 0x7fffff);
|
||||
view.setUint16(offset, value & 0xffff, true);
|
||||
view.setInt8(offset + 2, Math.floor(value * 2 ** -16));
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
require("internal/buffer").check_int32(this, value, offset, -0x80000000, 0x7fffffff);
|
||||
view.setInt32(offset, value, true);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
require("internal/buffer").check_int40(this, value, offset, -0x8000000000, 0x7fffffffff);
|
||||
view.setUint32(offset, value | 0, true);
|
||||
view.setInt8(offset + 4, Math.floor(value * 2 ** -32));
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
require("internal/buffer").check_int48(this, value, offset, -0x800000000000, 0x7fffffffffff);
|
||||
view.setUint32(offset, value | 0, true);
|
||||
view.setInt16(offset + 4, Math.floor(value * 2 ** -32), true);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new RangeError("byteLength must be >= 1 and <= 6");
|
||||
require("internal/buffer").boundsError(byteLength, 6, "byteLength");
|
||||
}
|
||||
}
|
||||
return offset + byteLength;
|
||||
}
|
||||
|
||||
export function writeIntBE(this: BufferExt, value, offset, byteLength) {
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
value = +value;
|
||||
|
||||
switch (byteLength) {
|
||||
case 1: {
|
||||
require("internal/buffer").check_int8(this, value, offset, -0x80, 0x7f);
|
||||
view.setInt8(offset, value);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
require("internal/buffer").check_int16(this, value, offset, -0x8000, 0x7fff);
|
||||
view.setInt16(offset, value, false);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
require("internal/buffer").check_int24(this, value, offset, -0x800000, 0x7fffff);
|
||||
view.setUint16(offset + 1, value & 0xffff, false);
|
||||
view.setInt8(offset, Math.floor(value * 2 ** -16));
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
require("internal/buffer").check_int32(this, value, offset, -0x80000000, 0x7fffffff);
|
||||
view.setInt32(offset, value, false);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
require("internal/buffer").check_int40(this, value, offset, -0x8000000000, 0x7fffffffff);
|
||||
view.setUint32(offset + 1, value | 0, false);
|
||||
view.setInt8(offset, Math.floor(value * 2 ** -32));
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
require("internal/buffer").check_int48(this, value, offset, -0x800000000000, 0x7fffffffffff);
|
||||
view.setUint32(offset + 2, value | 0, false);
|
||||
view.setInt16(offset, Math.floor(value * 2 ** -32), false);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new RangeError("byteLength must be >= 1 and <= 6");
|
||||
require("internal/buffer").boundsError(byteLength, 6, "byteLength");
|
||||
}
|
||||
}
|
||||
return offset + byteLength;
|
||||
}
|
||||
|
||||
export function writeUIntLE(this: BufferExt, value, offset, byteLength) {
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
value = +value;
|
||||
|
||||
switch (byteLength) {
|
||||
case 1: {
|
||||
require("internal/buffer").check_int8(this, value, offset, 0, 0xff);
|
||||
view.setUint8(offset, value);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
require("internal/buffer").check_int16(this, value, offset, 0, 0xffff);
|
||||
view.setUint16(offset, value, true);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
require("internal/buffer").check_int24(this, value, offset, 0, 0xffffff);
|
||||
view.setUint16(offset, value & 0xffff, true);
|
||||
view.setUint8(offset + 2, Math.floor(value * 2 ** -16));
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
require("internal/buffer").check_int32(this, value, offset, 0, 0xffffffff);
|
||||
view.setUint32(offset, value, true);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
require("internal/buffer").check_int40(this, value, offset, 0, 0xffffffffff);
|
||||
view.setUint32(offset, value | 0, true);
|
||||
view.setUint8(offset + 4, Math.floor(value * 2 ** -32));
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
require("internal/buffer").check_int48(this, value, offset, 0, 0xffffffffffff);
|
||||
view.setUint32(offset, value | 0, true);
|
||||
view.setUint16(offset + 4, Math.floor(value * 2 ** -32), true);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new RangeError("byteLength must be >= 1 and <= 6");
|
||||
require("internal/buffer").boundsError(byteLength, 6, "byteLength");
|
||||
}
|
||||
}
|
||||
return offset + byteLength;
|
||||
}
|
||||
|
||||
export function writeUIntBE(this: BufferExt, value, offset, byteLength) {
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
value = +value;
|
||||
|
||||
switch (byteLength) {
|
||||
case 1: {
|
||||
require("internal/buffer").check_int8(this, value, offset, 0, 0xff);
|
||||
view.setUint8(offset, value);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
require("internal/buffer").check_int16(this, value, offset, 0, 0xffff);
|
||||
view.setUint16(offset, value, false);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
require("internal/buffer").check_int24(this, value, offset, 0, 0xffffff);
|
||||
view.setUint16(offset + 1, value & 0xffff, false);
|
||||
view.setUint8(offset, Math.floor(value * 2 ** -16));
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
require("internal/buffer").check_int32(this, value, offset, 0, 0xffffffff);
|
||||
view.setUint32(offset, value, false);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
require("internal/buffer").check_int40(this, value, offset, 0, 0xffffffffff);
|
||||
view.setUint32(offset + 1, value | 0, false);
|
||||
view.setUint8(offset, Math.floor(value * 2 ** -32));
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
require("internal/buffer").check_int48(this, value, offset, 0, 0xffffffffffff);
|
||||
view.setUint32(offset + 2, value | 0, false);
|
||||
view.setUint16(offset, Math.floor(value * 2 ** -32), false);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new RangeError("byteLength must be >= 1 and <= 6");
|
||||
require("internal/buffer").boundsError(byteLength, 6, "byteLength");
|
||||
}
|
||||
}
|
||||
return offset + byteLength;
|
||||
}
|
||||
|
||||
export function writeFloatLE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setFloat32(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").checkBounds(this, offset, 3);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setFloat32(offset, value, true);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
export function writeFloatBE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setFloat32(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
false,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").checkBounds(this, offset, 3);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setFloat32(offset, value, false);
|
||||
return offset + 4;
|
||||
}
|
||||
|
||||
export function writeDoubleLE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setFloat64(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").checkBounds(this, offset, 7);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setFloat64(offset, value, true);
|
||||
return offset + 8;
|
||||
}
|
||||
|
||||
export function writeDoubleBE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setFloat64(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
false,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
value = +value;
|
||||
require("internal/buffer").checkBounds(this, offset, 7);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setFloat64(offset, value, false);
|
||||
return offset + 8;
|
||||
}
|
||||
|
||||
export function writeBigInt64LE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setBigInt64(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_bigint64(this, value, offset, -0x8000000000000000n, 0x7fffffffffffffffn);
|
||||
if (typeof value !== "bigint") throw require("internal/buffer").ERR_INVALID_ARG_TYPE("value", "bigint", value);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setBigInt64(offset, value, true);
|
||||
return offset + 8;
|
||||
}
|
||||
|
||||
export function writeBigInt64BE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setBigInt64(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
false,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_bigint64(this, value, offset, -0x8000000000000000n, 0x7fffffffffffffffn);
|
||||
if (typeof value !== "bigint") throw require("internal/buffer").ERR_INVALID_ARG_TYPE("value", "bigint", value);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setBigInt64(offset, value, false);
|
||||
return offset + 8;
|
||||
}
|
||||
|
||||
export function writeBigUInt64LE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setBigUint64(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
true,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_bigint64(this, value, offset, 0n, 0xffffffffffffffffn);
|
||||
if (typeof value !== "bigint") throw require("internal/buffer").ERR_INVALID_ARG_TYPE("value", "bigint", value);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setBigUint64(offset, value, true);
|
||||
return offset + 8;
|
||||
}
|
||||
|
||||
export function writeBigUInt64BE(this: BufferExt, value, offset) {
|
||||
(this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength)).setBigUint64(
|
||||
offset === undefined ? (offset = 0) : offset,
|
||||
value,
|
||||
false,
|
||||
);
|
||||
if (offset === undefined) offset = 0;
|
||||
require("internal/buffer").check_bigint64(this, value, offset, 0n, 0xffffffffffffffffn);
|
||||
if (typeof value !== "bigint") throw require("internal/buffer").ERR_INVALID_ARG_TYPE("value", "bigint", value);
|
||||
const view = (this.$dataView ||= new DataView(this.buffer, this.byteOffset, this.byteLength));
|
||||
view.setBigUint64(offset, value, false);
|
||||
return offset + 8;
|
||||
}
|
||||
|
||||
@@ -487,7 +655,7 @@ export function slice(this: BufferExt, start, end) {
|
||||
// Use Math.trunc() to convert offset to an integer value that can be larger
|
||||
// than an Int32. Hence, don't use offset | 0 or similar techniques.
|
||||
offset = Math.trunc(offset);
|
||||
if (offset === 0 || offset !== offset) {
|
||||
if (offset === undefined || offset !== offset) {
|
||||
return 0;
|
||||
} else if (offset < 0) {
|
||||
offset += length;
|
||||
|
||||
134
src/js/internal/buffer.ts
Normal file
134
src/js/internal/buffer.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
// XXX: should more of this file be c++ imports?
|
||||
const { validateNumber, validateInteger } = require("internal/validators");
|
||||
const { ERR_INVALID_ARG_TYPE, ERR_OUT_OF_RANGE, ERR_BUFFER_OUT_OF_BOUNDS } = require("internal/errors");
|
||||
const { isAnyArrayBuffer } = require("node:util/types");
|
||||
|
||||
const BufferFrom1 = $newCppFunction("JSBuffer.cpp", "jsFunction_BufferFrom_Array", 0);
|
||||
const BufferFrom2 = $newCppFunction("JSBuffer.cpp", "jsFunction_BufferFrom_ArrayBuffer", 0);
|
||||
const BufferFrom4 = $newCppFunction("JSBuffer.cpp", "jsFunction_BufferFrom_Size", 0);
|
||||
const BufferFrom5 = $newCppFunction("JSBuffer.cpp", "jsFunction_BufferFrom_String", 0);
|
||||
|
||||
const ArrayIsArray = Array.isArray;
|
||||
|
||||
function boundsError(value, length, type?) {
|
||||
if (Math.floor(value) !== value) {
|
||||
validateNumber(value, type);
|
||||
throw ERR_OUT_OF_RANGE(type || "offset", "an integer", value);
|
||||
}
|
||||
if (length < 0) throw ERR_BUFFER_OUT_OF_BOUNDS();
|
||||
throw ERR_OUT_OF_RANGE(type || "offset", `>= ${type ? 1 : 0} and <= ${length}`, value);
|
||||
}
|
||||
|
||||
function checkBounds(buf, offset, byteLength) {
|
||||
validateNumber(offset, "offset");
|
||||
if (buf[offset] === undefined || buf[offset + byteLength] === undefined)
|
||||
boundsError(offset, buf.length - (byteLength + 1));
|
||||
}
|
||||
|
||||
function checkInt(value, min, max, buf, offset, byteLength) {
|
||||
if (value > max || value < min) {
|
||||
const n = typeof min === "bigint" ? "n" : "";
|
||||
let range;
|
||||
if (byteLength > 3) {
|
||||
if (min === 0 || min === 0n) {
|
||||
range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`;
|
||||
} else {
|
||||
range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and ` + `< 2${n} ** ${(byteLength + 1) * 8 - 1}${n}`;
|
||||
}
|
||||
} else {
|
||||
range = `>= ${min}${n} and <= ${max}${n}`;
|
||||
}
|
||||
throw ERR_OUT_OF_RANGE("value", range, value);
|
||||
}
|
||||
checkBounds(buf, offset, byteLength);
|
||||
}
|
||||
|
||||
function check_read(buf, offset, byteLength) {
|
||||
validateInteger(offset, "offset");
|
||||
const type = buf.length - byteLength;
|
||||
if (!(offset >= 0 && offset <= type)) boundsError(offset, type);
|
||||
}
|
||||
|
||||
function check_int8(buf, value, offset, min, max) {
|
||||
validateNumber(offset, "offset");
|
||||
if (value > max || value < min) throw ERR_OUT_OF_RANGE("value", `>= ${min} and <= ${max}`, value);
|
||||
if (buf[offset] === undefined) boundsError(offset, buf.length - 1);
|
||||
}
|
||||
|
||||
function check_int16(buf, value, offset, min, max) {
|
||||
checkInt(value, min, max, buf, offset, 1);
|
||||
}
|
||||
|
||||
function check_int24(buf, value, offset, min, max) {
|
||||
checkInt(value, min, max, buf, offset, 2);
|
||||
}
|
||||
|
||||
function check_int32(buf, value, offset, min, max) {
|
||||
checkInt(value, min, max, buf, offset, 3);
|
||||
}
|
||||
|
||||
function check_int40(buf, value, offset, min, max) {
|
||||
checkInt(value, min, max, buf, offset, 4);
|
||||
}
|
||||
|
||||
function check_int48(buf, value, offset, min, max) {
|
||||
checkInt(value, min, max, buf, offset, 5);
|
||||
}
|
||||
|
||||
function check_bigint64(buf, value, offset, min, max) {
|
||||
checkInt(value, min, max, buf, offset, 7);
|
||||
}
|
||||
|
||||
function fromString(string, encoding) {
|
||||
return BufferFrom5(string, encoding);
|
||||
}
|
||||
|
||||
function fromArrayBuffer(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number) {
|
||||
return BufferFrom2(arrayBuffer, byteOffset, length);
|
||||
}
|
||||
|
||||
function fromObject(obj) {
|
||||
if (obj.length !== undefined || isAnyArrayBuffer(obj.buffer)) {
|
||||
if (typeof obj.length !== "number") {
|
||||
return BufferFrom4(0);
|
||||
}
|
||||
return fromArrayLike(obj);
|
||||
}
|
||||
if (obj.type === "Buffer" && ArrayIsArray(obj.data)) {
|
||||
return fromArrayLike(obj.data);
|
||||
}
|
||||
}
|
||||
|
||||
function fromArrayLike(obj) {
|
||||
if (obj.length <= 0) return BufferFrom4(0);
|
||||
if (obj.length < Buffer.poolSize >>> 1) {
|
||||
// if (obj.length > poolSize - poolOffset) createPool();
|
||||
// const b = new FastBuffer(allocPool, poolOffset, obj.length);
|
||||
// TypedArrayPrototypeSet(b, obj, 0);
|
||||
// poolOffset += obj.length;
|
||||
// alignPool();
|
||||
// return b;
|
||||
}
|
||||
return BufferFrom1(obj);
|
||||
}
|
||||
|
||||
export default {
|
||||
validateNumber,
|
||||
validateInteger,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_OUT_OF_RANGE,
|
||||
boundsError,
|
||||
checkBounds,
|
||||
checkInt,
|
||||
check_read,
|
||||
check_int8,
|
||||
check_int16,
|
||||
check_int24,
|
||||
check_int32,
|
||||
check_int40,
|
||||
check_int48,
|
||||
check_bigint64,
|
||||
fromString,
|
||||
fromObject,
|
||||
fromArrayBuffer,
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Buffer, SlowBuffer, isAscii, isUtf8, kMaxLength } from "buffer";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
||||
import { gc } from "harness";
|
||||
import vm from "node:vm";
|
||||
|
||||
const BufferModule = await import("buffer");
|
||||
|
||||
@@ -21,7 +22,7 @@ afterEach(() => gc());
|
||||
const NumberIsInteger = Number.isInteger;
|
||||
class ERR_INVALID_ARG_TYPE extends TypeError {
|
||||
constructor() {
|
||||
super("Invalid arg type" + Array.prototype.join.call(arguments, " "));
|
||||
super(`The "${arguments[0]}" argument must be of type ${arguments[1]}. Received (${Bun.inspect(arguments[2])})`);
|
||||
this.code = "ERR_INVALID_ARG_TYPE";
|
||||
}
|
||||
}
|
||||
@@ -269,7 +270,7 @@ for (let withOverridenBufferWrite of [false, true]) {
|
||||
// Invalid encoding for Buffer.write
|
||||
expect(() => b.write("test string", 0, 5, "invalid")).toThrow(/encoding/);
|
||||
// Unsupported arguments for Buffer.write
|
||||
expect(() => b.write("test", "utf8", 0)).toThrow(/invalid/i);
|
||||
expect(() => b.write("test", "utf8", 0)).toThrow(/The "offset" argument must be of type number. Received /);
|
||||
});
|
||||
|
||||
it("create 0-length buffers", () => {
|
||||
@@ -1205,7 +1206,7 @@ for (let withOverridenBufferWrite of [false, true]) {
|
||||
it("toLocaleString()", () => {
|
||||
const buf = Buffer.from("test");
|
||||
expect(buf.toLocaleString()).toBe(buf.toString());
|
||||
// expect(Buffer.prototype.toLocaleString).toBe(Buffer.prototype.toString);
|
||||
expect(Buffer.prototype.toLocaleString).toBe(Buffer.prototype.toString);
|
||||
});
|
||||
|
||||
it("alloc() should throw on invalid data", () => {
|
||||
@@ -2116,7 +2117,7 @@ for (let withOverridenBufferWrite of [false, true]) {
|
||||
const buf = Buffer.from(ab);
|
||||
|
||||
expect(buf instanceof Buffer).toBe(true);
|
||||
// expect(buf.parent, buf.buffer);
|
||||
expect(buf.parent, buf.buffer);
|
||||
expect(buf.buffer).toBe(ab);
|
||||
expect(buf.length).toBe(ab.byteLength);
|
||||
|
||||
@@ -2136,12 +2137,12 @@ for (let withOverridenBufferWrite of [false, true]) {
|
||||
|
||||
// Now test protecting users from doing stupid things
|
||||
|
||||
// expect(function () {
|
||||
// function AB() {}
|
||||
// Object.setPrototypeOf(AB, ArrayBuffer);
|
||||
// Object.setPrototypeOf(AB.prototype, ArrayBuffer.prototype);
|
||||
// // Buffer.from(new AB());
|
||||
// }).toThrow();
|
||||
expect(function () {
|
||||
function AB() {}
|
||||
Object.setPrototypeOf(AB, ArrayBuffer);
|
||||
Object.setPrototypeOf(AB.prototype, ArrayBuffer.prototype);
|
||||
Buffer.from(new AB());
|
||||
}).toThrow();
|
||||
// console.log(origAB !== ab);
|
||||
|
||||
// Test the byteOffset and length arguments
|
||||
@@ -2670,8 +2671,8 @@ for (let withOverridenBufferWrite of [false, true]) {
|
||||
});
|
||||
|
||||
// Test that ArrayBuffer from a different context is detected correctly
|
||||
// const arrayBuf = vm.runInNewContext("new ArrayBuffer()");
|
||||
// expect(Buffer.byteLength(arrayBuf)).toBe(0);
|
||||
const arrayBuf = vm.runInNewContext("new ArrayBuffer()");
|
||||
expect(Buffer.byteLength(arrayBuf)).toBe(0);
|
||||
|
||||
// Verify that invalid encodings are treated as utf8
|
||||
for (let i = 1; i < 10; i++) {
|
||||
|
||||
@@ -657,7 +657,7 @@ describe("fork", () => {
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
name: "TypeError",
|
||||
message: expect.stringContaining(
|
||||
`The "modulePath" argument must be of type string, Buffer or URL. Received `,
|
||||
`The "modulePath" argument must be of type string, Buffer, or URL. Received `,
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -30,6 +30,7 @@ const net = require('net');
|
||||
// Do not require 'os' until needed so that test-os-checked-function can
|
||||
// monkey patch it. If 'os' is required here, that test will fail.
|
||||
const path = require('path');
|
||||
const { inspect } = require('util');
|
||||
const { inspect, getCallSites } = require('util');
|
||||
const { isMainThread } = require('worker_threads');
|
||||
const { isModuleNamespaceObject } = require('util/types');
|
||||
@@ -902,13 +903,14 @@ function invalidArgTypeHelper(input) {
|
||||
return ` Received ${input}`;
|
||||
}
|
||||
if (typeof input === 'function') {
|
||||
return ` Received function ${input.name}`;
|
||||
if (input.name) return ` Received function ${input.name}`;
|
||||
return ` Received function`;
|
||||
}
|
||||
if (typeof input === 'object') {
|
||||
if (input.constructor?.name) {
|
||||
return ` Received an instance of ${input.constructor.name}`;
|
||||
}
|
||||
return ` Received ${inspect(input, { depth: -1 })}`;
|
||||
return ` Received ${inspect(input, { depth: 0 })}`;
|
||||
}
|
||||
|
||||
let inspected = inspect(input, { colors: false });
|
||||
|
||||
1199
test/js/node/test/parallel/test-buffer-alloc.js
Normal file
1199
test/js/node/test/parallel/test-buffer-alloc.js
Normal file
File diff suppressed because it is too large
Load Diff
152
test/js/node/test/parallel/test-buffer-arraybuffer.js
Normal file
152
test/js/node/test/parallel/test-buffer-arraybuffer.js
Normal file
@@ -0,0 +1,152 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const LENGTH = 16;
|
||||
|
||||
const ab = new ArrayBuffer(LENGTH);
|
||||
const dv = new DataView(ab);
|
||||
const ui = new Uint8Array(ab);
|
||||
const buf = Buffer.from(ab);
|
||||
|
||||
|
||||
assert.ok(buf instanceof Buffer);
|
||||
assert.strictEqual(buf.parent, buf.buffer);
|
||||
assert.strictEqual(buf.buffer, ab);
|
||||
assert.strictEqual(buf.length, ab.byteLength);
|
||||
|
||||
|
||||
buf.fill(0xC);
|
||||
for (let i = 0; i < LENGTH; i++) {
|
||||
assert.strictEqual(ui[i], 0xC);
|
||||
ui[i] = 0xF;
|
||||
assert.strictEqual(buf[i], 0xF);
|
||||
}
|
||||
|
||||
buf.writeUInt32LE(0xF00, 0);
|
||||
buf.writeUInt32BE(0xB47, 4);
|
||||
buf.writeDoubleLE(3.1415, 8);
|
||||
|
||||
assert.strictEqual(dv.getUint32(0, true), 0xF00);
|
||||
assert.strictEqual(dv.getUint32(4), 0xB47);
|
||||
assert.strictEqual(dv.getFloat64(8, true), 3.1415);
|
||||
|
||||
|
||||
// Now test protecting users from doing stupid things
|
||||
|
||||
assert.throws(function() {
|
||||
function AB() { }
|
||||
Object.setPrototypeOf(AB, ArrayBuffer);
|
||||
Object.setPrototypeOf(AB.prototype, ArrayBuffer.prototype);
|
||||
Buffer.from(new AB());
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The first argument must be of type string, ' +
|
||||
'Buffer, ArrayBuffer, Array, or Array-like Object. Received ' +
|
||||
'an instance of AB'
|
||||
});
|
||||
|
||||
// Test the byteOffset and length arguments
|
||||
{
|
||||
const ab = new Uint8Array(5);
|
||||
ab[0] = 1;
|
||||
ab[1] = 2;
|
||||
ab[2] = 3;
|
||||
ab[3] = 4;
|
||||
ab[4] = 5;
|
||||
const buf = Buffer.from(ab.buffer, 1, 3);
|
||||
assert.strictEqual(buf.length, 3);
|
||||
assert.strictEqual(buf[0], 2);
|
||||
assert.strictEqual(buf[1], 3);
|
||||
assert.strictEqual(buf[2], 4);
|
||||
buf[0] = 9;
|
||||
assert.strictEqual(ab[1], 9);
|
||||
|
||||
assert.throws(() => Buffer.from(ab.buffer, 6), {
|
||||
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
name: 'RangeError',
|
||||
message: '"offset" is outside of buffer bounds'
|
||||
});
|
||||
assert.throws(() => Buffer.from(ab.buffer, 3, 6), {
|
||||
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
name: 'RangeError',
|
||||
message: '"length" is outside of buffer bounds'
|
||||
});
|
||||
}
|
||||
|
||||
// Test the deprecated Buffer() version also
|
||||
{
|
||||
const ab = new Uint8Array(5);
|
||||
ab[0] = 1;
|
||||
ab[1] = 2;
|
||||
ab[2] = 3;
|
||||
ab[3] = 4;
|
||||
ab[4] = 5;
|
||||
const buf = Buffer(ab.buffer, 1, 3);
|
||||
assert.strictEqual(buf.length, 3);
|
||||
assert.strictEqual(buf[0], 2);
|
||||
assert.strictEqual(buf[1], 3);
|
||||
assert.strictEqual(buf[2], 4);
|
||||
buf[0] = 9;
|
||||
assert.strictEqual(ab[1], 9);
|
||||
|
||||
assert.throws(() => Buffer(ab.buffer, 6), {
|
||||
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
name: 'RangeError',
|
||||
message: '"offset" is outside of buffer bounds'
|
||||
});
|
||||
assert.throws(() => Buffer(ab.buffer, 3, 6), {
|
||||
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
name: 'RangeError',
|
||||
message: '"length" is outside of buffer bounds'
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// If byteOffset is not numeric, it defaults to 0.
|
||||
const ab = new ArrayBuffer(10);
|
||||
const expected = Buffer.from(ab, 0);
|
||||
assert.deepStrictEqual(Buffer.from(ab, 'fhqwhgads'), expected);
|
||||
assert.deepStrictEqual(Buffer.from(ab, NaN), expected);
|
||||
assert.deepStrictEqual(Buffer.from(ab, {}), expected);
|
||||
assert.deepStrictEqual(Buffer.from(ab, []), expected);
|
||||
|
||||
// If byteOffset can be converted to a number, it will be.
|
||||
assert.deepStrictEqual(Buffer.from(ab, [1]), Buffer.from(ab, 1));
|
||||
|
||||
// If byteOffset is Infinity, throw.
|
||||
assert.throws(() => {
|
||||
Buffer.from(ab, Infinity);
|
||||
}, {
|
||||
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
name: 'RangeError',
|
||||
message: '"offset" is outside of buffer bounds'
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// If length is not numeric, it defaults to 0.
|
||||
const ab = new ArrayBuffer(10);
|
||||
const expected = Buffer.from(ab, 0, 0);
|
||||
assert.deepStrictEqual(Buffer.from(ab, 0, 'fhqwhgads'), expected);
|
||||
assert.deepStrictEqual(Buffer.from(ab, 0, NaN), expected);
|
||||
assert.deepStrictEqual(Buffer.from(ab, 0, {}), expected);
|
||||
assert.deepStrictEqual(Buffer.from(ab, 0, []), expected);
|
||||
|
||||
// If length can be converted to a number, it will be.
|
||||
assert.deepStrictEqual(Buffer.from(ab, 0, [1]), Buffer.from(ab, 0, 1));
|
||||
|
||||
// If length is Infinity, throw.
|
||||
assert.throws(() => {
|
||||
Buffer.from(ab, 0, Infinity);
|
||||
}, {
|
||||
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
name: 'RangeError',
|
||||
message: '"length" is outside of buffer bounds'
|
||||
});
|
||||
}
|
||||
|
||||
// Test an array like entry with the length set to NaN.
|
||||
assert.deepStrictEqual(Buffer.from({ length: NaN }), Buffer.alloc(0));
|
||||
@@ -0,0 +1,38 @@
|
||||
// Flags: --expose-internals
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (true) return; // TODO: BUN
|
||||
const assert = require('assert');
|
||||
const { internalBinding } = require('internal/test/binding');
|
||||
const { arrayBufferViewHasBuffer } = internalBinding('util');
|
||||
|
||||
const tests = [
|
||||
{ length: 0, expectOnHeap: true },
|
||||
{ length: 48, expectOnHeap: true },
|
||||
{ length: 96, expectOnHeap: false },
|
||||
{ length: 1024, expectOnHeap: false },
|
||||
];
|
||||
|
||||
for (const { length, expectOnHeap } of tests) {
|
||||
const arrays = [
|
||||
new Uint8Array(length),
|
||||
new Uint16Array(length / 2),
|
||||
new Uint32Array(length / 4),
|
||||
new Float32Array(length / 4),
|
||||
new Float64Array(length / 8),
|
||||
Buffer.alloc(length),
|
||||
Buffer.allocUnsafeSlow(length),
|
||||
// Buffer.allocUnsafe() is missing because it may use pooled allocations.
|
||||
];
|
||||
|
||||
for (const array of arrays) {
|
||||
const isOnHeap = !arrayBufferViewHasBuffer(array);
|
||||
assert.strictEqual(isOnHeap, expectOnHeap,
|
||||
`mismatch: ${isOnHeap} vs ${expectOnHeap} ` +
|
||||
`for ${array.constructor.name}, length = ${length}`);
|
||||
|
||||
// Consistency check: Accessing .buffer should create it.
|
||||
array.buffer; // eslint-disable-line no-unused-expressions
|
||||
assert(arrayBufferViewHasBuffer(array));
|
||||
}
|
||||
}
|
||||
48
test/js/node/test/parallel/test-buffer-badhex.js
Normal file
48
test/js/node/test/parallel/test-buffer-badhex.js
Normal file
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Test hex strings and bad hex strings
|
||||
{
|
||||
const buf = Buffer.alloc(4);
|
||||
assert.strictEqual(buf.length, 4);
|
||||
assert.deepStrictEqual(buf, Buffer.from([0, 0, 0, 0]));
|
||||
assert.strictEqual(buf.write('abcdxx', 0, 'hex'), 2);
|
||||
assert.deepStrictEqual(buf, Buffer.from([0xab, 0xcd, 0x00, 0x00]));
|
||||
assert.strictEqual(buf.toString('hex'), 'abcd0000');
|
||||
assert.strictEqual(buf.write('abcdef01', 0, 'hex'), 4);
|
||||
assert.deepStrictEqual(buf, Buffer.from([0xab, 0xcd, 0xef, 0x01]));
|
||||
assert.strictEqual(buf.toString('hex'), 'abcdef01');
|
||||
|
||||
const copy = Buffer.from(buf.toString('hex'), 'hex');
|
||||
assert.strictEqual(buf.toString('hex'), copy.toString('hex'));
|
||||
}
|
||||
|
||||
{
|
||||
const buf = Buffer.alloc(5);
|
||||
assert.strictEqual(buf.write('abcdxx', 1, 'hex'), 2);
|
||||
assert.strictEqual(buf.toString('hex'), '00abcd0000');
|
||||
}
|
||||
|
||||
{
|
||||
const buf = Buffer.alloc(4);
|
||||
assert.deepStrictEqual(buf, Buffer.from([0, 0, 0, 0]));
|
||||
assert.strictEqual(buf.write('xxabcd', 0, 'hex'), 0);
|
||||
assert.deepStrictEqual(buf, Buffer.from([0, 0, 0, 0]));
|
||||
assert.strictEqual(buf.write('xxab', 1, 'hex'), 0);
|
||||
assert.deepStrictEqual(buf, Buffer.from([0, 0, 0, 0]));
|
||||
assert.strictEqual(buf.write('cdxxab', 0, 'hex'), 1);
|
||||
assert.deepStrictEqual(buf, Buffer.from([0xcd, 0, 0, 0]));
|
||||
}
|
||||
|
||||
{
|
||||
const buf = Buffer.alloc(256);
|
||||
for (let i = 0; i < 256; i++)
|
||||
buf[i] = i;
|
||||
|
||||
const hex = buf.toString('hex');
|
||||
assert.deepStrictEqual(Buffer.from(hex, 'hex'), buf);
|
||||
|
||||
const badHex = `${hex.slice(0, 256)}xx${hex.slice(256, 510)}`;
|
||||
assert.deepStrictEqual(Buffer.from(badHex, 'hex'), buf.slice(0, 128));
|
||||
}
|
||||
55
test/js/node/test/parallel/test-buffer-bigint64.js
Normal file
55
test/js/node/test/parallel/test-buffer-bigint64.js
Normal file
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const buf = Buffer.allocUnsafe(8);
|
||||
|
||||
['LE', 'BE'].forEach(function(endianness) {
|
||||
// Should allow simple BigInts to be written and read
|
||||
let val = 123456789n;
|
||||
buf[`writeBigInt64${endianness}`](val, 0);
|
||||
let rtn = buf[`readBigInt64${endianness}`](0);
|
||||
assert.strictEqual(val, rtn);
|
||||
|
||||
// Should allow INT64_MAX to be written and read
|
||||
val = 0x7fffffffffffffffn;
|
||||
buf[`writeBigInt64${endianness}`](val, 0);
|
||||
rtn = buf[`readBigInt64${endianness}`](0);
|
||||
assert.strictEqual(val, rtn);
|
||||
|
||||
// Should read and write a negative signed 64-bit integer
|
||||
val = -123456789n;
|
||||
buf[`writeBigInt64${endianness}`](val, 0);
|
||||
assert.strictEqual(val, buf[`readBigInt64${endianness}`](0));
|
||||
|
||||
// Should read and write an unsigned 64-bit integer
|
||||
val = 123456789n;
|
||||
buf[`writeBigUInt64${endianness}`](val, 0);
|
||||
assert.strictEqual(val, buf[`readBigUInt64${endianness}`](0));
|
||||
|
||||
// Should throw a RangeError upon INT64_MAX+1 being written
|
||||
assert.throws(function() {
|
||||
const val = 0x8000000000000000n;
|
||||
buf[`writeBigInt64${endianness}`](val, 0);
|
||||
}, RangeError);
|
||||
|
||||
// Should throw a RangeError upon UINT64_MAX+1 being written
|
||||
assert.throws(function() {
|
||||
const val = 0x10000000000000000n;
|
||||
buf[`writeBigUInt64${endianness}`](val, 0);
|
||||
}, {
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
message: 'The value of "value" is out of range. It must be ' +
|
||||
'>= 0n and < 2n ** 64n. Received 18446744073709551616n'
|
||||
});
|
||||
|
||||
// Should throw a TypeError upon invalid input
|
||||
assert.throws(function() {
|
||||
buf[`writeBigInt64${endianness}`]('bad', 0);
|
||||
}, TypeError);
|
||||
|
||||
// Should throw a TypeError upon invalid input
|
||||
assert.throws(function() {
|
||||
buf[`writeBigUInt64${endianness}`]('bad', 0);
|
||||
}, TypeError);
|
||||
});
|
||||
132
test/js/node/test/parallel/test-buffer-bytelength.js
Normal file
132
test/js/node/test/parallel/test-buffer-bytelength.js
Normal file
@@ -0,0 +1,132 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const SlowBuffer = require('buffer').SlowBuffer;
|
||||
const vm = require('vm');
|
||||
|
||||
[
|
||||
[32, 'latin1'],
|
||||
[NaN, 'utf8'],
|
||||
[{}, 'latin1'],
|
||||
[],
|
||||
].forEach((args) => {
|
||||
assert.throws(
|
||||
() => Buffer.byteLength(...args),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "string" argument must be of type string or an instance ' +
|
||||
'of Buffer or ArrayBuffer.' +
|
||||
common.invalidArgTypeHelper(args[0])
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
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('')));
|
||||
|
||||
// buffer
|
||||
const incomplete = Buffer.from([0xe4, 0xb8, 0xad, 0xe6, 0x96]);
|
||||
assert.strictEqual(Buffer.byteLength(incomplete), 5);
|
||||
const ascii = Buffer.from('abc');
|
||||
assert.strictEqual(Buffer.byteLength(ascii), 3);
|
||||
|
||||
// ArrayBuffer
|
||||
const buffer = new ArrayBuffer(8);
|
||||
assert.strictEqual(Buffer.byteLength(buffer), 8);
|
||||
|
||||
// TypedArray
|
||||
const int8 = new Int8Array(8);
|
||||
assert.strictEqual(Buffer.byteLength(int8), 8);
|
||||
const uint8 = new Uint8Array(8);
|
||||
assert.strictEqual(Buffer.byteLength(uint8), 8);
|
||||
const uintc8 = new Uint8ClampedArray(2);
|
||||
assert.strictEqual(Buffer.byteLength(uintc8), 2);
|
||||
const int16 = new Int16Array(8);
|
||||
assert.strictEqual(Buffer.byteLength(int16), 16);
|
||||
const uint16 = new Uint16Array(8);
|
||||
assert.strictEqual(Buffer.byteLength(uint16), 16);
|
||||
const int32 = new Int32Array(8);
|
||||
assert.strictEqual(Buffer.byteLength(int32), 32);
|
||||
const uint32 = new Uint32Array(8);
|
||||
assert.strictEqual(Buffer.byteLength(uint32), 32);
|
||||
const float32 = new Float32Array(8);
|
||||
assert.strictEqual(Buffer.byteLength(float32), 32);
|
||||
const float64 = new Float64Array(8);
|
||||
assert.strictEqual(Buffer.byteLength(float64), 64);
|
||||
|
||||
// DataView
|
||||
const dv = new DataView(new ArrayBuffer(2));
|
||||
assert.strictEqual(Buffer.byteLength(dv), 2);
|
||||
|
||||
// Special case: zero length string
|
||||
assert.strictEqual(Buffer.byteLength('', 'ascii'), 0);
|
||||
assert.strictEqual(Buffer.byteLength('', 'HeX'), 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);
|
||||
// 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);
|
||||
// It should also be assumed with unrecognized encoding
|
||||
assert.strictEqual(Buffer.byteLength('hello world', 'abc'), 11);
|
||||
assert.strictEqual(Buffer.byteLength('ßœ∑≈', 'unkn0wn enc0ding'), 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
|
||||
);
|
||||
// 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
|
||||
);
|
||||
// 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é'), 14);
|
||||
assert.strictEqual(Buffer.byteLength('Il était tué', 'utf8'), 14);
|
||||
|
||||
['ascii', 'latin1', 'binary']
|
||||
.reduce((es, e) => es.concat(e, e.toUpperCase()), [])
|
||||
.forEach((encoding) => {
|
||||
assert.strictEqual(Buffer.byteLength('Il était tué', encoding), 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);
|
||||
});
|
||||
|
||||
// Test that ArrayBuffer from a different context is detected correctly
|
||||
const arrayBuf = vm.runInNewContext('new ArrayBuffer()');
|
||||
assert.strictEqual(Buffer.byteLength(arrayBuf), 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'));
|
||||
}
|
||||
47
test/js/node/test/parallel/test-buffer-compare.js
Normal file
47
test/js/node/test/parallel/test-buffer-compare.js
Normal file
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const b = Buffer.alloc(1, 'a');
|
||||
const c = Buffer.alloc(1, 'c');
|
||||
const d = Buffer.alloc(2, 'aa');
|
||||
const e = new Uint8Array([ 0x61, 0x61 ]); // ASCII 'aa', same as d
|
||||
|
||||
assert.strictEqual(b.compare(c), -1);
|
||||
assert.strictEqual(c.compare(d), 1);
|
||||
assert.strictEqual(d.compare(b), 1);
|
||||
assert.strictEqual(d.compare(e), 0);
|
||||
assert.strictEqual(b.compare(d), -1);
|
||||
assert.strictEqual(b.compare(b), 0);
|
||||
|
||||
assert.strictEqual(Buffer.compare(b, c), -1);
|
||||
assert.strictEqual(Buffer.compare(c, d), 1);
|
||||
assert.strictEqual(Buffer.compare(d, b), 1);
|
||||
assert.strictEqual(Buffer.compare(b, d), -1);
|
||||
assert.strictEqual(Buffer.compare(c, c), 0);
|
||||
assert.strictEqual(Buffer.compare(e, e), 0);
|
||||
assert.strictEqual(Buffer.compare(d, e), 0);
|
||||
assert.strictEqual(Buffer.compare(d, b), 1);
|
||||
|
||||
assert.strictEqual(Buffer.compare(Buffer.alloc(0), Buffer.alloc(0)), 0);
|
||||
assert.strictEqual(Buffer.compare(Buffer.alloc(0), Buffer.alloc(1)), -1);
|
||||
assert.strictEqual(Buffer.compare(Buffer.alloc(1), Buffer.alloc(0)), 1);
|
||||
|
||||
assert.throws(() => Buffer.compare(Buffer.alloc(1), 'abc'), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: 'The "buf2" argument must be an instance of Buffer or Uint8Array. ' +
|
||||
'Received type string ("abc")'
|
||||
});
|
||||
assert.throws(() => Buffer.compare('abc', Buffer.alloc(1)), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: 'The "buf1" argument must be an instance of Buffer or Uint8Array. ' +
|
||||
'Received type string ("abc")'
|
||||
});
|
||||
|
||||
assert.throws(() => Buffer.alloc(1).compare('abc'), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "target" argument must be an instance of ' +
|
||||
'Buffer or Uint8Array. Received type string ("abc")'
|
||||
});
|
||||
100
test/js/node/test/parallel/test-buffer-concat.js
Normal file
100
test/js/node/test/parallel/test-buffer-concat.js
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const zero = [];
|
||||
const one = [ Buffer.from('asdf') ];
|
||||
const long = [];
|
||||
for (let i = 0; i < 10; i++) long.push(Buffer.from('asdf'));
|
||||
|
||||
const flatZero = Buffer.concat(zero);
|
||||
const flatOne = Buffer.concat(one);
|
||||
const flatLong = Buffer.concat(long);
|
||||
const flatLongLen = Buffer.concat(long, 40);
|
||||
|
||||
assert.strictEqual(flatZero.length, 0);
|
||||
assert.strictEqual(flatOne.toString(), 'asdf');
|
||||
|
||||
const check = 'asdf'.repeat(10);
|
||||
|
||||
// A special case where concat used to return the first item,
|
||||
// if the length is one. This check is to make sure that we don't do that.
|
||||
assert.notStrictEqual(flatOne, one[0]);
|
||||
assert.strictEqual(flatLong.toString(), check);
|
||||
assert.strictEqual(flatLongLen.toString(), check);
|
||||
|
||||
[undefined, null, Buffer.from('hello')].forEach((value) => {
|
||||
assert.throws(() => {
|
||||
Buffer.concat(value);
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: 'The "list" argument must be an instance of Array.' +
|
||||
`${common.invalidArgTypeHelper(value)}`
|
||||
});
|
||||
});
|
||||
|
||||
[[42], ['hello', Buffer.from('world')]].forEach((value) => {
|
||||
assert.throws(() => {
|
||||
Buffer.concat(value);
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: 'The "list[0]" argument must be an instance of Buffer ' +
|
||||
`or Uint8Array.${common.invalidArgTypeHelper(value[0])}`
|
||||
});
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
Buffer.concat([Buffer.from('hello'), 3]);
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: 'The "list[1]" argument must be an instance of Buffer ' +
|
||||
'or Uint8Array. Received type number (3)'
|
||||
});
|
||||
|
||||
// eslint-disable-next-line node-core/crypto-check
|
||||
const random10 = common.hasCrypto ?
|
||||
require('crypto').randomBytes(10) :
|
||||
Buffer.alloc(10, 1);
|
||||
const empty = Buffer.alloc(0);
|
||||
|
||||
assert.notDeepStrictEqual(random10, empty);
|
||||
assert.notDeepStrictEqual(random10, Buffer.alloc(10));
|
||||
|
||||
assert.deepStrictEqual(Buffer.concat([], 100), empty);
|
||||
assert.deepStrictEqual(Buffer.concat([random10], 0), empty);
|
||||
assert.deepStrictEqual(Buffer.concat([random10], 10), random10);
|
||||
assert.deepStrictEqual(Buffer.concat([random10, random10], 10), random10);
|
||||
assert.deepStrictEqual(Buffer.concat([empty, random10]), random10);
|
||||
assert.deepStrictEqual(Buffer.concat([random10, empty, empty]), random10);
|
||||
|
||||
// The tail should be zero-filled
|
||||
assert.deepStrictEqual(Buffer.concat([empty], 100), Buffer.alloc(100));
|
||||
assert.deepStrictEqual(Buffer.concat([empty], 4096), Buffer.alloc(4096));
|
||||
assert.deepStrictEqual(
|
||||
Buffer.concat([random10], 40),
|
||||
Buffer.concat([random10, Buffer.alloc(30)]));
|
||||
|
||||
assert.deepStrictEqual(Buffer.concat([new Uint8Array([0x41, 0x42]),
|
||||
new Uint8Array([0x43, 0x44])]),
|
||||
Buffer.from('ABCD'));
|
||||
17
test/js/node/test/parallel/test-buffer-constants.js
Normal file
17
test/js/node/test/parallel/test-buffer-constants.js
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const { kMaxLength, kStringMaxLength } = require('buffer');
|
||||
const { MAX_LENGTH, MAX_STRING_LENGTH } = require('buffer').constants;
|
||||
|
||||
assert.strictEqual(typeof MAX_LENGTH, 'number');
|
||||
assert.strictEqual(typeof MAX_STRING_LENGTH, 'number');
|
||||
assert(MAX_STRING_LENGTH <= MAX_LENGTH);
|
||||
assert.throws(() => ' '.repeat(MAX_STRING_LENGTH + 1), /^RangeError: Out of memory$/);
|
||||
|
||||
' '.repeat(MAX_STRING_LENGTH); // Should not throw.
|
||||
|
||||
// Legacy values match:
|
||||
assert.strictEqual(kMaxLength, MAX_LENGTH);
|
||||
assert.strictEqual(kStringMaxLength, MAX_STRING_LENGTH);
|
||||
237
test/js/node/test/parallel/test-buffer-copy.js
Normal file
237
test/js/node/test/parallel/test-buffer-copy.js
Normal file
@@ -0,0 +1,237 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const b = Buffer.allocUnsafe(1024);
|
||||
const c = Buffer.allocUnsafe(512);
|
||||
|
||||
let cntr = 0;
|
||||
|
||||
{
|
||||
// copy 512 bytes, from 0 to 512.
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
const copied = b.copy(c, 0, 0, 512);
|
||||
assert.strictEqual(copied, 512);
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
assert.strictEqual(c[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Current behavior is to coerce values to integers.
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
const copied = b.copy(c, '0', '0', '512');
|
||||
assert.strictEqual(copied, 512);
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
assert.strictEqual(c[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Floats will be converted to integers via `Math.floor`
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
const copied = b.copy(c, 0, 0, 512.5);
|
||||
assert.strictEqual(copied, 512);
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
assert.strictEqual(c[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Copy c into b, without specifying sourceEnd
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
const copied = c.copy(b, 0, 0);
|
||||
assert.strictEqual(copied, c.length);
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
assert.strictEqual(b[i], c[i]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Copy c into b, without specifying sourceStart
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
const copied = c.copy(b, 0);
|
||||
assert.strictEqual(copied, c.length);
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
assert.strictEqual(b[i], c[i]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Copied source range greater than source length
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
const copied = c.copy(b, 0, 0, c.length + 1);
|
||||
assert.strictEqual(copied, c.length);
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
assert.strictEqual(b[i], c[i]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Copy longer buffer b to shorter c without targetStart
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
const copied = b.copy(c);
|
||||
assert.strictEqual(copied, c.length);
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
assert.strictEqual(c[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Copy starting near end of b to c
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
const copied = b.copy(c, 0, b.length - Math.floor(c.length / 2));
|
||||
assert.strictEqual(copied, Math.floor(c.length / 2));
|
||||
for (let i = 0; i < Math.floor(c.length / 2); i++) {
|
||||
assert.strictEqual(c[i], b[b.length - Math.floor(c.length / 2) + i]);
|
||||
}
|
||||
for (let i = Math.floor(c.length / 2) + 1; i < c.length; i++) {
|
||||
assert.strictEqual(c[c.length - 1], c[i]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Try to copy 513 bytes, and check we don't overrun c
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
const copied = b.copy(c, 0, 0, 513);
|
||||
assert.strictEqual(copied, c.length);
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
assert.strictEqual(c[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// copy 768 bytes from b into b
|
||||
b.fill(++cntr);
|
||||
b.fill(++cntr, 256);
|
||||
const copied = b.copy(b, 0, 256, 1024);
|
||||
assert.strictEqual(copied, 768);
|
||||
for (let i = 0; i < b.length; i++) {
|
||||
assert.strictEqual(b[i], cntr);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy string longer than buffer length (failure will segfault)
|
||||
const bb = Buffer.allocUnsafe(10);
|
||||
bb.fill('hello crazy world');
|
||||
|
||||
|
||||
// Try to copy from before the beginning of b. Should not throw.
|
||||
b.copy(c, 0, 100, 10);
|
||||
|
||||
// Throw with invalid source type
|
||||
assert.throws(
|
||||
() => Buffer.prototype.copy.call(0),
|
||||
{
|
||||
// code: 'ERR_INVALID_ARG_TYPE',
|
||||
code: 'ERR_INVALID_THIS',
|
||||
name: 'TypeError',
|
||||
}
|
||||
);
|
||||
|
||||
// Copy throws at negative targetStart
|
||||
assert.throws(
|
||||
() => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), -1, 0),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "targetStart" is out of range. ' +
|
||||
'It must be >= 0 and <= 5. Received -1'
|
||||
}
|
||||
);
|
||||
|
||||
// Copy throws at negative sourceStart
|
||||
assert.throws(
|
||||
() => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), 0, -1),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
}
|
||||
);
|
||||
|
||||
// Copy throws if sourceStart is greater than length of source
|
||||
assert.throws(
|
||||
() => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), 0, 100),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
}
|
||||
);
|
||||
|
||||
{
|
||||
// Check sourceEnd resets to targetEnd if former is greater than the latter
|
||||
b.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
b.copy(c, 0, 0, 1025);
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
assert.strictEqual(c[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Throw with negative sourceEnd
|
||||
assert.throws(
|
||||
() => b.copy(c, 0, 0, -1),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "sourceEnd" is out of range. ' +
|
||||
'It must be >= 0 and <= 1024. Received -1'
|
||||
}
|
||||
);
|
||||
|
||||
// When sourceStart is greater than sourceEnd, zero copied
|
||||
assert.strictEqual(b.copy(c, 0, 100, 10), 0);
|
||||
|
||||
// When targetStart > targetLength, zero copied
|
||||
assert.strictEqual(b.copy(c, 512, 0, 10), 0);
|
||||
|
||||
// Test that the `target` can be a Uint8Array.
|
||||
{
|
||||
const d = new Uint8Array(c);
|
||||
// copy 512 bytes, from 0 to 512.
|
||||
b.fill(++cntr);
|
||||
d.fill(++cntr);
|
||||
const copied = b.copy(d, 0, 0, 512);
|
||||
assert.strictEqual(copied, 512);
|
||||
for (let i = 0; i < d.length; i++) {
|
||||
assert.strictEqual(d[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the source can be a Uint8Array, too.
|
||||
{
|
||||
const e = new Uint8Array(b);
|
||||
// copy 512 bytes, from 0 to 512.
|
||||
e.fill(++cntr);
|
||||
c.fill(++cntr);
|
||||
const copied = Buffer.prototype.copy.call(e, c, 0, 0, 512);
|
||||
assert.strictEqual(copied, 512);
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
assert.strictEqual(c[i], e[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/nodejs/node/issues/23668: Do not crash for invalid input.
|
||||
c.fill('c');
|
||||
b.copy(c, 'not a valid offset');
|
||||
// Make sure this acted like a regular copy with `0` offset.
|
||||
assert.deepStrictEqual(c, b.slice(0, c.length));
|
||||
|
||||
{
|
||||
c.fill('C');
|
||||
assert.throws(() => {
|
||||
b.copy(c, { [Symbol.toPrimitive]() { throw new Error('foo'); } });
|
||||
}, /foo/);
|
||||
// No copying took place:
|
||||
assert.deepStrictEqual(c.toString(), 'C'.repeat(c.length));
|
||||
}
|
||||
25
test/js/node/test/parallel/test-buffer-equals.js
Normal file
25
test/js/node/test/parallel/test-buffer-equals.js
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const b = Buffer.from('abcdf');
|
||||
const c = Buffer.from('abcdf');
|
||||
const d = Buffer.from('abcde');
|
||||
const e = Buffer.from('abcdef');
|
||||
|
||||
assert.ok(b.equals(c));
|
||||
assert.ok(!c.equals(d));
|
||||
assert.ok(!d.equals(e));
|
||||
assert.ok(d.equals(d));
|
||||
assert.ok(d.equals(new Uint8Array([0x61, 0x62, 0x63, 0x64, 0x65])));
|
||||
|
||||
assert.throws(
|
||||
() => Buffer.alloc(1).equals('abc'),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "otherBuffer" argument must be an instance of ' +
|
||||
'Buffer or Uint8Array. Received type string ("abc")'
|
||||
}
|
||||
);
|
||||
429
test/js/node/test/parallel/test-buffer-fill.js
Normal file
429
test/js/node/test/parallel/test-buffer-fill.js
Normal file
@@ -0,0 +1,429 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const SIZE = 28;
|
||||
|
||||
const buf1 = Buffer.allocUnsafe(SIZE);
|
||||
const buf2 = Buffer.allocUnsafe(SIZE);
|
||||
|
||||
// Default encoding
|
||||
testBufs('abc');
|
||||
testBufs('\u0222aa');
|
||||
testBufs('a\u0234b\u0235c\u0236');
|
||||
testBufs('abc', 4);
|
||||
testBufs('abc', 5);
|
||||
testBufs('abc', SIZE);
|
||||
testBufs('\u0222aa', 2);
|
||||
testBufs('\u0222aa', 8);
|
||||
testBufs('a\u0234b\u0235c\u0236', 4);
|
||||
testBufs('a\u0234b\u0235c\u0236', 12);
|
||||
testBufs('abc', 4, 1);
|
||||
testBufs('abc', 5, 1);
|
||||
testBufs('\u0222aa', 8, 1);
|
||||
testBufs('a\u0234b\u0235c\u0236', 4, 1);
|
||||
testBufs('a\u0234b\u0235c\u0236', 12, 1);
|
||||
|
||||
// UTF8
|
||||
testBufs('abc', 'utf8');
|
||||
testBufs('\u0222aa', 'utf8');
|
||||
testBufs('a\u0234b\u0235c\u0236', 'utf8');
|
||||
testBufs('abc', 4, 'utf8');
|
||||
testBufs('abc', 5, 'utf8');
|
||||
testBufs('abc', SIZE, 'utf8');
|
||||
testBufs('\u0222aa', 2, 'utf8');
|
||||
testBufs('\u0222aa', 8, 'utf8');
|
||||
testBufs('a\u0234b\u0235c\u0236', 4, 'utf8');
|
||||
testBufs('a\u0234b\u0235c\u0236', 12, 'utf8');
|
||||
testBufs('abc', 4, 1, 'utf8');
|
||||
testBufs('abc', 5, 1, 'utf8');
|
||||
testBufs('\u0222aa', 8, 1, 'utf8');
|
||||
testBufs('a\u0234b\u0235c\u0236', 4, 1, 'utf8');
|
||||
testBufs('a\u0234b\u0235c\u0236', 12, 1, 'utf8');
|
||||
assert.strictEqual(Buffer.allocUnsafe(1).fill(0).fill('\u0222')[0], 0xc8);
|
||||
|
||||
// BINARY
|
||||
testBufs('abc', 'binary');
|
||||
testBufs('\u0222aa', 'binary');
|
||||
testBufs('a\u0234b\u0235c\u0236', 'binary');
|
||||
testBufs('abc', 4, 'binary');
|
||||
testBufs('abc', 5, 'binary');
|
||||
testBufs('abc', SIZE, 'binary');
|
||||
testBufs('\u0222aa', 2, 'binary');
|
||||
testBufs('\u0222aa', 8, 'binary');
|
||||
testBufs('a\u0234b\u0235c\u0236', 4, 'binary');
|
||||
testBufs('a\u0234b\u0235c\u0236', 12, 'binary');
|
||||
testBufs('abc', 4, 1, 'binary');
|
||||
testBufs('abc', 5, 1, 'binary');
|
||||
testBufs('\u0222aa', 8, 1, 'binary');
|
||||
testBufs('a\u0234b\u0235c\u0236', 4, 1, 'binary');
|
||||
testBufs('a\u0234b\u0235c\u0236', 12, 1, 'binary');
|
||||
|
||||
// LATIN1
|
||||
testBufs('abc', 'latin1');
|
||||
testBufs('\u0222aa', 'latin1');
|
||||
testBufs('a\u0234b\u0235c\u0236', 'latin1');
|
||||
testBufs('abc', 4, 'latin1');
|
||||
testBufs('abc', 5, 'latin1');
|
||||
testBufs('abc', SIZE, 'latin1');
|
||||
testBufs('\u0222aa', 2, 'latin1');
|
||||
testBufs('\u0222aa', 8, 'latin1');
|
||||
testBufs('a\u0234b\u0235c\u0236', 4, 'latin1');
|
||||
testBufs('a\u0234b\u0235c\u0236', 12, 'latin1');
|
||||
testBufs('abc', 4, 1, 'latin1');
|
||||
testBufs('abc', 5, 1, 'latin1');
|
||||
testBufs('\u0222aa', 8, 1, 'latin1');
|
||||
testBufs('a\u0234b\u0235c\u0236', 4, 1, 'latin1');
|
||||
testBufs('a\u0234b\u0235c\u0236', 12, 1, 'latin1');
|
||||
|
||||
// UCS2
|
||||
testBufs('abc', 'ucs2');
|
||||
testBufs('\u0222aa', 'ucs2');
|
||||
testBufs('a\u0234b\u0235c\u0236', 'ucs2');
|
||||
testBufs('abc', 4, 'ucs2');
|
||||
testBufs('abc', SIZE, 'ucs2');
|
||||
testBufs('\u0222aa', 2, 'ucs2');
|
||||
testBufs('\u0222aa', 8, 'ucs2');
|
||||
testBufs('a\u0234b\u0235c\u0236', 4, 'ucs2');
|
||||
testBufs('a\u0234b\u0235c\u0236', 12, 'ucs2');
|
||||
testBufs('abc', 4, 1, 'ucs2');
|
||||
testBufs('abc', 5, 1, 'ucs2');
|
||||
testBufs('\u0222aa', 8, 1, 'ucs2');
|
||||
testBufs('a\u0234b\u0235c\u0236', 4, 1, 'ucs2');
|
||||
testBufs('a\u0234b\u0235c\u0236', 12, 1, 'ucs2');
|
||||
assert.strictEqual(Buffer.allocUnsafe(1).fill('\u0222', 'ucs2')[0], 0x22);
|
||||
|
||||
// HEX
|
||||
testBufs('616263', 'hex');
|
||||
testBufs('c8a26161', 'hex');
|
||||
testBufs('61c8b462c8b563c8b6', 'hex');
|
||||
testBufs('616263', 4, 'hex');
|
||||
testBufs('616263', 5, 'hex');
|
||||
testBufs('616263', SIZE, 'hex');
|
||||
testBufs('c8a26161', 2, 'hex');
|
||||
testBufs('c8a26161', 8, 'hex');
|
||||
testBufs('61c8b462c8b563c8b6', 4, 'hex');
|
||||
testBufs('61c8b462c8b563c8b6', 12, 'hex');
|
||||
testBufs('616263', 4, 1, 'hex');
|
||||
testBufs('616263', 5, 1, 'hex');
|
||||
testBufs('c8a26161', 8, 1, 'hex');
|
||||
testBufs('61c8b462c8b563c8b6', 4, 1, 'hex');
|
||||
testBufs('61c8b462c8b563c8b6', 12, 1, 'hex');
|
||||
|
||||
assert.throws(() => {
|
||||
const buf = Buffer.allocUnsafe(SIZE);
|
||||
|
||||
buf.fill('yKJh', 'hex');
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_VALUE',
|
||||
name: 'TypeError'
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
const buf = Buffer.allocUnsafe(SIZE);
|
||||
|
||||
buf.fill('\u0222', 'hex');
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_VALUE',
|
||||
name: 'TypeError'
|
||||
});
|
||||
|
||||
// BASE64
|
||||
testBufs('YWJj', 'base64');
|
||||
testBufs('yKJhYQ==', 'base64');
|
||||
testBufs('Yci0Ysi1Y8i2', 'base64');
|
||||
testBufs('YWJj', 4, 'base64');
|
||||
testBufs('YWJj', SIZE, 'base64');
|
||||
testBufs('yKJhYQ==', 2, 'base64');
|
||||
testBufs('yKJhYQ==', 8, 'base64');
|
||||
testBufs('Yci0Ysi1Y8i2', 4, 'base64');
|
||||
testBufs('Yci0Ysi1Y8i2', 12, 'base64');
|
||||
testBufs('YWJj', 4, 1, 'base64');
|
||||
testBufs('YWJj', 5, 1, 'base64');
|
||||
testBufs('yKJhYQ==', 8, 1, 'base64');
|
||||
testBufs('Yci0Ysi1Y8i2', 4, 1, 'base64');
|
||||
testBufs('Yci0Ysi1Y8i2', 12, 1, 'base64');
|
||||
|
||||
// BASE64URL
|
||||
testBufs('YWJj', 'base64url');
|
||||
testBufs('yKJhYQ', 'base64url');
|
||||
testBufs('Yci0Ysi1Y8i2', 'base64url');
|
||||
testBufs('YWJj', 4, 'base64url');
|
||||
testBufs('YWJj', SIZE, 'base64url');
|
||||
testBufs('yKJhYQ', 2, 'base64url');
|
||||
testBufs('yKJhYQ', 8, 'base64url');
|
||||
testBufs('Yci0Ysi1Y8i2', 4, 'base64url');
|
||||
testBufs('Yci0Ysi1Y8i2', 12, 'base64url');
|
||||
testBufs('YWJj', 4, 1, 'base64url');
|
||||
testBufs('YWJj', 5, 1, 'base64url');
|
||||
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()) {
|
||||
assert.deepStrictEqual(value, 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) => {
|
||||
assert.throws(
|
||||
() => buf1.fill(...args),
|
||||
{ code: 'ERR_OUT_OF_RANGE' }
|
||||
);
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => buf1.fill('a', 0, buf1.length, 'node rocks!'),
|
||||
{
|
||||
code: 'ERR_UNKNOWN_ENCODING',
|
||||
name: 'TypeError',
|
||||
message: 'Unknown encoding: node rocks!'
|
||||
}
|
||||
);
|
||||
|
||||
[
|
||||
['a', 0, 0, NaN],
|
||||
['a', 0, 0, false],
|
||||
].forEach((args) => {
|
||||
assert.throws(
|
||||
() => buf1.fill(...args),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: 'The "encoding" argument must be of type ' +
|
||||
`string.${common.invalidArgTypeHelper(args[3])}`
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => buf1.fill('a', 0, 0, 'foo'),
|
||||
{
|
||||
code: 'ERR_UNKNOWN_ENCODING',
|
||||
name: 'TypeError',
|
||||
message: 'Unknown encoding: foo'
|
||||
}
|
||||
);
|
||||
|
||||
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;
|
||||
assert(offset <= buf2.length);
|
||||
|
||||
// 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');
|
||||
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.
|
||||
assert.deepStrictEqual(buf1.fill.apply(buf1, arguments),
|
||||
writeToFill.apply(null, arguments));
|
||||
}
|
||||
|
||||
// Make sure these throw.
|
||||
assert.throws(
|
||||
() => Buffer.allocUnsafe(8).fill('a', -1),
|
||||
{ code: 'ERR_OUT_OF_RANGE' });
|
||||
assert.throws(
|
||||
() => Buffer.allocUnsafe(8).fill('a', 0, 9),
|
||||
{ code: 'ERR_OUT_OF_RANGE' });
|
||||
|
||||
// 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++)
|
||||
assert.strictEqual(buf[i], 10);
|
||||
|
||||
buf.fill(11, 0, buf.length >> 1);
|
||||
for (let i = 0; i < buf.length >> 1; i++)
|
||||
assert.strictEqual(buf[i], 11);
|
||||
for (let i = (buf.length >> 1) + 1; i < buf.length; i++)
|
||||
assert.strictEqual(buf[i], 10);
|
||||
|
||||
buf.fill('h');
|
||||
for (let i = 0; i < buf.length; i++)
|
||||
assert.strictEqual(buf[i], 'h'.charCodeAt(0));
|
||||
|
||||
buf.fill(0);
|
||||
for (let i = 0; i < buf.length; i++)
|
||||
assert.strictEqual(buf[i], 0);
|
||||
|
||||
buf.fill(null);
|
||||
for (let i = 0; i < buf.length; i++)
|
||||
assert.strictEqual(buf[i], 0);
|
||||
|
||||
buf.fill(1, 16, 32);
|
||||
for (let i = 0; i < 16; i++)
|
||||
assert.strictEqual(buf[i], 0);
|
||||
for (let i = 16; i < 32; i++)
|
||||
assert.strictEqual(buf[i], 1);
|
||||
for (let i = 32; i < buf.length; i++)
|
||||
assert.strictEqual(buf[i], 0);
|
||||
}
|
||||
|
||||
{
|
||||
const buf = Buffer.alloc(10, 'abc');
|
||||
assert.strictEqual(buf.toString(), 'abcabcabca');
|
||||
buf.fill('է');
|
||||
assert.strictEqual(buf.toString(), 'էէէէէ');
|
||||
}
|
||||
|
||||
// Make sure "end" is properly checked, even if it's magically mangled using
|
||||
// Symbol.toPrimitive.
|
||||
{
|
||||
assert.throws(() => {
|
||||
const end = {
|
||||
[Symbol.toPrimitive]() {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
Buffer.alloc(1).fill(Buffer.alloc(1), 0, end);
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: 'The "end" argument must be of type number. Received an ' +
|
||||
'instance of Object'
|
||||
});
|
||||
}
|
||||
|
||||
// Test that bypassing 'length' won't cause an abort.
|
||||
// assert.throws(() => {
|
||||
// const buf = Buffer.from('w00t');
|
||||
// Object.defineProperty(buf, 'length', {
|
||||
// value: 1337,
|
||||
// enumerable: true
|
||||
// });
|
||||
// buf.fill('');
|
||||
// }, {
|
||||
// code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
// name: 'RangeError',
|
||||
// message: 'Attempt to access memory outside buffer bounds'
|
||||
// });
|
||||
|
||||
assert.deepStrictEqual(
|
||||
Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'),
|
||||
Buffer.from('61006200610062006100620061006200', 'hex'));
|
||||
|
||||
assert.deepStrictEqual(
|
||||
Buffer.allocUnsafeSlow(15).fill('ab', 'utf16le'),
|
||||
Buffer.from('610062006100620061006200610062', 'hex'));
|
||||
|
||||
assert.deepStrictEqual(
|
||||
Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'),
|
||||
Buffer.from('61006200610062006100620061006200', 'hex'));
|
||||
assert.deepStrictEqual(
|
||||
Buffer.allocUnsafeSlow(16).fill('a', 'utf16le'),
|
||||
Buffer.from('61006100610061006100610061006100', 'hex'));
|
||||
|
||||
assert.strictEqual(
|
||||
Buffer.allocUnsafeSlow(16).fill('a', 'utf16le').toString('utf16le'),
|
||||
'a'.repeat(8));
|
||||
assert.strictEqual(
|
||||
Buffer.allocUnsafeSlow(16).fill('a', 'latin1').toString('latin1'),
|
||||
'a'.repeat(16));
|
||||
assert.strictEqual(
|
||||
Buffer.allocUnsafeSlow(16).fill('a', 'utf8').toString('utf8'),
|
||||
'a'.repeat(16));
|
||||
|
||||
assert.strictEqual(
|
||||
Buffer.allocUnsafeSlow(16).fill('Љ', 'utf16le').toString('utf16le'),
|
||||
'Љ'.repeat(8));
|
||||
assert.strictEqual(
|
||||
Buffer.allocUnsafeSlow(16).fill('Љ', 'latin1').toString('latin1'),
|
||||
'\t'.repeat(16));
|
||||
assert.strictEqual(
|
||||
Buffer.allocUnsafeSlow(16).fill('Љ', 'utf8').toString('utf8'),
|
||||
'Љ'.repeat(8));
|
||||
|
||||
assert.throws(() => {
|
||||
const buf = Buffer.from('a'.repeat(1000));
|
||||
|
||||
buf.fill('This is not correctly encoded', 'hex');
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_VALUE',
|
||||
name: 'TypeError'
|
||||
});
|
||||
|
||||
|
||||
{
|
||||
const bufEmptyString = Buffer.alloc(5, '');
|
||||
assert.strictEqual(bufEmptyString.toString(), '\x00\x00\x00\x00\x00');
|
||||
|
||||
const bufEmptyArray = Buffer.alloc(5, []);
|
||||
assert.strictEqual(bufEmptyArray.toString(), '\x00\x00\x00\x00\x00');
|
||||
|
||||
const bufEmptyBuffer = Buffer.alloc(5, Buffer.alloc(5));
|
||||
assert.strictEqual(bufEmptyBuffer.toString(), '\x00\x00\x00\x00\x00');
|
||||
|
||||
const bufZero = Buffer.alloc(5, 0);
|
||||
assert.strictEqual(bufZero.toString(), '\x00\x00\x00\x00\x00');
|
||||
}
|
||||
141
test/js/node/test/parallel/test-buffer-from.js
Normal file
141
test/js/node/test/parallel/test-buffer-from.js
Normal file
@@ -0,0 +1,141 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const { deepStrictEqual, strictEqual, throws } = require('assert');
|
||||
const { runInNewContext } = require('vm');
|
||||
|
||||
const checkString = 'test';
|
||||
|
||||
const check = Buffer.from(checkString);
|
||||
|
||||
class MyString extends String {
|
||||
constructor() {
|
||||
super(checkString);
|
||||
}
|
||||
}
|
||||
|
||||
class MyPrimitive {
|
||||
[Symbol.toPrimitive]() {
|
||||
return checkString;
|
||||
}
|
||||
}
|
||||
|
||||
class MyBadPrimitive {
|
||||
[Symbol.toPrimitive]() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
deepStrictEqual(Buffer.from(new String(checkString)), check);
|
||||
deepStrictEqual(Buffer.from(new MyString()), check);
|
||||
deepStrictEqual(Buffer.from(new MyPrimitive()), check);
|
||||
deepStrictEqual(
|
||||
Buffer.from(runInNewContext('new String(checkString)', { checkString })),
|
||||
check
|
||||
);
|
||||
|
||||
[
|
||||
{},
|
||||
new Boolean(true),
|
||||
{ valueOf() { return null; } },
|
||||
{ valueOf() { return undefined; } },
|
||||
{ valueOf: null },
|
||||
{ __proto__: null },
|
||||
new Number(true),
|
||||
new MyBadPrimitive(),
|
||||
Symbol(),
|
||||
5n,
|
||||
(one, two, three) => {},
|
||||
undefined,
|
||||
null,
|
||||
].forEach((input) => {
|
||||
const errObj = {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The first argument must be of type string, ' +
|
||||
'Buffer, ArrayBuffer, Array, or Array-like Object.' +
|
||||
common.invalidArgTypeHelper(input)
|
||||
};
|
||||
throws(() => Buffer.from(input), errObj);
|
||||
throws(() => Buffer.from(input, 'hex'), errObj);
|
||||
});
|
||||
|
||||
Buffer.allocUnsafe(10); // Should not throw.
|
||||
Buffer.from('deadbeaf', 'hex'); // Should not throw.
|
||||
|
||||
|
||||
{
|
||||
const u16 = new Uint16Array([0xffff]);
|
||||
const b16 = Buffer.copyBytesFrom(u16);
|
||||
u16[0] = 0;
|
||||
strictEqual(b16.length, 2);
|
||||
strictEqual(b16[0], 255);
|
||||
strictEqual(b16[1], 255);
|
||||
}
|
||||
|
||||
{
|
||||
const u16 = new Uint16Array([0, 0xffff]);
|
||||
const b16 = Buffer.copyBytesFrom(u16, 1, 5);
|
||||
u16[0] = 0xffff;
|
||||
u16[1] = 0;
|
||||
strictEqual(b16.length, 2);
|
||||
strictEqual(b16[0], 255);
|
||||
strictEqual(b16[1], 255);
|
||||
}
|
||||
|
||||
{
|
||||
const u32 = new Uint32Array([0xffffffff]);
|
||||
const b32 = Buffer.copyBytesFrom(u32);
|
||||
u32[0] = 0;
|
||||
strictEqual(b32.length, 4);
|
||||
strictEqual(b32[0], 255);
|
||||
strictEqual(b32[1], 255);
|
||||
strictEqual(b32[2], 255);
|
||||
strictEqual(b32[3], 255);
|
||||
}
|
||||
|
||||
throws(() => {
|
||||
Buffer.copyBytesFrom();
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
});
|
||||
|
||||
['', Symbol(), true, false, {}, [], () => {}, 1, 1n, null, undefined].forEach(
|
||||
(notTypedArray) => throws(() => {
|
||||
Buffer.copyBytesFrom('nope');
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
})
|
||||
);
|
||||
|
||||
['', Symbol(), true, false, {}, [], () => {}, 1n].forEach((notANumber) =>
|
||||
throws(() => {
|
||||
Buffer.copyBytesFrom(new Uint8Array(1), notANumber);
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
})
|
||||
);
|
||||
|
||||
[-1, NaN, 1.1, -Infinity].forEach((outOfRange) =>
|
||||
throws(() => {
|
||||
Buffer.copyBytesFrom(new Uint8Array(1), outOfRange);
|
||||
}, {
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
})
|
||||
);
|
||||
|
||||
['', Symbol(), true, false, {}, [], () => {}, 1n].forEach((notANumber) =>
|
||||
throws(() => {
|
||||
Buffer.copyBytesFrom(new Uint8Array(1), 0, notANumber);
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
})
|
||||
);
|
||||
|
||||
[-1, NaN, 1.1, -Infinity].forEach((outOfRange) =>
|
||||
throws(() => {
|
||||
Buffer.copyBytesFrom(new Uint8Array(1), 0, outOfRange);
|
||||
}, {
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
})
|
||||
);
|
||||
304
test/js/node/test/parallel/test-buffer-includes.js
Normal file
304
test/js/node/test/parallel/test-buffer-includes.js
Normal file
@@ -0,0 +1,304 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const b = Buffer.from('abcdef');
|
||||
const buf_a = Buffer.from('a');
|
||||
const buf_bc = Buffer.from('bc');
|
||||
const buf_f = Buffer.from('f');
|
||||
const buf_z = Buffer.from('z');
|
||||
const buf_empty = Buffer.from('');
|
||||
|
||||
assert(b.includes('a'));
|
||||
assert(!b.includes('a', 1));
|
||||
assert(!b.includes('a', -1));
|
||||
assert(!b.includes('a', -4));
|
||||
assert(b.includes('a', -b.length));
|
||||
assert(b.includes('a', NaN));
|
||||
assert(b.includes('a', -Infinity));
|
||||
assert(!b.includes('a', Infinity));
|
||||
assert(b.includes('bc'));
|
||||
assert(!b.includes('bc', 2));
|
||||
assert(!b.includes('bc', -1));
|
||||
assert(!b.includes('bc', -3));
|
||||
assert(b.includes('bc', -5));
|
||||
assert(b.includes('bc', NaN));
|
||||
assert(b.includes('bc', -Infinity));
|
||||
assert(!b.includes('bc', Infinity));
|
||||
assert(b.includes('f'), b.length - 1);
|
||||
assert(!b.includes('z'));
|
||||
assert(b.includes(''));
|
||||
assert(b.includes('', 1));
|
||||
assert(b.includes('', b.length + 1));
|
||||
assert(b.includes('', Infinity));
|
||||
assert(b.includes(buf_a));
|
||||
assert(!b.includes(buf_a, 1));
|
||||
assert(!b.includes(buf_a, -1));
|
||||
assert(!b.includes(buf_a, -4));
|
||||
assert(b.includes(buf_a, -b.length));
|
||||
assert(b.includes(buf_a, NaN));
|
||||
assert(b.includes(buf_a, -Infinity));
|
||||
assert(!b.includes(buf_a, Infinity));
|
||||
assert(b.includes(buf_bc));
|
||||
assert(!b.includes(buf_bc, 2));
|
||||
assert(!b.includes(buf_bc, -1));
|
||||
assert(!b.includes(buf_bc, -3));
|
||||
assert(b.includes(buf_bc, -5));
|
||||
assert(b.includes(buf_bc, NaN));
|
||||
assert(b.includes(buf_bc, -Infinity));
|
||||
assert(!b.includes(buf_bc, Infinity));
|
||||
assert(b.includes(buf_f), b.length - 1);
|
||||
assert(!b.includes(buf_z));
|
||||
assert(b.includes(buf_empty));
|
||||
assert(b.includes(buf_empty, 1));
|
||||
assert(b.includes(buf_empty, b.length + 1));
|
||||
assert(b.includes(buf_empty, Infinity));
|
||||
assert(b.includes(0x61));
|
||||
assert(!b.includes(0x61, 1));
|
||||
assert(!b.includes(0x61, -1));
|
||||
assert(!b.includes(0x61, -4));
|
||||
assert(b.includes(0x61, -b.length));
|
||||
assert(b.includes(0x61, NaN));
|
||||
assert(b.includes(0x61, -Infinity));
|
||||
assert(!b.includes(0x61, Infinity));
|
||||
assert(!b.includes(0x0));
|
||||
|
||||
// test offsets
|
||||
assert(b.includes('d', 2));
|
||||
assert(b.includes('f', 5));
|
||||
assert(b.includes('f', -1));
|
||||
assert(!b.includes('f', 6));
|
||||
|
||||
assert(b.includes(Buffer.from('d'), 2));
|
||||
assert(b.includes(Buffer.from('f'), 5));
|
||||
assert(b.includes(Buffer.from('f'), -1));
|
||||
assert(!b.includes(Buffer.from('f'), 6));
|
||||
|
||||
assert(!Buffer.from('ff').includes(Buffer.from('f'), 1, 'ucs2'));
|
||||
|
||||
// test hex encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('hex'), 'hex')
|
||||
.includes('64', 0, 'hex'),
|
||||
true
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('hex'), 'hex')
|
||||
.includes(Buffer.from('64', 'hex'), 0, 'hex'),
|
||||
true
|
||||
);
|
||||
|
||||
// Test base64 encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('base64'), 'base64')
|
||||
.includes('ZA==', 0, 'base64'),
|
||||
true
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('base64'), 'base64')
|
||||
.includes(Buffer.from('ZA==', 'base64'), 0, 'base64'),
|
||||
true
|
||||
);
|
||||
|
||||
// test ascii encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('ascii'), 'ascii')
|
||||
.includes('d', 0, 'ascii'),
|
||||
true
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('ascii'), 'ascii')
|
||||
.includes(Buffer.from('d', 'ascii'), 0, 'ascii'),
|
||||
true
|
||||
);
|
||||
|
||||
// Test latin1 encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('latin1'), 'latin1')
|
||||
.includes('d', 0, 'latin1'),
|
||||
true
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('latin1'), 'latin1')
|
||||
.includes(Buffer.from('d', 'latin1'), 0, 'latin1'),
|
||||
true
|
||||
);
|
||||
|
||||
// Test binary encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('binary'), 'binary')
|
||||
.includes('d', 0, 'binary'),
|
||||
true
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('binary'), 'binary')
|
||||
.includes(Buffer.from('d', 'binary'), 0, 'binary'),
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
// test ucs2 encoding
|
||||
let twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2');
|
||||
|
||||
assert(twoByteString.includes('\u0395', 4, 'ucs2'));
|
||||
assert(twoByteString.includes('\u03a3', -4, 'ucs2'));
|
||||
assert(twoByteString.includes('\u03a3', -6, 'ucs2'));
|
||||
assert(twoByteString.includes(
|
||||
Buffer.from('\u03a3', 'ucs2'), -6, 'ucs2'));
|
||||
assert(!twoByteString.includes('\u03a3', -2, 'ucs2'));
|
||||
|
||||
const mixedByteStringUcs2 =
|
||||
Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395', 'ucs2');
|
||||
assert(mixedByteStringUcs2.includes('bc', 0, 'ucs2'));
|
||||
assert(mixedByteStringUcs2.includes('\u03a3', 0, 'ucs2'));
|
||||
assert(!mixedByteStringUcs2.includes('\u0396', 0, 'ucs2'));
|
||||
|
||||
assert.ok(
|
||||
mixedByteStringUcs2.includes(Buffer.from('bc', 'ucs2'), 0, 'ucs2'));
|
||||
assert.ok(
|
||||
mixedByteStringUcs2.includes(Buffer.from('\u03a3', 'ucs2'), 0, 'ucs2'));
|
||||
assert.ok(
|
||||
!mixedByteStringUcs2.includes(Buffer.from('\u0396', 'ucs2'), 0, 'ucs2'));
|
||||
|
||||
twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2');
|
||||
|
||||
// Test single char pattern
|
||||
assert(twoByteString.includes('\u039a', 0, 'ucs2'));
|
||||
assert(twoByteString.includes('\u0391', 0, 'ucs2'), 'Alpha');
|
||||
assert(twoByteString.includes('\u03a3', 0, 'ucs2'), 'First Sigma');
|
||||
assert(twoByteString.includes('\u03a3', 6, 'ucs2'), 'Second Sigma');
|
||||
assert(twoByteString.includes('\u0395', 0, 'ucs2'), 'Epsilon');
|
||||
assert(!twoByteString.includes('\u0392', 0, 'ucs2'), 'Not beta');
|
||||
|
||||
// Test multi-char pattern
|
||||
assert(twoByteString.includes('\u039a\u0391', 0, 'ucs2'), 'Lambda Alpha');
|
||||
assert(twoByteString.includes('\u0391\u03a3', 0, 'ucs2'), 'Alpha Sigma');
|
||||
assert(twoByteString.includes('\u03a3\u03a3', 0, 'ucs2'), 'Sigma Sigma');
|
||||
assert(twoByteString.includes('\u03a3\u0395', 0, 'ucs2'), 'Sigma Epsilon');
|
||||
|
||||
const mixedByteStringUtf8 = Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395');
|
||||
assert(mixedByteStringUtf8.includes('bc'));
|
||||
assert(mixedByteStringUtf8.includes('bc', 5));
|
||||
assert(mixedByteStringUtf8.includes('bc', -8));
|
||||
assert(mixedByteStringUtf8.includes('\u03a3'));
|
||||
assert(!mixedByteStringUtf8.includes('\u0396'));
|
||||
|
||||
|
||||
// Test complex string includes algorithms. Only trigger for long strings.
|
||||
// Long string that isn't a simple repeat of a shorter string.
|
||||
let longString = 'A';
|
||||
for (let i = 66; i < 76; i++) { // from 'B' to 'K'
|
||||
longString = longString + String.fromCharCode(i) + longString;
|
||||
}
|
||||
|
||||
const longBufferString = Buffer.from(longString);
|
||||
|
||||
// Pattern of 15 chars, repeated every 16 chars in long
|
||||
let pattern = 'ABACABADABACABA';
|
||||
for (let i = 0; i < longBufferString.length - pattern.length; i += 7) {
|
||||
const includes = longBufferString.includes(pattern, i);
|
||||
assert(includes, `Long ABACABA...-string at index ${i}`);
|
||||
}
|
||||
assert(longBufferString.includes('AJABACA'), 'Long AJABACA, First J');
|
||||
assert(longBufferString.includes('AJABACA', 511), 'Long AJABACA, Second J');
|
||||
|
||||
pattern = 'JABACABADABACABA';
|
||||
assert(longBufferString.includes(pattern), 'Long JABACABA..., First J');
|
||||
assert(longBufferString.includes(pattern, 512), 'Long JABACABA..., Second J');
|
||||
|
||||
// Search for a non-ASCII string in a pure ASCII string.
|
||||
const asciiString = Buffer.from(
|
||||
'arglebargleglopglyfarglebargleglopglyfarglebargleglopglyf');
|
||||
assert(!asciiString.includes('\x2061'));
|
||||
assert(asciiString.includes('leb', 0));
|
||||
|
||||
// Search in string containing many non-ASCII chars.
|
||||
const allCodePoints = [];
|
||||
for (let i = 0; i < 65534; i++) allCodePoints[i] = i;
|
||||
const allCharsString = String.fromCharCode.apply(String, allCodePoints) +
|
||||
String.fromCharCode(65534, 65535);
|
||||
const allCharsBufferUtf8 = Buffer.from(allCharsString);
|
||||
const allCharsBufferUcs2 = Buffer.from(allCharsString, 'ucs2');
|
||||
|
||||
// Search for string long enough to trigger complex search with ASCII pattern
|
||||
// and UC16 subject.
|
||||
assert(!allCharsBufferUtf8.includes('notfound'));
|
||||
assert(!allCharsBufferUcs2.includes('notfound'));
|
||||
|
||||
// Find substrings in Utf8.
|
||||
let lengths = [1, 3, 15]; // Single char, simple and complex.
|
||||
let indices = [0x5, 0x60, 0x400, 0x680, 0x7ee, 0xFF02, 0x16610, 0x2f77b];
|
||||
for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) {
|
||||
for (let i = 0; i < indices.length; i++) {
|
||||
const index = indices[i];
|
||||
let length = lengths[lengthIndex];
|
||||
|
||||
if (index + length > 0x7F) {
|
||||
length = 2 * length;
|
||||
}
|
||||
|
||||
if (index + length > 0x7FF) {
|
||||
length = 3 * length;
|
||||
}
|
||||
|
||||
if (index + length > 0xFFFF) {
|
||||
length = 4 * length;
|
||||
}
|
||||
|
||||
const patternBufferUtf8 = allCharsBufferUtf8.slice(index, index + length);
|
||||
assert(index, allCharsBufferUtf8.includes(patternBufferUtf8));
|
||||
|
||||
const patternStringUtf8 = patternBufferUtf8.toString();
|
||||
assert(index, allCharsBufferUtf8.includes(patternStringUtf8));
|
||||
}
|
||||
}
|
||||
|
||||
// Find substrings in Usc2.
|
||||
lengths = [2, 4, 16]; // Single char, simple and complex.
|
||||
indices = [0x5, 0x65, 0x105, 0x205, 0x285, 0x2005, 0x2085, 0xfff0];
|
||||
for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) {
|
||||
for (let i = 0; i < indices.length; i++) {
|
||||
const index = indices[i] * 2;
|
||||
const length = lengths[lengthIndex];
|
||||
|
||||
const patternBufferUcs2 =
|
||||
allCharsBufferUcs2.slice(index, index + length);
|
||||
assert.ok(
|
||||
allCharsBufferUcs2.includes(patternBufferUcs2, 0, 'ucs2'));
|
||||
|
||||
const patternStringUcs2 = patternBufferUcs2.toString('ucs2');
|
||||
assert.ok(
|
||||
allCharsBufferUcs2.includes(patternStringUcs2, 0, 'ucs2'));
|
||||
}
|
||||
}
|
||||
|
||||
[
|
||||
() => { },
|
||||
{},
|
||||
[],
|
||||
].forEach((val) => {
|
||||
assert.throws(
|
||||
() => b.includes(val),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "value" argument must be of type number, string, Buffer, or Uint8Array.' + common.invalidArgTypeHelper(val)
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Test truncation of Number arguments to uint8
|
||||
{
|
||||
const buf = Buffer.from('this is a test');
|
||||
assert.ok(buf.includes(0x6973));
|
||||
assert.ok(buf.includes(0x697320));
|
||||
assert.ok(buf.includes(0x69732069));
|
||||
assert.ok(buf.includes(0x697374657374));
|
||||
assert.ok(buf.includes(0x69737374));
|
||||
assert.ok(buf.includes(0x69737465));
|
||||
assert.ok(buf.includes(0x69737465));
|
||||
assert.ok(buf.includes(-140));
|
||||
assert.ok(buf.includes(-152));
|
||||
assert.ok(!buf.includes(0xff));
|
||||
assert.ok(!buf.includes(0xffff));
|
||||
}
|
||||
629
test/js/node/test/parallel/test-buffer-indexof.js
Normal file
629
test/js/node/test/parallel/test-buffer-indexof.js
Normal file
@@ -0,0 +1,629 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const b = Buffer.from('abcdef');
|
||||
const buf_a = Buffer.from('a');
|
||||
const buf_bc = Buffer.from('bc');
|
||||
const buf_f = Buffer.from('f');
|
||||
const buf_z = Buffer.from('z');
|
||||
const buf_empty = Buffer.from('');
|
||||
|
||||
const s = 'abcdef';
|
||||
|
||||
assert.strictEqual(b.indexOf('a'), 0);
|
||||
assert.strictEqual(b.indexOf('a', 1), -1);
|
||||
assert.strictEqual(b.indexOf('a', -1), -1);
|
||||
assert.strictEqual(b.indexOf('a', -4), -1);
|
||||
assert.strictEqual(b.indexOf('a', -b.length), 0);
|
||||
assert.strictEqual(b.indexOf('a', NaN), 0);
|
||||
assert.strictEqual(b.indexOf('a', -Infinity), 0);
|
||||
assert.strictEqual(b.indexOf('a', Infinity), -1);
|
||||
assert.strictEqual(b.indexOf('bc'), 1);
|
||||
assert.strictEqual(b.indexOf('bc', 2), -1);
|
||||
assert.strictEqual(b.indexOf('bc', -1), -1);
|
||||
assert.strictEqual(b.indexOf('bc', -3), -1);
|
||||
assert.strictEqual(b.indexOf('bc', -5), 1);
|
||||
assert.strictEqual(b.indexOf('bc', NaN), 1);
|
||||
assert.strictEqual(b.indexOf('bc', -Infinity), 1);
|
||||
assert.strictEqual(b.indexOf('bc', Infinity), -1);
|
||||
assert.strictEqual(b.indexOf('f'), b.length - 1);
|
||||
assert.strictEqual(b.indexOf('z'), -1);
|
||||
assert.strictEqual(b.indexOf(''), 0);
|
||||
assert.strictEqual(b.indexOf('', 1), 1);
|
||||
assert.strictEqual(b.indexOf('', b.length + 1), b.length);
|
||||
assert.strictEqual(b.indexOf('', Infinity), b.length);
|
||||
assert.strictEqual(b.indexOf(buf_a), 0);
|
||||
assert.strictEqual(b.indexOf(buf_a, 1), -1);
|
||||
assert.strictEqual(b.indexOf(buf_a, -1), -1);
|
||||
assert.strictEqual(b.indexOf(buf_a, -4), -1);
|
||||
assert.strictEqual(b.indexOf(buf_a, -b.length), 0);
|
||||
assert.strictEqual(b.indexOf(buf_a, NaN), 0);
|
||||
assert.strictEqual(b.indexOf(buf_a, -Infinity), 0);
|
||||
assert.strictEqual(b.indexOf(buf_a, Infinity), -1);
|
||||
assert.strictEqual(b.indexOf(buf_bc), 1);
|
||||
assert.strictEqual(b.indexOf(buf_bc, 2), -1);
|
||||
assert.strictEqual(b.indexOf(buf_bc, -1), -1);
|
||||
assert.strictEqual(b.indexOf(buf_bc, -3), -1);
|
||||
assert.strictEqual(b.indexOf(buf_bc, -5), 1);
|
||||
assert.strictEqual(b.indexOf(buf_bc, NaN), 1);
|
||||
assert.strictEqual(b.indexOf(buf_bc, -Infinity), 1);
|
||||
assert.strictEqual(b.indexOf(buf_bc, Infinity), -1);
|
||||
assert.strictEqual(b.indexOf(buf_f), b.length - 1);
|
||||
assert.strictEqual(b.indexOf(buf_z), -1);
|
||||
assert.strictEqual(b.indexOf(buf_empty), 0);
|
||||
assert.strictEqual(b.indexOf(buf_empty, 1), 1);
|
||||
assert.strictEqual(b.indexOf(buf_empty, b.length + 1), b.length);
|
||||
assert.strictEqual(b.indexOf(buf_empty, Infinity), b.length);
|
||||
assert.strictEqual(b.indexOf(0x61), 0);
|
||||
assert.strictEqual(b.indexOf(0x61, 1), -1);
|
||||
assert.strictEqual(b.indexOf(0x61, -1), -1);
|
||||
assert.strictEqual(b.indexOf(0x61, -4), -1);
|
||||
assert.strictEqual(b.indexOf(0x61, -b.length), 0);
|
||||
assert.strictEqual(b.indexOf(0x61, NaN), 0);
|
||||
assert.strictEqual(b.indexOf(0x61, -Infinity), 0);
|
||||
assert.strictEqual(b.indexOf(0x61, Infinity), -1);
|
||||
assert.strictEqual(b.indexOf(0x0), -1);
|
||||
|
||||
// test offsets
|
||||
assert.strictEqual(b.indexOf('d', 2), 3);
|
||||
assert.strictEqual(b.indexOf('f', 5), 5);
|
||||
assert.strictEqual(b.indexOf('f', -1), 5);
|
||||
assert.strictEqual(b.indexOf('f', 6), -1);
|
||||
|
||||
assert.strictEqual(b.indexOf(Buffer.from('d'), 2), 3);
|
||||
assert.strictEqual(b.indexOf(Buffer.from('f'), 5), 5);
|
||||
assert.strictEqual(b.indexOf(Buffer.from('f'), -1), 5);
|
||||
assert.strictEqual(b.indexOf(Buffer.from('f'), 6), -1);
|
||||
|
||||
assert.strictEqual(Buffer.from('ff').indexOf(Buffer.from('f'), 1, 'ucs2'), -1);
|
||||
|
||||
// Test invalid and uppercase encoding
|
||||
assert.strictEqual(b.indexOf('b', 'utf8'), 1);
|
||||
assert.strictEqual(b.indexOf('b', 'UTF8'), 1);
|
||||
assert.strictEqual(b.indexOf('62', 'HEX'), 1);
|
||||
assert.throws(() => b.indexOf('bad', 'enc'), /Unknown encoding: enc/);
|
||||
|
||||
// test hex encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('hex'), 'hex')
|
||||
.indexOf('64', 0, 'hex'),
|
||||
3
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('hex'), 'hex')
|
||||
.indexOf(Buffer.from('64', 'hex'), 0, 'hex'),
|
||||
3
|
||||
);
|
||||
|
||||
// Test base64 encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('base64'), 'base64')
|
||||
.indexOf('ZA==', 0, 'base64'),
|
||||
3
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('base64'), 'base64')
|
||||
.indexOf(Buffer.from('ZA==', 'base64'), 0, 'base64'),
|
||||
3
|
||||
);
|
||||
|
||||
// Test base64url encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('base64url'), 'base64url')
|
||||
.indexOf('ZA==', 0, 'base64url'),
|
||||
3
|
||||
);
|
||||
|
||||
// test ascii encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('ascii'), 'ascii')
|
||||
.indexOf('d', 0, 'ascii'),
|
||||
3
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('ascii'), 'ascii')
|
||||
.indexOf(Buffer.from('d', 'ascii'), 0, 'ascii'),
|
||||
3
|
||||
);
|
||||
|
||||
// Test latin1 encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('latin1'), 'latin1')
|
||||
.indexOf('d', 0, 'latin1'),
|
||||
3
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('latin1'), 'latin1')
|
||||
.indexOf(Buffer.from('d', 'latin1'), 0, 'latin1'),
|
||||
3
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from('aa\u00e8aa', 'latin1')
|
||||
.indexOf('\u00e8', 'latin1'),
|
||||
2
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from('\u00e8', 'latin1')
|
||||
.indexOf('\u00e8', 'latin1'),
|
||||
0
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from('\u00e8', 'latin1')
|
||||
.indexOf(Buffer.from('\u00e8', 'latin1'), 'latin1'),
|
||||
0
|
||||
);
|
||||
|
||||
// Test binary encoding
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('binary'), 'binary')
|
||||
.indexOf('d', 0, 'binary'),
|
||||
3
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(b.toString('binary'), 'binary')
|
||||
.indexOf(Buffer.from('d', 'binary'), 0, 'binary'),
|
||||
3
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from('aa\u00e8aa', 'binary')
|
||||
.indexOf('\u00e8', 'binary'),
|
||||
2
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from('\u00e8', 'binary')
|
||||
.indexOf('\u00e8', 'binary'),
|
||||
0
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from('\u00e8', 'binary')
|
||||
.indexOf(Buffer.from('\u00e8', 'binary'), 'binary'),
|
||||
0
|
||||
);
|
||||
|
||||
|
||||
// Test optional offset with passed encoding
|
||||
assert.strictEqual(Buffer.from('aaaa0').indexOf('30', 'hex'), 4);
|
||||
assert.strictEqual(Buffer.from('aaaa00a').indexOf('3030', 'hex'), 4);
|
||||
|
||||
{
|
||||
// Test usc2 and utf16le encoding
|
||||
['ucs2', 'utf16le'].forEach((encoding) => {
|
||||
const twoByteString = Buffer.from(
|
||||
'\u039a\u0391\u03a3\u03a3\u0395', encoding);
|
||||
|
||||
assert.strictEqual(twoByteString.indexOf('\u0395', 4, encoding), 8);
|
||||
assert.strictEqual(twoByteString.indexOf('\u03a3', -4, encoding), 6);
|
||||
assert.strictEqual(twoByteString.indexOf('\u03a3', -6, encoding), 4);
|
||||
assert.strictEqual(twoByteString.indexOf(
|
||||
Buffer.from('\u03a3', encoding), -6, encoding), 4);
|
||||
assert.strictEqual(-1, twoByteString.indexOf('\u03a3', -2, encoding));
|
||||
});
|
||||
}
|
||||
|
||||
const mixedByteStringUcs2 =
|
||||
Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395', 'ucs2');
|
||||
assert.strictEqual(mixedByteStringUcs2.indexOf('bc', 0, 'ucs2'), 6);
|
||||
assert.strictEqual(mixedByteStringUcs2.indexOf('\u03a3', 0, 'ucs2'), 10);
|
||||
assert.strictEqual(-1, mixedByteStringUcs2.indexOf('\u0396', 0, 'ucs2'));
|
||||
|
||||
assert.strictEqual(
|
||||
mixedByteStringUcs2.indexOf(Buffer.from('bc', 'ucs2'), 0, 'ucs2'), 6);
|
||||
assert.strictEqual(
|
||||
mixedByteStringUcs2.indexOf(Buffer.from('\u03a3', 'ucs2'), 0, 'ucs2'), 10);
|
||||
assert.strictEqual(
|
||||
-1, mixedByteStringUcs2.indexOf(Buffer.from('\u0396', 'ucs2'), 0, 'ucs2'));
|
||||
|
||||
{
|
||||
const twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2');
|
||||
|
||||
// Test single char pattern
|
||||
assert.strictEqual(twoByteString.indexOf('\u039a', 0, 'ucs2'), 0);
|
||||
let index = twoByteString.indexOf('\u0391', 0, 'ucs2');
|
||||
assert.strictEqual(index, 2, `Alpha - at index ${index}`);
|
||||
index = twoByteString.indexOf('\u03a3', 0, 'ucs2');
|
||||
assert.strictEqual(index, 4, `First Sigma - at index ${index}`);
|
||||
index = twoByteString.indexOf('\u03a3', 6, 'ucs2');
|
||||
assert.strictEqual(index, 6, `Second Sigma - at index ${index}`);
|
||||
index = twoByteString.indexOf('\u0395', 0, 'ucs2');
|
||||
assert.strictEqual(index, 8, `Epsilon - at index ${index}`);
|
||||
index = twoByteString.indexOf('\u0392', 0, 'ucs2');
|
||||
assert.strictEqual(-1, index, `Not beta - at index ${index}`);
|
||||
|
||||
// Test multi-char pattern
|
||||
index = twoByteString.indexOf('\u039a\u0391', 0, 'ucs2');
|
||||
assert.strictEqual(index, 0, `Lambda Alpha - at index ${index}`);
|
||||
index = twoByteString.indexOf('\u0391\u03a3', 0, 'ucs2');
|
||||
assert.strictEqual(index, 2, `Alpha Sigma - at index ${index}`);
|
||||
index = twoByteString.indexOf('\u03a3\u03a3', 0, 'ucs2');
|
||||
assert.strictEqual(index, 4, `Sigma Sigma - at index ${index}`);
|
||||
index = twoByteString.indexOf('\u03a3\u0395', 0, 'ucs2');
|
||||
assert.strictEqual(index, 6, `Sigma Epsilon - at index ${index}`);
|
||||
}
|
||||
|
||||
const mixedByteStringUtf8 = Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395');
|
||||
assert.strictEqual(mixedByteStringUtf8.indexOf('bc'), 5);
|
||||
assert.strictEqual(mixedByteStringUtf8.indexOf('bc', 5), 5);
|
||||
assert.strictEqual(mixedByteStringUtf8.indexOf('bc', -8), 5);
|
||||
assert.strictEqual(mixedByteStringUtf8.indexOf('\u03a3'), 7);
|
||||
assert.strictEqual(mixedByteStringUtf8.indexOf('\u0396'), -1);
|
||||
|
||||
|
||||
// Test complex string indexOf algorithms. Only trigger for long strings.
|
||||
// Long string that isn't a simple repeat of a shorter string.
|
||||
let longString = 'A';
|
||||
for (let i = 66; i < 76; i++) { // from 'B' to 'K'
|
||||
longString = longString + String.fromCharCode(i) + longString;
|
||||
}
|
||||
|
||||
const longBufferString = Buffer.from(longString);
|
||||
|
||||
// Pattern of 15 chars, repeated every 16 chars in long
|
||||
let pattern = 'ABACABADABACABA';
|
||||
for (let i = 0; i < longBufferString.length - pattern.length; i += 7) {
|
||||
const index = longBufferString.indexOf(pattern, i);
|
||||
assert.strictEqual((i + 15) & ~0xf, index,
|
||||
`Long ABACABA...-string at index ${i}`);
|
||||
}
|
||||
|
||||
let index = longBufferString.indexOf('AJABACA');
|
||||
assert.strictEqual(index, 510, `Long AJABACA, First J - at index ${index}`);
|
||||
index = longBufferString.indexOf('AJABACA', 511);
|
||||
assert.strictEqual(index, 1534, `Long AJABACA, Second J - at index ${index}`);
|
||||
|
||||
pattern = 'JABACABADABACABA';
|
||||
index = longBufferString.indexOf(pattern);
|
||||
assert.strictEqual(index, 511, `Long JABACABA..., First J - at index ${index}`);
|
||||
index = longBufferString.indexOf(pattern, 512);
|
||||
assert.strictEqual(
|
||||
index, 1535, `Long JABACABA..., Second J - at index ${index}`);
|
||||
|
||||
// Search for a non-ASCII string in a pure ASCII string.
|
||||
const asciiString = Buffer.from(
|
||||
'arglebargleglopglyfarglebargleglopglyfarglebargleglopglyf');
|
||||
assert.strictEqual(-1, asciiString.indexOf('\x2061'));
|
||||
assert.strictEqual(asciiString.indexOf('leb', 0), 3);
|
||||
|
||||
// Search in string containing many non-ASCII chars.
|
||||
const allCodePoints = [];
|
||||
for (let i = 0; i < 65534; i++) allCodePoints[i] = i;
|
||||
const allCharsString = String.fromCharCode.apply(String, allCodePoints) + String.fromCharCode(65534, 65535);
|
||||
const allCharsBufferUtf8 = Buffer.from(allCharsString);
|
||||
const allCharsBufferUcs2 = Buffer.from(allCharsString, 'ucs2');
|
||||
|
||||
// Search for string long enough to trigger complex search with ASCII pattern
|
||||
// and UC16 subject.
|
||||
assert.strictEqual(-1, allCharsBufferUtf8.indexOf('notfound'));
|
||||
assert.strictEqual(-1, allCharsBufferUcs2.indexOf('notfound'));
|
||||
|
||||
// Needle is longer than haystack, but only because it's encoded as UTF-16
|
||||
assert.strictEqual(Buffer.from('aaaa').indexOf('a'.repeat(4), 'ucs2'), -1);
|
||||
|
||||
assert.strictEqual(Buffer.from('aaaa').indexOf('a'.repeat(4), 'utf8'), 0);
|
||||
assert.strictEqual(Buffer.from('aaaa').indexOf('你好', 'ucs2'), -1);
|
||||
|
||||
// Haystack has odd length, but the needle is UCS2.
|
||||
assert.strictEqual(Buffer.from('aaaaa').indexOf('b', 'ucs2'), -1);
|
||||
|
||||
{
|
||||
// Find substrings in Utf8.
|
||||
const lengths = [1, 3, 15]; // Single char, simple and complex.
|
||||
const indices = [0x5, 0x60, 0x400, 0x680, 0x7ee, 0xFF02, 0x16610, 0x2f77b];
|
||||
for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) {
|
||||
for (let i = 0; i < indices.length; i++) {
|
||||
const index = indices[i];
|
||||
let length = lengths[lengthIndex];
|
||||
|
||||
if (index + length > 0x7F) {
|
||||
length = 2 * length;
|
||||
}
|
||||
|
||||
if (index + length > 0x7FF) {
|
||||
length = 3 * length;
|
||||
}
|
||||
|
||||
if (index + length > 0xFFFF) {
|
||||
length = 4 * length;
|
||||
}
|
||||
|
||||
const patternBufferUtf8 = allCharsBufferUtf8.slice(index, index + length);
|
||||
assert.strictEqual(index, allCharsBufferUtf8.indexOf(patternBufferUtf8));
|
||||
|
||||
const patternStringUtf8 = patternBufferUtf8.toString();
|
||||
assert.strictEqual(index, allCharsBufferUtf8.indexOf(patternStringUtf8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Find substrings in Usc2.
|
||||
const lengths = [2, 4, 16]; // Single char, simple and complex.
|
||||
const indices = [0x5, 0x65, 0x105, 0x205, 0x285, 0x2005, 0x2085, 0xfff0];
|
||||
for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) {
|
||||
for (let i = 0; i < indices.length; i++) {
|
||||
const index = indices[i] * 2;
|
||||
const length = lengths[lengthIndex];
|
||||
|
||||
const patternBufferUcs2 = allCharsBufferUcs2.slice(index, index + length);
|
||||
const actualB = allCharsBufferUcs2.indexOf(patternBufferUcs2, 0, 'ucs2');
|
||||
assert.strictEqual(actualB, index);
|
||||
|
||||
const patternStringUcs2 = patternBufferUcs2.toString('ucs2');
|
||||
const actualS = allCharsBufferUcs2.indexOf(patternStringUcs2, 0, 'ucs2');
|
||||
assert.strictEqual(actualS, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[
|
||||
() => {},
|
||||
{},
|
||||
[],
|
||||
].forEach((val) => {
|
||||
assert.throws(
|
||||
() => b.indexOf(val),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "value" argument must be of type number, string, Buffer, or Uint8Array.' + common.invalidArgTypeHelper(val)
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Test weird offset arguments.
|
||||
// The following offsets coerce to NaN or 0, searching the whole Buffer
|
||||
assert.strictEqual(b.indexOf('b', undefined), 1);
|
||||
assert.strictEqual(b.indexOf('b', {}), 1);
|
||||
assert.strictEqual(b.indexOf('b', 0), 1);
|
||||
assert.strictEqual(b.indexOf('b', null), 1);
|
||||
assert.strictEqual(b.indexOf('b', []), 1);
|
||||
|
||||
// The following offset coerces to 2, in other words +[2] === 2
|
||||
assert.strictEqual(b.indexOf('b', [2]), -1);
|
||||
|
||||
// Behavior should match String.indexOf()
|
||||
assert.strictEqual(
|
||||
b.indexOf('b', undefined),
|
||||
s.indexOf('b', undefined));
|
||||
assert.strictEqual(
|
||||
b.indexOf('b', {}),
|
||||
s.indexOf('b', {}));
|
||||
assert.strictEqual(
|
||||
b.indexOf('b', 0),
|
||||
s.indexOf('b', 0));
|
||||
assert.strictEqual(
|
||||
b.indexOf('b', null),
|
||||
s.indexOf('b', null));
|
||||
assert.strictEqual(
|
||||
b.indexOf('b', []),
|
||||
s.indexOf('b', []));
|
||||
assert.strictEqual(
|
||||
b.indexOf('b', [2]),
|
||||
s.indexOf('b', [2]));
|
||||
|
||||
// All code for handling encodings is shared between Buffer.indexOf and
|
||||
// Buffer.lastIndexOf, so only testing the separate lastIndexOf semantics.
|
||||
|
||||
// Test lastIndexOf basic functionality; Buffer b contains 'abcdef'.
|
||||
// lastIndexOf string:
|
||||
assert.strictEqual(b.lastIndexOf('a'), 0);
|
||||
assert.strictEqual(b.lastIndexOf('a', 1), 0);
|
||||
assert.strictEqual(b.lastIndexOf('b', 1), 1);
|
||||
assert.strictEqual(b.lastIndexOf('c', 1), -1);
|
||||
assert.strictEqual(b.lastIndexOf('a', -1), 0);
|
||||
assert.strictEqual(b.lastIndexOf('a', -4), 0);
|
||||
assert.strictEqual(b.lastIndexOf('a', -b.length), 0);
|
||||
assert.strictEqual(b.lastIndexOf('a', -b.length - 1), -1);
|
||||
assert.strictEqual(b.lastIndexOf('a', NaN), 0);
|
||||
assert.strictEqual(b.lastIndexOf('a', -Infinity), -1);
|
||||
assert.strictEqual(b.lastIndexOf('a', Infinity), 0);
|
||||
// lastIndexOf Buffer:
|
||||
assert.strictEqual(b.lastIndexOf(buf_a), 0);
|
||||
assert.strictEqual(b.lastIndexOf(buf_a, 1), 0);
|
||||
assert.strictEqual(b.lastIndexOf(buf_a, -1), 0);
|
||||
assert.strictEqual(b.lastIndexOf(buf_a, -4), 0);
|
||||
assert.strictEqual(b.lastIndexOf(buf_a, -b.length), 0);
|
||||
assert.strictEqual(b.lastIndexOf(buf_a, -b.length - 1), -1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_a, NaN), 0);
|
||||
assert.strictEqual(b.lastIndexOf(buf_a, -Infinity), -1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_a, Infinity), 0);
|
||||
assert.strictEqual(b.lastIndexOf(buf_bc), 1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_bc, 2), 1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_bc, -1), 1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_bc, -3), 1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_bc, -5), 1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_bc, -6), -1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_bc, NaN), 1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_bc, -Infinity), -1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_bc, Infinity), 1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_f), b.length - 1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_z), -1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_empty), b.length);
|
||||
assert.strictEqual(b.lastIndexOf(buf_empty, 1), 1);
|
||||
assert.strictEqual(b.lastIndexOf(buf_empty, b.length + 1), b.length);
|
||||
assert.strictEqual(b.lastIndexOf(buf_empty, Infinity), b.length);
|
||||
// lastIndexOf number:
|
||||
assert.strictEqual(b.lastIndexOf(0x61), 0);
|
||||
assert.strictEqual(b.lastIndexOf(0x61, 1), 0);
|
||||
assert.strictEqual(b.lastIndexOf(0x61, -1), 0);
|
||||
assert.strictEqual(b.lastIndexOf(0x61, -4), 0);
|
||||
assert.strictEqual(b.lastIndexOf(0x61, -b.length), 0);
|
||||
assert.strictEqual(b.lastIndexOf(0x61, -b.length - 1), -1);
|
||||
assert.strictEqual(b.lastIndexOf(0x61, NaN), 0);
|
||||
assert.strictEqual(b.lastIndexOf(0x61, -Infinity), -1);
|
||||
assert.strictEqual(b.lastIndexOf(0x61, Infinity), 0);
|
||||
assert.strictEqual(b.lastIndexOf(0x0), -1);
|
||||
|
||||
// Test weird offset arguments.
|
||||
// The following offsets coerce to NaN, searching the whole Buffer
|
||||
assert.strictEqual(b.lastIndexOf('b', undefined), 1);
|
||||
assert.strictEqual(b.lastIndexOf('b', {}), 1);
|
||||
|
||||
// The following offsets coerce to 0
|
||||
assert.strictEqual(b.lastIndexOf('b', 0), -1);
|
||||
assert.strictEqual(b.lastIndexOf('b', null), -1);
|
||||
assert.strictEqual(b.lastIndexOf('b', []), -1);
|
||||
|
||||
// The following offset coerces to 2, in other words +[2] === 2
|
||||
assert.strictEqual(b.lastIndexOf('b', [2]), 1);
|
||||
|
||||
// Behavior should match String.lastIndexOf()
|
||||
assert.strictEqual(
|
||||
b.lastIndexOf('b', undefined),
|
||||
s.lastIndexOf('b', undefined));
|
||||
assert.strictEqual(
|
||||
b.lastIndexOf('b', {}),
|
||||
s.lastIndexOf('b', {}));
|
||||
assert.strictEqual(
|
||||
b.lastIndexOf('b', 0),
|
||||
s.lastIndexOf('b', 0));
|
||||
assert.strictEqual(
|
||||
b.lastIndexOf('b', null),
|
||||
s.lastIndexOf('b', null));
|
||||
assert.strictEqual(
|
||||
b.lastIndexOf('b', []),
|
||||
s.lastIndexOf('b', []));
|
||||
assert.strictEqual(
|
||||
b.lastIndexOf('b', [2]),
|
||||
s.lastIndexOf('b', [2]));
|
||||
|
||||
// Test needles longer than the haystack.
|
||||
assert.strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 'ucs2'), -1);
|
||||
assert.strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 'utf8'), -1);
|
||||
assert.strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 'latin1'), -1);
|
||||
assert.strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 'binary'), -1);
|
||||
assert.strictEqual(b.lastIndexOf(Buffer.from('aaaaaaaaaaaaaaa')), -1);
|
||||
assert.strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 2, 'ucs2'), -1);
|
||||
assert.strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 3, 'utf8'), -1);
|
||||
assert.strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 5, 'latin1'), -1);
|
||||
assert.strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 5, 'binary'), -1);
|
||||
assert.strictEqual(b.lastIndexOf(Buffer.from('aaaaaaaaaaaaaaa'), 7), -1);
|
||||
|
||||
// 你好 expands to a total of 6 bytes using UTF-8 and 4 bytes using UTF-16
|
||||
assert.strictEqual(buf_bc.lastIndexOf('你好', 'ucs2'), -1);
|
||||
assert.strictEqual(buf_bc.lastIndexOf('你好', 'utf8'), -1);
|
||||
assert.strictEqual(buf_bc.lastIndexOf('你好', 'latin1'), -1);
|
||||
assert.strictEqual(buf_bc.lastIndexOf('你好', 'binary'), -1);
|
||||
assert.strictEqual(buf_bc.lastIndexOf(Buffer.from('你好')), -1);
|
||||
assert.strictEqual(buf_bc.lastIndexOf('你好', 2, 'ucs2'), -1);
|
||||
assert.strictEqual(buf_bc.lastIndexOf('你好', 3, 'utf8'), -1);
|
||||
assert.strictEqual(buf_bc.lastIndexOf('你好', 5, 'latin1'), -1);
|
||||
assert.strictEqual(buf_bc.lastIndexOf('你好', 5, 'binary'), -1);
|
||||
assert.strictEqual(buf_bc.lastIndexOf(Buffer.from('你好'), 7), -1);
|
||||
|
||||
// Test lastIndexOf on a longer buffer:
|
||||
const bufferString = Buffer.from('a man a plan a canal panama');
|
||||
assert.strictEqual(bufferString.lastIndexOf('canal'), 15);
|
||||
assert.strictEqual(bufferString.lastIndexOf('panama'), 21);
|
||||
assert.strictEqual(bufferString.lastIndexOf('a man a plan a canal panama'), 0);
|
||||
assert.strictEqual(-1, bufferString.lastIndexOf('a man a plan a canal mexico'));
|
||||
assert.strictEqual(-1, bufferString
|
||||
.lastIndexOf('a man a plan a canal mexico city'));
|
||||
assert.strictEqual(-1, bufferString.lastIndexOf(Buffer.from('a'.repeat(1000))));
|
||||
assert.strictEqual(bufferString.lastIndexOf('a man a plan', 4), 0);
|
||||
assert.strictEqual(bufferString.lastIndexOf('a '), 13);
|
||||
assert.strictEqual(bufferString.lastIndexOf('a ', 13), 13);
|
||||
assert.strictEqual(bufferString.lastIndexOf('a ', 12), 6);
|
||||
assert.strictEqual(bufferString.lastIndexOf('a ', 5), 0);
|
||||
assert.strictEqual(bufferString.lastIndexOf('a ', -1), 13);
|
||||
assert.strictEqual(bufferString.lastIndexOf('a ', -27), 0);
|
||||
assert.strictEqual(-1, bufferString.lastIndexOf('a ', -28));
|
||||
|
||||
// Test lastIndexOf for the case that the first character can be found,
|
||||
// but in a part of the buffer that does not make search to search
|
||||
// due do length constraints.
|
||||
const abInUCS2 = Buffer.from('ab', 'ucs2');
|
||||
assert.strictEqual(-1, Buffer.from('µaaaa¶bbbb', 'latin1').lastIndexOf('µ'));
|
||||
assert.strictEqual(-1, Buffer.from('µaaaa¶bbbb', 'binary').lastIndexOf('µ'));
|
||||
assert.strictEqual(-1, Buffer.from('bc').lastIndexOf('ab'));
|
||||
assert.strictEqual(-1, Buffer.from('abc').lastIndexOf('qa'));
|
||||
assert.strictEqual(-1, Buffer.from('abcdef').lastIndexOf('qabc'));
|
||||
assert.strictEqual(-1, Buffer.from('bc').lastIndexOf(Buffer.from('ab')));
|
||||
assert.strictEqual(-1, Buffer.from('bc', 'ucs2').lastIndexOf('ab', 'ucs2'));
|
||||
assert.strictEqual(-1, Buffer.from('bc', 'ucs2').lastIndexOf(abInUCS2));
|
||||
|
||||
assert.strictEqual(Buffer.from('abc').lastIndexOf('ab'), 0);
|
||||
assert.strictEqual(Buffer.from('abc').lastIndexOf('ab', 1), 0);
|
||||
assert.strictEqual(Buffer.from('abc').lastIndexOf('ab', 2), 0);
|
||||
assert.strictEqual(Buffer.from('abc').lastIndexOf('ab', 3), 0);
|
||||
|
||||
// The above tests test the LINEAR and SINGLE-CHAR strategies.
|
||||
// Now, we test the BOYER-MOORE-HORSPOOL strategy.
|
||||
// Test lastIndexOf on a long buffer w multiple matches:
|
||||
pattern = 'JABACABADABACABA';
|
||||
assert.strictEqual(longBufferString.lastIndexOf(pattern), 1535);
|
||||
assert.strictEqual(longBufferString.lastIndexOf(pattern, 1535), 1535);
|
||||
assert.strictEqual(longBufferString.lastIndexOf(pattern, 1534), 511);
|
||||
|
||||
// Finally, give it a really long input to trigger fallback from BMH to
|
||||
// regular BOYER-MOORE (which has better worst-case complexity).
|
||||
|
||||
// Generate a really long Thue-Morse sequence of 'yolo' and 'swag',
|
||||
// "yolo swag swag yolo swag yolo yolo swag" ..., goes on for about 5MB.
|
||||
// This is hard to search because it all looks similar, but never repeats.
|
||||
|
||||
// countBits returns the number of bits in the binary representation of n.
|
||||
function countBits(n) {
|
||||
let count;
|
||||
for (count = 0; n > 0; count++) {
|
||||
n = n & (n - 1); // remove top bit
|
||||
}
|
||||
return count;
|
||||
}
|
||||
const parts = [];
|
||||
for (let i = 0; i < 1000000; i++) {
|
||||
parts.push((countBits(i) % 2 === 0) ? 'yolo' : 'swag');
|
||||
}
|
||||
const reallyLong = Buffer.from(parts.join(' '));
|
||||
assert.strictEqual(reallyLong.slice(0, 19).toString(), 'yolo swag swag yolo');
|
||||
|
||||
// Expensive reverse searches. Stress test lastIndexOf:
|
||||
pattern = reallyLong.slice(0, 100000); // First 1/50th of the pattern.
|
||||
assert.strictEqual(reallyLong.lastIndexOf(pattern), 4751360);
|
||||
assert.strictEqual(reallyLong.lastIndexOf(pattern, 4000000), 3932160);
|
||||
assert.strictEqual(reallyLong.lastIndexOf(pattern, 3000000), 2949120);
|
||||
pattern = reallyLong.slice(100000, 200000); // Second 1/50th.
|
||||
assert.strictEqual(reallyLong.lastIndexOf(pattern), 4728480);
|
||||
pattern = reallyLong.slice(0, 1000000); // First 1/5th.
|
||||
assert.strictEqual(reallyLong.lastIndexOf(pattern), 3932160);
|
||||
pattern = reallyLong.slice(0, 2000000); // first 2/5ths.
|
||||
assert.strictEqual(reallyLong.lastIndexOf(pattern), 0);
|
||||
|
||||
// Test truncation of Number arguments to uint8
|
||||
{
|
||||
const buf = Buffer.from('this is a test');
|
||||
assert.strictEqual(buf.indexOf(0x6973), 3);
|
||||
assert.strictEqual(buf.indexOf(0x697320), 4);
|
||||
assert.strictEqual(buf.indexOf(0x69732069), 2);
|
||||
assert.strictEqual(buf.indexOf(0x697374657374), 0);
|
||||
assert.strictEqual(buf.indexOf(0x69737374), 0);
|
||||
assert.strictEqual(buf.indexOf(0x69737465), 11);
|
||||
assert.strictEqual(buf.indexOf(0x69737465), 11);
|
||||
assert.strictEqual(buf.indexOf(-140), 0);
|
||||
assert.strictEqual(buf.indexOf(-152), 1);
|
||||
assert.strictEqual(buf.indexOf(0xff), -1);
|
||||
assert.strictEqual(buf.indexOf(0xffff), -1);
|
||||
}
|
||||
|
||||
// Test that Uint8Array arguments are okay.
|
||||
{
|
||||
const needle = new Uint8Array([ 0x66, 0x6f, 0x6f ]);
|
||||
const haystack = Buffer.from('a foo b foo');
|
||||
assert.strictEqual(haystack.indexOf(needle), 2);
|
||||
assert.strictEqual(haystack.lastIndexOf(needle), haystack.length - 3);
|
||||
}
|
||||
|
||||
// Avoid abort because of invalid usage
|
||||
// see https://github.com/nodejs/node/issues/32753
|
||||
// {
|
||||
// assert.throws(() => {
|
||||
// const buffer = require('buffer');
|
||||
// new buffer.Buffer.prototype.lastIndexOf(1, 'str');
|
||||
// }, {
|
||||
// code: 'ERR_INVALID_ARG_TYPE',
|
||||
// name: 'TypeError',
|
||||
// message: 'The "buffer" argument must be an instance of Buffer, ' +
|
||||
// 'TypedArray, or DataView. ' +
|
||||
// 'Received an instance of lastIndexOf'
|
||||
// });
|
||||
// }
|
||||
10
test/js/node/test/parallel/test-buffer-new.js
Normal file
10
test/js/node/test/parallel/test-buffer-new.js
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
assert.throws(() => new Buffer(42, 'utf8'), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "string" argument must be of type string. Received type number (42)'
|
||||
});
|
||||
106
test/js/node/test/parallel/test-buffer-read.js
Normal file
106
test/js/node/test/parallel/test-buffer-read.js
Normal file
@@ -0,0 +1,106 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Testing basic buffer read functions
|
||||
const buf = Buffer.from([0xa4, 0xfd, 0x48, 0xea, 0xcf, 0xff, 0xd9, 0x01, 0xde]);
|
||||
|
||||
function read(buff, funx, args, expected) {
|
||||
assert.strictEqual(buff[funx](...args), expected);
|
||||
assert.throws(
|
||||
() => buff[funx](-1, args[1]),
|
||||
{ name: 'RangeError', code: 'ERR_OUT_OF_RANGE' }
|
||||
);
|
||||
}
|
||||
|
||||
// Testing basic functionality of readDoubleBE() and readDoubleLE()
|
||||
read(buf, 'readDoubleBE', [1], -3.1827727774563287e+295);
|
||||
read(buf, 'readDoubleLE', [1], -6.966010051009108e+144);
|
||||
|
||||
// Testing basic functionality of readFloatBE() and readFloatLE()
|
||||
read(buf, 'readFloatBE', [1], -1.6691549692541768e+37);
|
||||
read(buf, 'readFloatLE', [1], -7861303808);
|
||||
|
||||
// Testing basic functionality of readInt8()
|
||||
read(buf, 'readInt8', [1], -3);
|
||||
|
||||
// Testing basic functionality of readInt16BE() and readInt16LE()
|
||||
read(buf, 'readInt16BE', [1], -696);
|
||||
read(buf, 'readInt16LE', [1], 0x48fd);
|
||||
|
||||
// Testing basic functionality of readInt32BE() and readInt32LE()
|
||||
read(buf, 'readInt32BE', [1], -45552945);
|
||||
read(buf, 'readInt32LE', [1], -806729475);
|
||||
|
||||
// Testing basic functionality of readIntBE() and readIntLE()
|
||||
read(buf, 'readIntBE', [1, 1], -3);
|
||||
read(buf, 'readIntLE', [2, 1], 0x48);
|
||||
|
||||
// Testing basic functionality of readUInt8()
|
||||
read(buf, 'readUInt8', [1], 0xfd);
|
||||
|
||||
// Testing basic functionality of readUInt16BE() and readUInt16LE()
|
||||
read(buf, 'readUInt16BE', [2], 0x48ea);
|
||||
read(buf, 'readUInt16LE', [2], 0xea48);
|
||||
|
||||
// Testing basic functionality of readUInt32BE() and readUInt32LE()
|
||||
read(buf, 'readUInt32BE', [1], 0xfd48eacf);
|
||||
read(buf, 'readUInt32LE', [1], 0xcfea48fd);
|
||||
|
||||
// Testing basic functionality of readUIntBE() and readUIntLE()
|
||||
read(buf, 'readUIntBE', [2, 2], 0x48ea);
|
||||
read(buf, 'readUIntLE', [2, 2], 0xea48);
|
||||
|
||||
// Error name and message
|
||||
const OOR_ERROR =
|
||||
{
|
||||
name: 'RangeError'
|
||||
};
|
||||
|
||||
const OOB_ERROR =
|
||||
{
|
||||
name: 'RangeError',
|
||||
message: 'Attempt to access memory outside buffer bounds'
|
||||
};
|
||||
|
||||
// Attempt to overflow buffers, similar to previous bug in array buffers
|
||||
assert.throws(
|
||||
() => Buffer.allocUnsafe(8).readFloatBE(0xffffffff), OOR_ERROR);
|
||||
|
||||
assert.throws(
|
||||
() => Buffer.allocUnsafe(8).readFloatLE(0xffffffff), OOR_ERROR);
|
||||
|
||||
// Ensure negative values can't get past offset
|
||||
assert.throws(
|
||||
() => Buffer.allocUnsafe(8).readFloatBE(-1), OOR_ERROR);
|
||||
assert.throws(
|
||||
() => Buffer.allocUnsafe(8).readFloatLE(-1), OOR_ERROR);
|
||||
|
||||
// Offset checks
|
||||
{
|
||||
const buf = Buffer.allocUnsafe(0);
|
||||
|
||||
assert.throws(
|
||||
() => buf.readUInt8(0), OOB_ERROR);
|
||||
assert.throws(
|
||||
() => buf.readInt8(0), OOB_ERROR);
|
||||
}
|
||||
|
||||
[16, 32].forEach((bit) => {
|
||||
const buf = Buffer.allocUnsafe(bit / 8 - 1);
|
||||
[`Int${bit}B`, `Int${bit}L`, `UInt${bit}B`, `UInt${bit}L`].forEach((fn) => {
|
||||
assert.throws(
|
||||
() => buf[`read${fn}E`](0), OOB_ERROR);
|
||||
});
|
||||
});
|
||||
|
||||
[16, 32].forEach((bits) => {
|
||||
const buf = Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]);
|
||||
['LE', 'BE'].forEach((endian) => {
|
||||
assert.strictEqual(buf[`readUInt${bits}${endian}`](0),
|
||||
(0xFFFFFFFF >>> (32 - bits)));
|
||||
|
||||
assert.strictEqual(buf[`readInt${bits}${endian}`](0),
|
||||
(0xFFFFFFFF >> (32 - bits)));
|
||||
});
|
||||
});
|
||||
148
test/js/node/test/parallel/test-buffer-readdouble.js
Normal file
148
test/js/node/test/parallel/test-buffer-readdouble.js
Normal file
@@ -0,0 +1,148 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Test (64 bit) double
|
||||
const buffer = Buffer.allocUnsafe(8);
|
||||
|
||||
buffer[0] = 0x55;
|
||||
buffer[1] = 0x55;
|
||||
buffer[2] = 0x55;
|
||||
buffer[3] = 0x55;
|
||||
buffer[4] = 0x55;
|
||||
buffer[5] = 0x55;
|
||||
buffer[6] = 0xd5;
|
||||
buffer[7] = 0x3f;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 1.1945305291680097e+103);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), 0.3333333333333333);
|
||||
|
||||
buffer[0] = 1;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0;
|
||||
buffer[4] = 0;
|
||||
buffer[5] = 0;
|
||||
buffer[6] = 0xf0;
|
||||
buffer[7] = 0x3f;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 7.291122019655968e-304);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), 1.0000000000000002);
|
||||
|
||||
buffer[0] = 2;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 4.778309726801735e-299);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), 1.0000000000000004);
|
||||
|
||||
buffer[0] = 1;
|
||||
buffer[6] = 0;
|
||||
buffer[7] = 0;
|
||||
// eslint-disable-next-line no-loss-of-precision
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 7.291122019556398e-304);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), 5e-324);
|
||||
|
||||
buffer[0] = 0xff;
|
||||
buffer[1] = 0xff;
|
||||
buffer[2] = 0xff;
|
||||
buffer[3] = 0xff;
|
||||
buffer[4] = 0xff;
|
||||
buffer[5] = 0xff;
|
||||
buffer[6] = 0x0f;
|
||||
buffer[7] = 0x00;
|
||||
assert.ok(Number.isNaN(buffer.readDoubleBE(0)));
|
||||
assert.strictEqual(buffer.readDoubleLE(0), 2.225073858507201e-308);
|
||||
|
||||
buffer[6] = 0xef;
|
||||
buffer[7] = 0x7f;
|
||||
assert.ok(Number.isNaN(buffer.readDoubleBE(0)));
|
||||
assert.strictEqual(buffer.readDoubleLE(0), 1.7976931348623157e+308);
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0;
|
||||
buffer[4] = 0;
|
||||
buffer[5] = 0;
|
||||
buffer[6] = 0xf0;
|
||||
buffer[7] = 0x3f;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 3.03865e-319);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), 1);
|
||||
|
||||
buffer[6] = 0;
|
||||
buffer[7] = 0x40;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 3.16e-322);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), 2);
|
||||
|
||||
buffer[7] = 0xc0;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 9.5e-322);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), -2);
|
||||
|
||||
buffer[6] = 0x10;
|
||||
buffer[7] = 0;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 2.0237e-320);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), 2.2250738585072014e-308);
|
||||
|
||||
buffer[6] = 0;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 0);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), 0);
|
||||
assert.ok(1 / buffer.readDoubleLE(0) >= 0);
|
||||
|
||||
buffer[7] = 0x80;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 6.3e-322);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), -0);
|
||||
assert.ok(1 / buffer.readDoubleLE(0) < 0);
|
||||
|
||||
buffer[6] = 0xf0;
|
||||
buffer[7] = 0x7f;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 3.0418e-319);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), Infinity);
|
||||
|
||||
buffer[7] = 0xff;
|
||||
assert.strictEqual(buffer.readDoubleBE(0), 3.04814e-319);
|
||||
assert.strictEqual(buffer.readDoubleLE(0), -Infinity);
|
||||
|
||||
['readDoubleLE', 'readDoubleBE'].forEach((fn) => {
|
||||
|
||||
// Verify that default offset works fine.
|
||||
buffer[fn](undefined);
|
||||
buffer[fn]();
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((off) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](off),
|
||||
{
|
||||
name: 'TypeError',
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: `The "offset" argument must be of type number.${common.invalidArgTypeHelper(off)}`,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
[-1, 1].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be >= 0 and <= 0. Received ${offset}`
|
||||
});
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => Buffer.alloc(1)[fn](1),
|
||||
{
|
||||
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
name: 'RangeError',
|
||||
message: 'Attempt to access memory outside buffer bounds'
|
||||
});
|
||||
|
||||
[Infinity, NaN, 1.01].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be an integer. Received ${offset}`
|
||||
});
|
||||
});
|
||||
});
|
||||
110
test/js/node/test/parallel/test-buffer-readfloat.js
Normal file
110
test/js/node/test/parallel/test-buffer-readfloat.js
Normal file
@@ -0,0 +1,110 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Test 32 bit float
|
||||
const buffer = Buffer.alloc(4);
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0x80;
|
||||
buffer[3] = 0x3f;
|
||||
assert.strictEqual(buffer.readFloatBE(0), 4.600602988224807e-41);
|
||||
assert.strictEqual(buffer.readFloatLE(0), 1);
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0xc0;
|
||||
assert.strictEqual(buffer.readFloatBE(0), 2.6904930515036488e-43);
|
||||
assert.strictEqual(buffer.readFloatLE(0), -2);
|
||||
|
||||
buffer[0] = 0xff;
|
||||
buffer[1] = 0xff;
|
||||
buffer[2] = 0x7f;
|
||||
buffer[3] = 0x7f;
|
||||
assert.ok(Number.isNaN(buffer.readFloatBE(0)));
|
||||
assert.strictEqual(buffer.readFloatLE(0), 3.4028234663852886e+38);
|
||||
|
||||
buffer[0] = 0xab;
|
||||
buffer[1] = 0xaa;
|
||||
buffer[2] = 0xaa;
|
||||
buffer[3] = 0x3e;
|
||||
assert.strictEqual(buffer.readFloatBE(0), -1.2126478207002966e-12);
|
||||
assert.strictEqual(buffer.readFloatLE(0), 0.3333333432674408);
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0;
|
||||
assert.strictEqual(buffer.readFloatBE(0), 0);
|
||||
assert.strictEqual(buffer.readFloatLE(0), 0);
|
||||
assert.ok(1 / buffer.readFloatLE(0) >= 0);
|
||||
|
||||
buffer[3] = 0x80;
|
||||
assert.strictEqual(buffer.readFloatBE(0), 1.793662034335766e-43);
|
||||
assert.strictEqual(buffer.readFloatLE(0), -0);
|
||||
assert.ok(1 / buffer.readFloatLE(0) < 0);
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0x80;
|
||||
buffer[3] = 0x7f;
|
||||
assert.strictEqual(buffer.readFloatBE(0), 4.609571298396486e-41);
|
||||
assert.strictEqual(buffer.readFloatLE(0), Infinity);
|
||||
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0x80;
|
||||
buffer[3] = 0xff;
|
||||
assert.strictEqual(buffer.readFloatBE(0), 4.627507918739843e-41);
|
||||
assert.strictEqual(buffer.readFloatLE(0), -Infinity);
|
||||
|
||||
['readFloatLE', 'readFloatBE'].forEach((fn) => {
|
||||
|
||||
// Verify that default offset works fine.
|
||||
buffer[fn](undefined);
|
||||
buffer[fn]();
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((off) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](off),
|
||||
{
|
||||
name: 'TypeError',
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: `The "offset" argument must be of type number.${common.invalidArgTypeHelper(off)}`,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
[-1, 1].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be >= 0 and <= 0. Received ${offset}`
|
||||
});
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => Buffer.alloc(1)[fn](1),
|
||||
{
|
||||
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
name: 'RangeError',
|
||||
message: 'Attempt to access memory outside buffer bounds'
|
||||
});
|
||||
|
||||
[Infinity, NaN, 1.01].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be an integer. Received ${offset}`
|
||||
});
|
||||
});
|
||||
});
|
||||
198
test/js/node/test/parallel/test-buffer-readint.js
Normal file
198
test/js/node/test/parallel/test-buffer-readint.js
Normal file
@@ -0,0 +1,198 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
// Test OOB
|
||||
{
|
||||
const buffer = Buffer.alloc(4);
|
||||
|
||||
['Int8', 'Int16BE', 'Int16LE', 'Int32BE', 'Int32LE'].forEach((fn) => {
|
||||
|
||||
// Verify that default offset works fine.
|
||||
buffer[`read${fn}`](undefined);
|
||||
buffer[`read${fn}`]();
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((o) => {
|
||||
assert.throws(
|
||||
() => buffer[`read${fn}`](o),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: `The "offset" argument must be of type number.${common.invalidArgTypeHelper(o)}`,
|
||||
});
|
||||
});
|
||||
|
||||
[Infinity, -1, -4294967295].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[`read${fn}`](offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError'
|
||||
});
|
||||
});
|
||||
|
||||
[NaN, 1.01].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[`read${fn}`](offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be an integer. Received ${offset}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Test 8 bit signed integers
|
||||
{
|
||||
const data = Buffer.from([0x23, 0xab, 0x7c, 0xef]);
|
||||
|
||||
assert.strictEqual(data.readInt8(0), 0x23);
|
||||
|
||||
data[0] = 0xff;
|
||||
assert.strictEqual(data.readInt8(0), -1);
|
||||
|
||||
data[0] = 0x87;
|
||||
assert.strictEqual(data.readInt8(0), -121);
|
||||
assert.strictEqual(data.readInt8(1), -85);
|
||||
assert.strictEqual(data.readInt8(2), 124);
|
||||
assert.strictEqual(data.readInt8(3), -17);
|
||||
}
|
||||
|
||||
// Test 16 bit integers
|
||||
{
|
||||
const buffer = Buffer.from([0x16, 0x79, 0x65, 0x6e, 0x69, 0x78]);
|
||||
|
||||
assert.strictEqual(buffer.readInt16BE(0), 0x1679);
|
||||
assert.strictEqual(buffer.readInt16LE(0), 0x7916);
|
||||
|
||||
buffer[0] = 0xff;
|
||||
buffer[1] = 0x80;
|
||||
assert.strictEqual(buffer.readInt16BE(0), -128);
|
||||
assert.strictEqual(buffer.readInt16LE(0), -32513);
|
||||
|
||||
buffer[0] = 0x77;
|
||||
buffer[1] = 0x65;
|
||||
assert.strictEqual(buffer.readInt16BE(0), 0x7765);
|
||||
assert.strictEqual(buffer.readInt16BE(1), 0x6565);
|
||||
assert.strictEqual(buffer.readInt16BE(2), 0x656e);
|
||||
assert.strictEqual(buffer.readInt16BE(3), 0x6e69);
|
||||
assert.strictEqual(buffer.readInt16BE(4), 0x6978);
|
||||
assert.strictEqual(buffer.readInt16LE(0), 0x6577);
|
||||
assert.strictEqual(buffer.readInt16LE(1), 0x6565);
|
||||
assert.strictEqual(buffer.readInt16LE(2), 0x6e65);
|
||||
assert.strictEqual(buffer.readInt16LE(3), 0x696e);
|
||||
assert.strictEqual(buffer.readInt16LE(4), 0x7869);
|
||||
}
|
||||
|
||||
// Test 32 bit integers
|
||||
{
|
||||
const buffer = Buffer.from([0x43, 0x53, 0x16, 0x79, 0x36, 0x17]);
|
||||
|
||||
assert.strictEqual(buffer.readInt32BE(0), 0x43531679);
|
||||
assert.strictEqual(buffer.readInt32LE(0), 0x79165343);
|
||||
|
||||
buffer[0] = 0xff;
|
||||
buffer[1] = 0xfe;
|
||||
buffer[2] = 0xef;
|
||||
buffer[3] = 0xfa;
|
||||
assert.strictEqual(buffer.readInt32BE(0), -69638);
|
||||
assert.strictEqual(buffer.readInt32LE(0), -84934913);
|
||||
|
||||
buffer[0] = 0x42;
|
||||
buffer[1] = 0xc3;
|
||||
buffer[2] = 0x95;
|
||||
buffer[3] = 0xa9;
|
||||
assert.strictEqual(buffer.readInt32BE(0), 0x42c395a9);
|
||||
assert.strictEqual(buffer.readInt32BE(1), -1013601994);
|
||||
assert.strictEqual(buffer.readInt32BE(2), -1784072681);
|
||||
assert.strictEqual(buffer.readInt32LE(0), -1449802942);
|
||||
assert.strictEqual(buffer.readInt32LE(1), 917083587);
|
||||
assert.strictEqual(buffer.readInt32LE(2), 389458325);
|
||||
}
|
||||
|
||||
// Test Int
|
||||
{
|
||||
const buffer = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
|
||||
|
||||
assert.strictEqual(buffer.readIntLE(0, 1), 0x01);
|
||||
assert.strictEqual(buffer.readIntBE(0, 1), 0x01);
|
||||
assert.strictEqual(buffer.readIntLE(0, 3), 0x030201);
|
||||
assert.strictEqual(buffer.readIntBE(0, 3), 0x010203);
|
||||
assert.strictEqual(buffer.readIntLE(0, 5), 0x0504030201);
|
||||
assert.strictEqual(buffer.readIntBE(0, 5), 0x0102030405);
|
||||
assert.strictEqual(buffer.readIntLE(0, 6), 0x060504030201);
|
||||
assert.strictEqual(buffer.readIntBE(0, 6), 0x010203040506);
|
||||
assert.strictEqual(buffer.readIntLE(1, 6), 0x070605040302);
|
||||
assert.strictEqual(buffer.readIntBE(1, 6), 0x020304050607);
|
||||
assert.strictEqual(buffer.readIntLE(2, 6), 0x080706050403);
|
||||
assert.strictEqual(buffer.readIntBE(2, 6), 0x030405060708);
|
||||
|
||||
// Check byteLength.
|
||||
['readIntBE', 'readIntLE'].forEach((fn) => {
|
||||
['', '0', null, {}, [], () => {}, true, false, undefined].forEach((len) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](0, len),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' });
|
||||
});
|
||||
|
||||
[Infinity, -1].forEach((byteLength) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](0, byteLength),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
message: 'The value of "byteLength" is out of range. ' +
|
||||
`It must be >= 1 and <= 6. Received ${byteLength}`
|
||||
});
|
||||
});
|
||||
|
||||
[NaN, 1.01].forEach((byteLength) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](0, byteLength),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "byteLength" is out of range. ' +
|
||||
`It must be an integer. Received ${byteLength}`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Test 1 to 6 bytes.
|
||||
for (let i = 1; i <= 6; i++) {
|
||||
['readIntBE', 'readIntLE'].forEach((fn) => {
|
||||
['', '0', null, {}, [], () => {}, true, false, undefined].forEach((o) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](o, i),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError'
|
||||
});
|
||||
});
|
||||
|
||||
[-1, -4294967295].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](offset, i),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be >= 0 and <= ${8 - i}. Received ${offset}`
|
||||
});
|
||||
});
|
||||
|
||||
[Infinity, NaN, 1.01].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](offset, i),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be an integer. Received ${offset}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
168
test/js/node/test/parallel/test-buffer-readuint.js
Normal file
168
test/js/node/test/parallel/test-buffer-readuint.js
Normal file
@@ -0,0 +1,168 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const common = require('../common');
|
||||
|
||||
// Test OOB
|
||||
{
|
||||
const buffer = Buffer.alloc(4);
|
||||
|
||||
['UInt8', 'UInt16BE', 'UInt16LE', 'UInt32BE', 'UInt32LE'].forEach((fn) => {
|
||||
|
||||
// Verify that default offset works fine.
|
||||
buffer[`read${fn}`](undefined);
|
||||
buffer[`read${fn}`]();
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((o) => {
|
||||
assert.throws(
|
||||
() => buffer[`read${fn}`](o),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: `The "offset" argument must be of type number.${common.invalidArgTypeHelper(o)}`,
|
||||
});
|
||||
});
|
||||
|
||||
[Infinity, -1, -4294967295].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[`read${fn}`](offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
});
|
||||
});
|
||||
|
||||
[NaN, 1.01].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[`read${fn}`](offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be an integer. Received ${offset}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Test 8 bit unsigned integers
|
||||
{
|
||||
const data = Buffer.from([0xff, 0x2a, 0x2a, 0x2a]);
|
||||
assert.strictEqual(data.readUInt8(0), 255);
|
||||
assert.strictEqual(data.readUInt8(1), 42);
|
||||
assert.strictEqual(data.readUInt8(2), 42);
|
||||
assert.strictEqual(data.readUInt8(3), 42);
|
||||
}
|
||||
|
||||
// Test 16 bit unsigned integers
|
||||
{
|
||||
const data = Buffer.from([0x00, 0x2a, 0x42, 0x3f]);
|
||||
assert.strictEqual(data.readUInt16BE(0), 0x2a);
|
||||
assert.strictEqual(data.readUInt16BE(1), 0x2a42);
|
||||
assert.strictEqual(data.readUInt16BE(2), 0x423f);
|
||||
assert.strictEqual(data.readUInt16LE(0), 0x2a00);
|
||||
assert.strictEqual(data.readUInt16LE(1), 0x422a);
|
||||
assert.strictEqual(data.readUInt16LE(2), 0x3f42);
|
||||
|
||||
data[0] = 0xfe;
|
||||
data[1] = 0xfe;
|
||||
assert.strictEqual(data.readUInt16BE(0), 0xfefe);
|
||||
assert.strictEqual(data.readUInt16LE(0), 0xfefe);
|
||||
}
|
||||
|
||||
// Test 32 bit unsigned integers
|
||||
{
|
||||
const data = Buffer.from([0x32, 0x65, 0x42, 0x56, 0x23, 0xff]);
|
||||
assert.strictEqual(data.readUInt32BE(0), 0x32654256);
|
||||
assert.strictEqual(data.readUInt32BE(1), 0x65425623);
|
||||
assert.strictEqual(data.readUInt32BE(2), 0x425623ff);
|
||||
assert.strictEqual(data.readUInt32LE(0), 0x56426532);
|
||||
assert.strictEqual(data.readUInt32LE(1), 0x23564265);
|
||||
assert.strictEqual(data.readUInt32LE(2), 0xff235642);
|
||||
}
|
||||
|
||||
// Test UInt
|
||||
{
|
||||
const buffer = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
|
||||
|
||||
assert.strictEqual(buffer.readUIntLE(0, 1), 0x01);
|
||||
assert.strictEqual(buffer.readUIntBE(0, 1), 0x01);
|
||||
assert.strictEqual(buffer.readUIntLE(0, 3), 0x030201);
|
||||
assert.strictEqual(buffer.readUIntBE(0, 3), 0x010203);
|
||||
assert.strictEqual(buffer.readUIntLE(0, 5), 0x0504030201);
|
||||
assert.strictEqual(buffer.readUIntBE(0, 5), 0x0102030405);
|
||||
assert.strictEqual(buffer.readUIntLE(0, 6), 0x060504030201);
|
||||
assert.strictEqual(buffer.readUIntBE(0, 6), 0x010203040506);
|
||||
assert.strictEqual(buffer.readUIntLE(1, 6), 0x070605040302);
|
||||
assert.strictEqual(buffer.readUIntBE(1, 6), 0x020304050607);
|
||||
assert.strictEqual(buffer.readUIntLE(2, 6), 0x080706050403);
|
||||
assert.strictEqual(buffer.readUIntBE(2, 6), 0x030405060708);
|
||||
|
||||
// Check byteLength.
|
||||
['readUIntBE', 'readUIntLE'].forEach((fn) => {
|
||||
['', '0', null, {}, [], () => {}, true, false, undefined].forEach((len) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](0, len),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' });
|
||||
});
|
||||
|
||||
[Infinity, -1].forEach((byteLength) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](0, byteLength),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
message: 'The value of "byteLength" is out of range. ' +
|
||||
`It must be >= 1 and <= 6. Received ${byteLength}`
|
||||
});
|
||||
});
|
||||
|
||||
[NaN, 1.01].forEach((byteLength) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](0, byteLength),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "byteLength" is out of range. ' +
|
||||
`It must be an integer. Received ${byteLength}`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Test 1 to 6 bytes.
|
||||
for (let i = 1; i <= 6; i++) {
|
||||
['readUIntBE', 'readUIntLE'].forEach((fn) => {
|
||||
['', '0', null, {}, [], () => {}, true, false, undefined].forEach((o) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](o, i),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: `The "offset" argument must be of type number.${common.invalidArgTypeHelper(o)}`,
|
||||
});
|
||||
});
|
||||
|
||||
[-1, -4294967295].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](offset, i),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be >= 0 and <= ${8 - i}. Received ${offset}`
|
||||
});
|
||||
});
|
||||
|
||||
[Infinity, NaN, 1.01].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](offset, i),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be an integer. Received ${offset}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
27
test/js/node/test/parallel/test-buffer-sharedarraybuffer.js
Normal file
27
test/js/node/test/parallel/test-buffer-sharedarraybuffer.js
Normal file
@@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const sab = new SharedArrayBuffer(24);
|
||||
const arr1 = new Uint16Array(sab);
|
||||
const arr2 = new Uint16Array(12);
|
||||
arr2[0] = 5000;
|
||||
arr1[0] = 5000;
|
||||
arr1[1] = 4000;
|
||||
arr2[1] = 4000;
|
||||
|
||||
const arr_buf = Buffer.from(arr1.buffer);
|
||||
const ar_buf = Buffer.from(arr2.buffer);
|
||||
|
||||
assert.deepStrictEqual(arr_buf, ar_buf);
|
||||
|
||||
arr1[1] = 6000;
|
||||
arr2[1] = 6000;
|
||||
|
||||
assert.deepStrictEqual(arr_buf, ar_buf);
|
||||
|
||||
// Checks for calling Buffer.byteLength on a SharedArrayBuffer.
|
||||
assert.strictEqual(Buffer.byteLength(sab), sab.byteLength);
|
||||
|
||||
Buffer.from({ buffer: sab }); // Should not throw.
|
||||
108
test/js/node/test/parallel/test-buffer-write.js
Normal file
108
test/js/node/test/parallel/test-buffer-write.js
Normal file
@@ -0,0 +1,108 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
[-1, 10].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => Buffer.alloc(9).write('foo', offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be >= 0 and <= 9. Received ${offset}`
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const resultMap = new Map([
|
||||
['utf8', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
|
||||
['ucs2', Buffer.from([102, 0, 111, 0, 111, 0, 0, 0, 0])],
|
||||
['ascii', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
|
||||
['latin1', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
|
||||
['binary', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
|
||||
['utf16le', Buffer.from([102, 0, 111, 0, 111, 0, 0, 0, 0])],
|
||||
['base64', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
|
||||
['base64url', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
|
||||
['hex', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])],
|
||||
]);
|
||||
|
||||
// utf8, ucs2, ascii, latin1, utf16le
|
||||
const encodings = ['utf8', 'utf-8', 'ucs2', 'ucs-2', 'ascii', 'latin1',
|
||||
'binary', 'utf16le', 'utf-16le'];
|
||||
|
||||
encodings
|
||||
.reduce((es, e) => es.concat(e, e.toUpperCase()), [])
|
||||
.forEach((encoding) => {
|
||||
const buf = Buffer.alloc(9);
|
||||
const len = Buffer.byteLength('foo', encoding);
|
||||
assert.strictEqual(buf.write('foo', 0, len, encoding), len);
|
||||
|
||||
if (encoding.includes('-'))
|
||||
encoding = encoding.replace('-', '');
|
||||
|
||||
assert.deepStrictEqual(buf, resultMap.get(encoding.toLowerCase()));
|
||||
});
|
||||
|
||||
// base64
|
||||
['base64', 'BASE64', 'base64url', 'BASE64URL'].forEach((encoding) => {
|
||||
const buf = Buffer.alloc(9);
|
||||
const len = Buffer.byteLength('Zm9v', encoding);
|
||||
|
||||
assert.strictEqual(buf.write('Zm9v', 0, len, encoding), len);
|
||||
assert.deepStrictEqual(buf, resultMap.get(encoding.toLowerCase()));
|
||||
});
|
||||
|
||||
// hex
|
||||
['hex', 'HEX'].forEach((encoding) => {
|
||||
const buf = Buffer.alloc(9);
|
||||
const len = Buffer.byteLength('666f6f', encoding);
|
||||
|
||||
assert.strictEqual(buf.write('666f6f', 0, len, encoding), len);
|
||||
assert.deepStrictEqual(buf, resultMap.get(encoding.toLowerCase()));
|
||||
});
|
||||
|
||||
// Invalid encodings
|
||||
for (let i = 1; i < 10; i++) {
|
||||
const encoding = String(i).repeat(i);
|
||||
const error = common.expectsError({
|
||||
code: 'ERR_UNKNOWN_ENCODING',
|
||||
name: 'TypeError',
|
||||
message: `Unknown encoding: ${encoding}`
|
||||
});
|
||||
|
||||
assert.ok(!Buffer.isEncoding(encoding));
|
||||
assert.throws(() => Buffer.alloc(9).write('foo', encoding), error);
|
||||
}
|
||||
|
||||
// UCS-2 overflow CVE-2018-12115
|
||||
for (let i = 1; i < 4; i++) {
|
||||
// Allocate two Buffers sequentially off the pool. Run more than once in case
|
||||
// we hit the end of the pool and don't get sequential allocations
|
||||
const x = Buffer.allocUnsafe(4).fill(0);
|
||||
const y = Buffer.allocUnsafe(4).fill(1);
|
||||
// Should not write anything, pos 3 doesn't have enough room for a 16-bit char
|
||||
assert.strictEqual(x.write('ыыыыыы', 3, 'ucs2'), 0);
|
||||
// CVE-2018-12115 experienced via buffer overrun to next block in the pool
|
||||
assert.strictEqual(Buffer.compare(y, Buffer.alloc(4, 1)), 0);
|
||||
}
|
||||
|
||||
// Should not write any data when there is no space for 16-bit chars
|
||||
const z = Buffer.alloc(4, 0);
|
||||
assert.strictEqual(z.write('\u0001', 3, 'ucs2'), 0);
|
||||
assert.strictEqual(Buffer.compare(z, Buffer.alloc(4, 0)), 0);
|
||||
// Make sure longer strings are written up to the buffer end.
|
||||
assert.strictEqual(z.write('abcd', 2), 2);
|
||||
assert.deepStrictEqual([...z], [0, 0, 0x61, 0x62]);
|
||||
|
||||
// Large overrun could corrupt the process
|
||||
assert.strictEqual(Buffer.alloc(4)
|
||||
.write('ыыыыыы'.repeat(100), 3, 'utf16le'), 0);
|
||||
|
||||
{
|
||||
// .write() does not affect the byte after the written-to slice of the Buffer.
|
||||
// Refs: https://github.com/nodejs/node/issues/26422
|
||||
const buf = Buffer.alloc(8);
|
||||
assert.strictEqual(buf.write('ыы', 1, 'utf16le'), 4);
|
||||
assert.deepStrictEqual([...buf], [0, 0x4b, 0x04, 0x4b, 0x04, 0, 0, 0]);
|
||||
}
|
||||
133
test/js/node/test/parallel/test-buffer-writedouble.js
Normal file
133
test/js/node/test/parallel/test-buffer-writedouble.js
Normal file
@@ -0,0 +1,133 @@
|
||||
'use strict';
|
||||
|
||||
// Tests to verify doubles are correctly written
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const buffer = Buffer.allocUnsafe(16);
|
||||
|
||||
buffer.writeDoubleBE(2.225073858507201e-308, 0);
|
||||
buffer.writeDoubleLE(2.225073858507201e-308, 8);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
|
||||
])));
|
||||
|
||||
buffer.writeDoubleBE(1.0000000000000004, 0);
|
||||
buffer.writeDoubleLE(1.0000000000000004, 8);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f,
|
||||
])));
|
||||
|
||||
buffer.writeDoubleBE(-2, 0);
|
||||
buffer.writeDoubleLE(-2, 8);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
|
||||
])));
|
||||
|
||||
buffer.writeDoubleBE(1.7976931348623157e+308, 0);
|
||||
buffer.writeDoubleLE(1.7976931348623157e+308, 8);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f,
|
||||
])));
|
||||
|
||||
buffer.writeDoubleBE(0 * -1, 0);
|
||||
buffer.writeDoubleLE(0 * -1, 8);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
])));
|
||||
|
||||
buffer.writeDoubleBE(Infinity, 0);
|
||||
buffer.writeDoubleLE(Infinity, 8);
|
||||
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F,
|
||||
])));
|
||||
|
||||
assert.strictEqual(buffer.readDoubleBE(0), Infinity);
|
||||
assert.strictEqual(buffer.readDoubleLE(8), Infinity);
|
||||
|
||||
buffer.writeDoubleBE(-Infinity, 0);
|
||||
buffer.writeDoubleLE(-Infinity, 8);
|
||||
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF,
|
||||
])));
|
||||
|
||||
assert.strictEqual(buffer.readDoubleBE(0), -Infinity);
|
||||
assert.strictEqual(buffer.readDoubleLE(8), -Infinity);
|
||||
|
||||
buffer.writeDoubleBE(NaN, 0);
|
||||
buffer.writeDoubleLE(NaN, 8);
|
||||
|
||||
// JS only knows a single NaN but there exist two platform specific
|
||||
// implementations. Therefore, allow both quiet and signalling NaNs.
|
||||
if (buffer[1] === 0xF7) {
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x7F,
|
||||
])));
|
||||
} else {
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x7F,
|
||||
])));
|
||||
}
|
||||
|
||||
assert.ok(Number.isNaN(buffer.readDoubleBE(0)));
|
||||
assert.ok(Number.isNaN(buffer.readDoubleLE(8)));
|
||||
|
||||
// OOB in writeDouble{LE,BE} should throw.
|
||||
{
|
||||
const small = Buffer.allocUnsafe(1);
|
||||
|
||||
['writeDoubleLE', 'writeDoubleBE'].forEach((fn) => {
|
||||
|
||||
// Verify that default offset works fine.
|
||||
buffer[fn](23, undefined);
|
||||
buffer[fn](23);
|
||||
|
||||
assert.throws(
|
||||
() => small[fn](11.11, 0),
|
||||
{
|
||||
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
name: 'RangeError',
|
||||
message: 'Attempt to access memory outside buffer bounds'
|
||||
});
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((off) => {
|
||||
assert.throws(
|
||||
() => small[fn](23, off),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' });
|
||||
});
|
||||
|
||||
[Infinity, -1, 9].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](23, offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be >= 0 and <= 8. Received ${offset}`
|
||||
});
|
||||
});
|
||||
|
||||
[NaN, 1.01].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](42, offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be an integer. Received ${offset}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
117
test/js/node/test/parallel/test-buffer-writefloat.js
Normal file
117
test/js/node/test/parallel/test-buffer-writefloat.js
Normal file
@@ -0,0 +1,117 @@
|
||||
'use strict';
|
||||
|
||||
// Tests to verify floats are correctly written
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
const buffer = Buffer.allocUnsafe(8);
|
||||
|
||||
buffer.writeFloatBE(1, 0);
|
||||
buffer.writeFloatLE(1, 4);
|
||||
assert.ok(buffer.equals(
|
||||
new Uint8Array([ 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f ])));
|
||||
|
||||
buffer.writeFloatBE(1 / 3, 0);
|
||||
buffer.writeFloatLE(1 / 3, 4);
|
||||
assert.ok(buffer.equals(
|
||||
new Uint8Array([ 0x3e, 0xaa, 0xaa, 0xab, 0xab, 0xaa, 0xaa, 0x3e ])));
|
||||
|
||||
buffer.writeFloatBE(3.4028234663852886e+38, 0);
|
||||
buffer.writeFloatLE(3.4028234663852886e+38, 4);
|
||||
assert.ok(buffer.equals(
|
||||
new Uint8Array([ 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f ])));
|
||||
|
||||
buffer.writeFloatLE(1.1754943508222875e-38, 0);
|
||||
buffer.writeFloatBE(1.1754943508222875e-38, 4);
|
||||
assert.ok(buffer.equals(
|
||||
new Uint8Array([ 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00 ])));
|
||||
|
||||
buffer.writeFloatBE(0 * -1, 0);
|
||||
buffer.writeFloatLE(0 * -1, 4);
|
||||
assert.ok(buffer.equals(
|
||||
new Uint8Array([ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 ])));
|
||||
|
||||
buffer.writeFloatBE(Infinity, 0);
|
||||
buffer.writeFloatLE(Infinity, 4);
|
||||
assert.ok(buffer.equals(
|
||||
new Uint8Array([ 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F ])));
|
||||
|
||||
assert.strictEqual(buffer.readFloatBE(0), Infinity);
|
||||
assert.strictEqual(buffer.readFloatLE(4), Infinity);
|
||||
|
||||
buffer.writeFloatBE(-Infinity, 0);
|
||||
buffer.writeFloatLE(-Infinity, 4);
|
||||
assert.ok(buffer.equals(
|
||||
new Uint8Array([ 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF ])));
|
||||
|
||||
assert.strictEqual(buffer.readFloatBE(0), -Infinity);
|
||||
assert.strictEqual(buffer.readFloatLE(4), -Infinity);
|
||||
|
||||
buffer.writeFloatBE(NaN, 0);
|
||||
buffer.writeFloatLE(NaN, 4);
|
||||
|
||||
// JS only knows a single NaN but there exist two platform specific
|
||||
// implementations. Therefore, allow both quiet and signalling NaNs.
|
||||
if (buffer[1] === 0xBF) {
|
||||
assert.ok(
|
||||
buffer.equals(new Uint8Array(
|
||||
[ 0x7F, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x7F ])));
|
||||
} else {
|
||||
assert.ok(
|
||||
buffer.equals(new Uint8Array(
|
||||
[ 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x7F ])));
|
||||
}
|
||||
|
||||
assert.ok(Number.isNaN(buffer.readFloatBE(0)));
|
||||
assert.ok(Number.isNaN(buffer.readFloatLE(4)));
|
||||
|
||||
// OOB in writeFloat{LE,BE} should throw.
|
||||
{
|
||||
const small = Buffer.allocUnsafe(1);
|
||||
|
||||
['writeFloatLE', 'writeFloatBE'].forEach((fn) => {
|
||||
|
||||
// Verify that default offset works fine.
|
||||
buffer[fn](23, undefined);
|
||||
buffer[fn](23);
|
||||
|
||||
assert.throws(
|
||||
() => small[fn](11.11, 0),
|
||||
{
|
||||
code: 'ERR_BUFFER_OUT_OF_BOUNDS',
|
||||
name: 'RangeError',
|
||||
message: 'Attempt to access memory outside buffer bounds'
|
||||
});
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((off) => {
|
||||
assert.throws(
|
||||
() => small[fn](23, off),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' }
|
||||
);
|
||||
});
|
||||
|
||||
[Infinity, -1, 5].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](23, offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be >= 0 and <= 4. Received ${offset}`
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
[NaN, 1.01].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](42, offset),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be an integer. Received ${offset}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
268
test/js/node/test/parallel/test-buffer-writeint.js
Normal file
268
test/js/node/test/parallel/test-buffer-writeint.js
Normal file
@@ -0,0 +1,268 @@
|
||||
'use strict';
|
||||
|
||||
// Tests to verify signed integers are correctly written
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const errorOutOfBounds = {
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: new RegExp('^The value of "value" is out of range\\. ' +
|
||||
'It must be >= -\\d+ and <= \\d+\\. Received .+$')
|
||||
};
|
||||
|
||||
// Test 8 bit
|
||||
{
|
||||
const buffer = Buffer.alloc(2);
|
||||
|
||||
buffer.writeInt8(0x23, 0);
|
||||
buffer.writeInt8(-5, 1);
|
||||
assert.ok(buffer.equals(new Uint8Array([ 0x23, 0xfb ])));
|
||||
|
||||
/* Make sure we handle min/max correctly */
|
||||
buffer.writeInt8(0x7f, 0);
|
||||
buffer.writeInt8(-0x80, 1);
|
||||
assert.ok(buffer.equals(new Uint8Array([ 0x7f, 0x80 ])));
|
||||
|
||||
assert.throws(() => {
|
||||
buffer.writeInt8(0x7f + 1, 0);
|
||||
}, errorOutOfBounds);
|
||||
assert.throws(() => {
|
||||
buffer.writeInt8(-0x80 - 1, 0);
|
||||
}, errorOutOfBounds);
|
||||
|
||||
// Verify that default offset works fine.
|
||||
buffer.writeInt8(23, undefined);
|
||||
buffer.writeInt8(23);
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((off) => {
|
||||
assert.throws(
|
||||
() => buffer.writeInt8(23, off),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' });
|
||||
});
|
||||
|
||||
[NaN, Infinity, -1, 1.01].forEach((off) => {
|
||||
assert.throws(
|
||||
() => buffer.writeInt8(23, off),
|
||||
{ code: 'ERR_OUT_OF_RANGE' });
|
||||
});
|
||||
}
|
||||
|
||||
// Test 16 bit
|
||||
{
|
||||
const buffer = Buffer.alloc(4);
|
||||
|
||||
buffer.writeInt16BE(0x0023, 0);
|
||||
buffer.writeInt16LE(0x0023, 2);
|
||||
assert.ok(buffer.equals(new Uint8Array([ 0x00, 0x23, 0x23, 0x00 ])));
|
||||
|
||||
buffer.writeInt16BE(-5, 0);
|
||||
buffer.writeInt16LE(-5, 2);
|
||||
assert.ok(buffer.equals(new Uint8Array([ 0xff, 0xfb, 0xfb, 0xff ])));
|
||||
|
||||
buffer.writeInt16BE(-1679, 0);
|
||||
buffer.writeInt16LE(-1679, 2);
|
||||
assert.ok(buffer.equals(new Uint8Array([ 0xf9, 0x71, 0x71, 0xf9 ])));
|
||||
|
||||
/* Make sure we handle min/max correctly */
|
||||
buffer.writeInt16BE(0x7fff, 0);
|
||||
buffer.writeInt16BE(-0x8000, 2);
|
||||
assert.ok(buffer.equals(new Uint8Array([ 0x7f, 0xff, 0x80, 0x00 ])));
|
||||
|
||||
buffer.writeInt16LE(0x7fff, 0);
|
||||
buffer.writeInt16LE(-0x8000, 2);
|
||||
assert.ok(buffer.equals(new Uint8Array([ 0xff, 0x7f, 0x00, 0x80 ])));
|
||||
|
||||
['writeInt16BE', 'writeInt16LE'].forEach((fn) => {
|
||||
|
||||
// Verify that default offset works fine.
|
||||
buffer[fn](23, undefined);
|
||||
buffer[fn](23);
|
||||
|
||||
assert.throws(() => {
|
||||
buffer[fn](0x7fff + 1, 0);
|
||||
}, errorOutOfBounds);
|
||||
assert.throws(() => {
|
||||
buffer[fn](-0x8000 - 1, 0);
|
||||
}, errorOutOfBounds);
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((off) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](23, off),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' });
|
||||
});
|
||||
|
||||
[NaN, Infinity, -1, 1.01].forEach((off) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](23, off),
|
||||
{ code: 'ERR_OUT_OF_RANGE' });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Test 32 bit
|
||||
{
|
||||
const buffer = Buffer.alloc(8);
|
||||
|
||||
buffer.writeInt32BE(0x23, 0);
|
||||
buffer.writeInt32LE(0x23, 4);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0x00, 0x00, 0x00, 0x23, 0x23, 0x00, 0x00, 0x00,
|
||||
])));
|
||||
|
||||
buffer.writeInt32BE(-5, 0);
|
||||
buffer.writeInt32LE(-5, 4);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0xff, 0xff, 0xff, 0xfb, 0xfb, 0xff, 0xff, 0xff,
|
||||
])));
|
||||
|
||||
buffer.writeInt32BE(-805306713, 0);
|
||||
buffer.writeInt32LE(-805306713, 4);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0xcf, 0xff, 0xfe, 0xa7, 0xa7, 0xfe, 0xff, 0xcf,
|
||||
])));
|
||||
|
||||
/* Make sure we handle min/max correctly */
|
||||
buffer.writeInt32BE(0x7fffffff, 0);
|
||||
buffer.writeInt32BE(-0x80000000, 4);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0x7f, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00,
|
||||
])));
|
||||
|
||||
buffer.writeInt32LE(0x7fffffff, 0);
|
||||
buffer.writeInt32LE(-0x80000000, 4);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x80,
|
||||
])));
|
||||
|
||||
['writeInt32BE', 'writeInt32LE'].forEach((fn) => {
|
||||
|
||||
// Verify that default offset works fine.
|
||||
buffer[fn](23, undefined);
|
||||
buffer[fn](23);
|
||||
|
||||
assert.throws(() => {
|
||||
buffer[fn](0x7fffffff + 1, 0);
|
||||
}, errorOutOfBounds);
|
||||
assert.throws(() => {
|
||||
buffer[fn](-0x80000000 - 1, 0);
|
||||
}, errorOutOfBounds);
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((off) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](23, off),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' });
|
||||
});
|
||||
|
||||
[NaN, Infinity, -1, 1.01].forEach((off) => {
|
||||
assert.throws(
|
||||
() => buffer[fn](23, off),
|
||||
{ code: 'ERR_OUT_OF_RANGE' });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Test 48 bit
|
||||
{
|
||||
const value = 0x1234567890ab;
|
||||
const buffer = Buffer.allocUnsafe(6);
|
||||
buffer.writeIntBE(value, 0, 6);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0x12, 0x34, 0x56, 0x78, 0x90, 0xab,
|
||||
])));
|
||||
|
||||
buffer.writeIntLE(value, 0, 6);
|
||||
assert.ok(buffer.equals(new Uint8Array([
|
||||
0xab, 0x90, 0x78, 0x56, 0x34, 0x12,
|
||||
])));
|
||||
}
|
||||
|
||||
// Test Int
|
||||
{
|
||||
const data = Buffer.alloc(8);
|
||||
|
||||
// Check byteLength.
|
||||
['writeIntBE', 'writeIntLE'].forEach((fn) => {
|
||||
['', '0', null, {}, [], () => {}, true, false, undefined].forEach((bl) => {
|
||||
assert.throws(
|
||||
() => data[fn](23, 0, bl),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' });
|
||||
});
|
||||
|
||||
[Infinity, -1].forEach((byteLength) => {
|
||||
assert.throws(
|
||||
() => data[fn](23, 0, byteLength),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
message: 'The value of "byteLength" is out of range. ' +
|
||||
`It must be >= 1 and <= 6. Received ${byteLength}`
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
[NaN, 1.01].forEach((byteLength) => {
|
||||
assert.throws(
|
||||
() => data[fn](42, 0, byteLength),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "byteLength" is out of range. ' +
|
||||
`It must be an integer. Received ${byteLength}`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Test 1 to 6 bytes.
|
||||
for (let i = 1; i <= 6; i++) {
|
||||
['writeIntBE', 'writeIntLE'].forEach((fn) => {
|
||||
const min = -(2 ** (i * 8 - 1));
|
||||
const max = 2 ** (i * 8 - 1) - 1;
|
||||
let range = `>= ${min} and <= ${max}`;
|
||||
if (i > 4) {
|
||||
range = `>= -(2 ** ${i * 8 - 1}) and < 2 ** ${i * 8 - 1}`;
|
||||
}
|
||||
[min - 1, max + 1].forEach((val) => {
|
||||
const received = String(val);
|
||||
assert.throws(() => {
|
||||
data[fn](val, 0, i);
|
||||
}, {
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "value" is out of range. ' +
|
||||
`It must be ${range}. Received ${received}`
|
||||
});
|
||||
});
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false, undefined].forEach((o) => {
|
||||
assert.throws(
|
||||
() => data[fn](min, o, i),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError'
|
||||
});
|
||||
});
|
||||
|
||||
[Infinity, -1, -4294967295].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => data[fn](min, offset, i),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be >= 0 and <= ${8 - i}. Received ${offset}`
|
||||
});
|
||||
});
|
||||
|
||||
[NaN, 1.01].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => data[fn](max, offset, i),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be an integer. Received ${offset}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
234
test/js/node/test/parallel/test-buffer-writeuint.js
Normal file
234
test/js/node/test/parallel/test-buffer-writeuint.js
Normal file
@@ -0,0 +1,234 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const common = require('../common');
|
||||
|
||||
// We need to check the following things:
|
||||
// - We are correctly resolving big endian (doesn't mean anything for 8 bit)
|
||||
// - Correctly resolving little endian (doesn't mean anything for 8 bit)
|
||||
// - Correctly using the offsets
|
||||
// - Correctly interpreting values that are beyond the signed range as unsigned
|
||||
|
||||
{ // OOB
|
||||
const data = Buffer.alloc(8);
|
||||
['UInt8', 'UInt16BE', 'UInt16LE', 'UInt32BE', 'UInt32LE'].forEach((fn) => {
|
||||
|
||||
// Verify that default offset works fine.
|
||||
data[`write${fn}`](23, undefined);
|
||||
data[`write${fn}`](23);
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((o) => {
|
||||
assert.throws(
|
||||
() => data[`write${fn}`](23, o),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: `The "offset" argument must be of type number.${common.invalidArgTypeHelper(o)}`,
|
||||
});
|
||||
});
|
||||
|
||||
[NaN, Infinity, -1, 1.01].forEach((o) => {
|
||||
assert.throws(
|
||||
() => data[`write${fn}`](23, o),
|
||||
{ code: 'ERR_OUT_OF_RANGE' });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{ // Test 8 bit
|
||||
const data = Buffer.alloc(4);
|
||||
|
||||
data.writeUInt8(23, 0);
|
||||
data.writeUInt8(23, 1);
|
||||
data.writeUInt8(23, 2);
|
||||
data.writeUInt8(23, 3);
|
||||
assert.ok(data.equals(new Uint8Array([23, 23, 23, 23])));
|
||||
|
||||
data.writeUInt8(23, 0);
|
||||
data.writeUInt8(23, 1);
|
||||
data.writeUInt8(23, 2);
|
||||
data.writeUInt8(23, 3);
|
||||
assert.ok(data.equals(new Uint8Array([23, 23, 23, 23])));
|
||||
|
||||
data.writeUInt8(255, 0);
|
||||
assert.strictEqual(data[0], 255);
|
||||
|
||||
data.writeUInt8(255, 0);
|
||||
assert.strictEqual(data[0], 255);
|
||||
}
|
||||
|
||||
// Test 16 bit
|
||||
{
|
||||
let value = 0x2343;
|
||||
const data = Buffer.alloc(4);
|
||||
|
||||
data.writeUInt16BE(value, 0);
|
||||
assert.ok(data.equals(new Uint8Array([0x23, 0x43, 0, 0])));
|
||||
|
||||
data.writeUInt16BE(value, 1);
|
||||
assert.ok(data.equals(new Uint8Array([0x23, 0x23, 0x43, 0])));
|
||||
|
||||
data.writeUInt16BE(value, 2);
|
||||
assert.ok(data.equals(new Uint8Array([0x23, 0x23, 0x23, 0x43])));
|
||||
|
||||
data.writeUInt16LE(value, 0);
|
||||
assert.ok(data.equals(new Uint8Array([0x43, 0x23, 0x23, 0x43])));
|
||||
|
||||
data.writeUInt16LE(value, 1);
|
||||
assert.ok(data.equals(new Uint8Array([0x43, 0x43, 0x23, 0x43])));
|
||||
|
||||
data.writeUInt16LE(value, 2);
|
||||
assert.ok(data.equals(new Uint8Array([0x43, 0x43, 0x43, 0x23])));
|
||||
|
||||
value = 0xff80;
|
||||
data.writeUInt16LE(value, 0);
|
||||
assert.ok(data.equals(new Uint8Array([0x80, 0xff, 0x43, 0x23])));
|
||||
|
||||
data.writeUInt16BE(value, 0);
|
||||
assert.ok(data.equals(new Uint8Array([0xff, 0x80, 0x43, 0x23])));
|
||||
|
||||
value = 0xfffff;
|
||||
['writeUInt16BE', 'writeUInt16LE'].forEach((fn) => {
|
||||
assert.throws(
|
||||
() => data[fn](value, 0),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
message: 'The value of "value" is out of range. ' +
|
||||
`It must be >= 0 and <= 65535. Received ${value}`
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Test 32 bit
|
||||
{
|
||||
const data = Buffer.alloc(6);
|
||||
const value = 0xe7f90a6d;
|
||||
|
||||
data.writeUInt32BE(value, 0);
|
||||
assert.ok(data.equals(new Uint8Array([0xe7, 0xf9, 0x0a, 0x6d, 0, 0])));
|
||||
|
||||
data.writeUInt32BE(value, 1);
|
||||
assert.ok(data.equals(new Uint8Array([0xe7, 0xe7, 0xf9, 0x0a, 0x6d, 0])));
|
||||
|
||||
data.writeUInt32BE(value, 2);
|
||||
assert.ok(data.equals(new Uint8Array([0xe7, 0xe7, 0xe7, 0xf9, 0x0a, 0x6d])));
|
||||
|
||||
data.writeUInt32LE(value, 0);
|
||||
assert.ok(data.equals(new Uint8Array([0x6d, 0x0a, 0xf9, 0xe7, 0x0a, 0x6d])));
|
||||
|
||||
data.writeUInt32LE(value, 1);
|
||||
assert.ok(data.equals(new Uint8Array([0x6d, 0x6d, 0x0a, 0xf9, 0xe7, 0x6d])));
|
||||
|
||||
data.writeUInt32LE(value, 2);
|
||||
assert.ok(data.equals(new Uint8Array([0x6d, 0x6d, 0x6d, 0x0a, 0xf9, 0xe7])));
|
||||
}
|
||||
|
||||
// Test 48 bit
|
||||
{
|
||||
const value = 0x1234567890ab;
|
||||
const data = Buffer.allocUnsafe(6);
|
||||
data.writeUIntBE(value, 0, 6);
|
||||
assert.ok(data.equals(new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x90, 0xab])));
|
||||
|
||||
data.writeUIntLE(value, 0, 6);
|
||||
assert.ok(data.equals(new Uint8Array([0xab, 0x90, 0x78, 0x56, 0x34, 0x12])));
|
||||
}
|
||||
|
||||
// Test UInt
|
||||
{
|
||||
const data = Buffer.alloc(8);
|
||||
let val = 0x100;
|
||||
|
||||
// Check byteLength.
|
||||
['writeUIntBE', 'writeUIntLE'].forEach((fn) => {
|
||||
['', '0', null, {}, [], () => {}, true, false, undefined].forEach((bl) => {
|
||||
assert.throws(
|
||||
() => data[fn](23, 0, bl),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
});
|
||||
});
|
||||
|
||||
[Infinity, -1].forEach((byteLength) => {
|
||||
assert.throws(
|
||||
() => data[fn](23, 0, byteLength),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
message: 'The value of "byteLength" is out of range. ' +
|
||||
`It must be >= 1 and <= 6. Received ${byteLength}`
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
[NaN, 1.01].forEach((byteLength) => {
|
||||
assert.throws(
|
||||
() => data[fn](42, 0, byteLength),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "byteLength" is out of range. ' +
|
||||
`It must be an integer. Received ${byteLength}`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Test 1 to 6 bytes.
|
||||
for (let i = 1; i <= 6; i++) {
|
||||
const range = i < 5 ? `= ${val - 1}` : ` 2 ** ${i * 8}`;
|
||||
const received = String(val);
|
||||
['writeUIntBE', 'writeUIntLE'].forEach((fn) => {
|
||||
assert.throws(() => {
|
||||
data[fn](val, 0, i);
|
||||
}, {
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "value" is out of range. ' +
|
||||
`It must be >= 0 and <${range}. Received ${received}`
|
||||
});
|
||||
|
||||
['', '0', null, {}, [], () => {}, true, false].forEach((o) => {
|
||||
assert.throws(
|
||||
() => data[fn](23, o, i),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError'
|
||||
});
|
||||
});
|
||||
|
||||
[Infinity, -1, -4294967295].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => data[fn](val - 1, offset, i),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be >= 0 and <= ${8 - i}. Received ${offset}`
|
||||
});
|
||||
});
|
||||
|
||||
[NaN, 1.01].forEach((offset) => {
|
||||
assert.throws(
|
||||
() => data[fn](val - 1, offset, i),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "offset" is out of range. ' +
|
||||
`It must be an integer. Received ${offset}`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
val *= 0x100;
|
||||
}
|
||||
}
|
||||
|
||||
for (const fn of [
|
||||
'UInt8', 'UInt16LE', 'UInt16BE', 'UInt32LE', 'UInt32BE', 'UIntLE', 'UIntBE',
|
||||
'BigUInt64LE', 'BigUInt64BE',
|
||||
]) {
|
||||
const p = Buffer.prototype;
|
||||
const lowerFn = fn.replace(/UInt/, 'Uint');
|
||||
assert.strictEqual(p[`write${fn}`], p[`write${lowerFn}`]);
|
||||
assert.strictEqual(p[`read${fn}`], p[`read${lowerFn}`]);
|
||||
}
|
||||
32
test/js/node/test/parallel/test-buffer-zero-fill-cli.js
Normal file
32
test/js/node/test/parallel/test-buffer-zero-fill-cli.js
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
// Flags: --zero-fill-buffers
|
||||
|
||||
// when using --zero-fill-buffers, every Buffer and SlowBuffer
|
||||
// instance must be zero filled upon creation
|
||||
|
||||
require('../common');
|
||||
const SlowBuffer = require('buffer').SlowBuffer;
|
||||
const assert = require('assert');
|
||||
|
||||
function isZeroFilled(buf) {
|
||||
for (const n of buf)
|
||||
if (n > 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// This can be somewhat unreliable because the
|
||||
// allocated memory might just already happen to
|
||||
// contain all zeroes. The test is run multiple
|
||||
// times to improve the reliability.
|
||||
for (let i = 0; i < 50; i++) {
|
||||
const bufs = [
|
||||
Buffer.alloc(20),
|
||||
Buffer(20),
|
||||
Buffer.allocUnsafe(20),
|
||||
SlowBuffer(20),
|
||||
new SlowBuffer(20),
|
||||
];
|
||||
for (const buf of bufs) {
|
||||
assert(isZeroFilled(buf));
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ const createValidate = (line, args = []) => common.mustCall((e) => {
|
||||
const rest = msg.substring(firstColon + 1);
|
||||
assert.strictEqual(path.basename(fileName), 'test-common-must-not-call.js');
|
||||
const argsInfo = args.length > 0 ?
|
||||
`\ncalled with arguments: ${args.map(util.inspect).join(', ')}` : '';
|
||||
`\ncalled with arguments: ${args.map(v => Bun.inspect(v)).join(', ')}` : '';
|
||||
assert.strictEqual(rest, line + argsInfo);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user