[njs] QuickJS: added buffer module.
noreply at nginx.com
noreply at nginx.com
Fri Aug 16 01:36:02 UTC 2024
details: https://github.com/nginx/njs/commit/d1c615eaa208a4e7c92b661f8f7674e92f19aedf
branches: master
commit: d1c615eaa208a4e7c92b661f8f7674e92f19aedf
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Wed, 7 Aug 2024 23:11:24 -0700
description:
QuickJS: added buffer module.
---
src/qjs.h | 2 +
src/qjs_buffer.c | 1845 ++++++++++++++++++++++++++++++++++++++++-----
src/test/njs_unit_test.c | 817 --------------------
test/buffer.t.js | 815 +++++++++++++++++++-
test/harness/runTsuite.js | 3 +
5 files changed, 2465 insertions(+), 1017 deletions(-)
diff --git a/src/qjs.h b/src/qjs.h
index 71e23d78..00e9296a 100644
--- a/src/qjs.h
+++ b/src/qjs.h
@@ -16,6 +16,7 @@
#include <njs_unicode.h>
#include <njs_utf8.h>
#include <njs_chb.h>
+#include <njs_utils.h>
#if defined(__GNUC__) && (__GNUC__ >= 8)
#pragma GCC diagnostic push
@@ -43,6 +44,7 @@ JSContext *qjs_new_context(JSRuntime *rt, _Bool eval);
JSValue qjs_buffer_alloc(JSContext *ctx, size_t size);
+JSValue qjs_buffer_create(JSContext *ctx, u_char *start, size_t size);
JSValue qjs_buffer_chb_alloc(JSContext *ctx, njs_chb_t *chain);
typedef int (*qjs_buffer_encode_t)(JSContext *ctx, const njs_str_t *src,
diff --git a/src/qjs_buffer.c b/src/qjs_buffer.c
index 166eb970..83764e02 100644
--- a/src/qjs_buffer.c
+++ b/src/qjs_buffer.c
@@ -6,23 +6,75 @@
#include <qjs.h>
+#define INT24_MAX 0x7FFFFF
+#define INT24_MIN (-0x800000)
+#define INT40_MAX 0x7FFFFFFFFFLL
+#define INT40_MIN (-0x8000000000LL)
+#define INT48_MAX 0x7FFFFFFFFFFFLL
+#define INT48_MIN (-0x800000000000LL)
+#define UINT24_MAX 0xFFFFFFLL
+#define UINT40_MAX 0xFFFFFFFFFFLL
+#define UINT48_MAX 0xFFFFFFFFFFFFLL
+
+#define qjs_buffer_magic(size, sign, little) \
+ ((size << 2) | (sign << 1) | little)
+
static JSValue qjs_buffer(JSContext *ctx, JSValueConst this_val, int argc,
JSValueConst *argv);
+static JSValue qjs_buffer_ctor(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv);
+static JSValue qjs_bufferobj_alloc(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int ignored);
+static JSValue qjs_buffer_byte_length(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv);
+static JSValue qjs_buffer_compare(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv);
+static JSValue qjs_buffer_concat(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv);
+static JSValue qjs_buffer_fill(JSContext *ctx, JSValueConst buffer,
+ JSValueConst fill, JSValueConst encode, uint64_t offset, uint64_t end);
static JSValue qjs_buffer_from(JSContext *ctx, JSValueConst this_val, int argc,
JSValueConst *argv);
static JSValue qjs_buffer_is_buffer(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv);
+static JSValue qjs_buffer_is_encoding(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv);
+static JSValue qjs_buffer_prototype_compare(JSContext *ctx,
+ JSValueConst this_val, int argc, JSValueConst *argv);
+static JSValue qjs_buffer_prototype_copy(JSContext *ctx,
+ JSValueConst this_val, int argc, JSValueConst *argv);
+static JSValue qjs_buffer_prototype_equals(JSContext *ctx,
+ JSValueConst this_val, int argc, JSValueConst *argv);
+static JSValue qjs_buffer_prototype_fill(JSContext *ctx,
+ JSValueConst this_val, int argc, JSValueConst *argv);
+static JSValue qjs_buffer_prototype_includes(JSContext *ctx,
+ JSValueConst this_val, int argc, JSValueConst *argv);
+static JSValue qjs_buffer_prototype_index_of(JSContext *ctx,
+ JSValueConst this_val, int argc, JSValueConst *argv, int last);
+static JSValue qjs_buffer_prototype_read_float(JSContext *ctx,
+ JSValueConst this_val, int argc, JSValueConst *argv, int magic);
+static JSValue qjs_buffer_prototype_read_int(JSContext *ctx,
+ JSValueConst this_val, int argc, JSValueConst *argv, int magic);
+static JSValue qjs_buffer_prototype_swap(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int size);
static JSValue qjs_buffer_prototype_to_json(JSContext *ctx,
JSValueConst this_val, int argc, JSValueConst *argv);
static JSValue qjs_buffer_prototype_to_string(JSContext *ctx,
JSValueConst this_val, int argc, JSValueConst *argv);
+static JSValue qjs_buffer_prototype_write(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv);
+static JSValue qjs_buffer_prototype_write_int(JSContext *ctx,
+ JSValueConst this_val, int argc, JSValueConst *argv, int magic);
+static JSValue qjs_buffer_prototype_write_float(JSContext *ctx,
+ JSValueConst this_val, int argc, JSValueConst *argv, int magic);
static JSValue qjs_buffer_from_string(JSContext *ctx, JSValueConst str,
JSValueConst encoding);
static JSValue qjs_buffer_from_typed_array(JSContext *ctx, JSValueConst obj,
size_t offset, size_t size, size_t bytes, int float32);
-static JSValue qjs_buffer_from_array_buffer(JSContext *ctx, u_char *buf,
- size_t size, JSValueConst offset, JSValueConst length);
static JSValue qjs_buffer_from_object(JSContext *ctx, JSValueConst obj);
+static JSValue qjs_buffer_compare_array(JSContext *ctx, JSValue val1,
+ JSValue val2, JSValueConst target_start, JSValueConst target_end,
+ JSValueConst source_start, JSValueConst source_end);
static int qjs_base64_encode(JSContext *ctx, const njs_str_t *src,
njs_str_t *dst);
static size_t qjs_base64_encode_length(JSContext *ctx, const njs_str_t *src);
@@ -38,7 +90,8 @@ static int qjs_hex_encode(JSContext *ctx, const njs_str_t *src, njs_str_t *dst);
static size_t qjs_hex_encode_length(JSContext *ctx, const njs_str_t *src);
static int qjs_hex_decode(JSContext *ctx, const njs_str_t *src, njs_str_t *dst);
static size_t qjs_hex_decode_length(JSContext *ctx, const njs_str_t *src);
-static JSValue qjs_new_uint8_array(JSContext *ctx, size_t size);
+static JSValue qjs_new_uint8_array(JSContext *ctx, int argc,
+ JSValueConst *argv);
static JSModuleDef *qjs_buffer_init(JSContext *ctx, const char *name);
@@ -103,14 +156,103 @@ static const JSCFunctionListEntry qjs_buffer_export[] = {
static const JSCFunctionListEntry qjs_buffer_props[] = {
+ JS_CFUNC_MAGIC_DEF("alloc", 3, qjs_bufferobj_alloc, 0),
+ JS_CFUNC_MAGIC_DEF("allocUnsafe", 3, qjs_bufferobj_alloc, 1),
+ JS_CFUNC_DEF("byteLength", 2, qjs_buffer_byte_length),
+ JS_CFUNC_DEF("compare", 6, qjs_buffer_compare),
+ JS_CFUNC_DEF("concat", 1, qjs_buffer_concat),
JS_CFUNC_DEF("from", 3, qjs_buffer_from),
JS_CFUNC_DEF("isBuffer", 1, qjs_buffer_is_buffer),
+ JS_CFUNC_DEF("isEncoding", 1, qjs_buffer_is_encoding),
};
static const JSCFunctionListEntry qjs_buffer_proto[] = {
+ JS_CFUNC_DEF("compare", 5, qjs_buffer_prototype_compare),
+ JS_CFUNC_DEF("copy", 5, qjs_buffer_prototype_copy),
+ JS_CFUNC_DEF("equals", 1, qjs_buffer_prototype_equals),
+ JS_CFUNC_DEF("fill", 4, qjs_buffer_prototype_fill),
+ JS_CFUNC_DEF("includes", 3, qjs_buffer_prototype_includes),
+ JS_CFUNC_MAGIC_DEF("indexOf", 3, qjs_buffer_prototype_index_of, 0),
+ JS_CFUNC_MAGIC_DEF("lastIndexOf", 3, qjs_buffer_prototype_index_of, 1),
+ JS_CFUNC_MAGIC_DEF("readFloatLE", 1, qjs_buffer_prototype_read_float,
+ qjs_buffer_magic(4, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("readFloatBE", 1, qjs_buffer_prototype_read_float,
+ qjs_buffer_magic(4, 1, 0)),
+ JS_CFUNC_MAGIC_DEF("readDoubleLE", 1, qjs_buffer_prototype_read_float,
+ qjs_buffer_magic(8, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("readDoubleBE", 1, qjs_buffer_prototype_read_float,
+ qjs_buffer_magic(8, 1, 0)),
+ JS_CFUNC_MAGIC_DEF("readInt8", 1, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(1, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("readUInt8", 1, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(1, 0, 1)),
+ JS_CFUNC_MAGIC_DEF("readInt16LE", 1, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(2, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("readUInt16LE", 1, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(2, 0, 1)),
+ JS_CFUNC_MAGIC_DEF("readInt16BE", 1, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(2, 1, 0)),
+ JS_CFUNC_MAGIC_DEF("readUInt16BE", 1, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(2, 0, 0)),
+ JS_CFUNC_MAGIC_DEF("readInt32LE", 1, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(4, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("readUInt32LE", 1, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(4, 0, 1)),
+ JS_CFUNC_MAGIC_DEF("readInt32BE", 1, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(4, 1, 0)),
+ JS_CFUNC_MAGIC_DEF("readUInt32BE", 1, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(4, 0, 0)),
+ JS_CFUNC_MAGIC_DEF("readIntLE", 2, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(0, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("readUIntLE", 2, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(0, 0, 1)),
+ JS_CFUNC_MAGIC_DEF("readIntBE", 2, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(0, 1, 0)),
+ JS_CFUNC_MAGIC_DEF("readUIntBE", 2, qjs_buffer_prototype_read_int,
+ qjs_buffer_magic(0, 0, 0)),
+ JS_CFUNC_MAGIC_DEF("swap16", 0, qjs_buffer_prototype_swap, 2),
+ JS_CFUNC_MAGIC_DEF("swap32", 0, qjs_buffer_prototype_swap, 4),
+ JS_CFUNC_MAGIC_DEF("swap64", 0, qjs_buffer_prototype_swap, 8),
JS_CFUNC_DEF("toJSON", 0, qjs_buffer_prototype_to_json),
JS_CFUNC_DEF("toString", 1, qjs_buffer_prototype_to_string),
+ JS_CFUNC_DEF("write", 4, qjs_buffer_prototype_write),
+ JS_CFUNC_MAGIC_DEF("writeInt8", 1, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(1, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("writeUInt8", 1, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(1, 0, 1)),
+ JS_CFUNC_MAGIC_DEF("writeInt16LE", 1, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(2, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("writeUInt16LE", 1, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(2, 0, 1)),
+ JS_CFUNC_MAGIC_DEF("writeInt16BE", 1, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(2, 1, 0)),
+ JS_CFUNC_MAGIC_DEF("writeUInt16BE", 1, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(2, 0, 0)),
+ JS_CFUNC_MAGIC_DEF("writeInt32LE", 1, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(4, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("writeUInt32LE", 1, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(4, 0, 1)),
+ JS_CFUNC_MAGIC_DEF("writeInt32BE", 1, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(4, 1, 0)),
+ JS_CFUNC_MAGIC_DEF("writeUInt32BE", 1, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(4, 0, 0)),
+ JS_CFUNC_MAGIC_DEF("writeIntLE", 2, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(0, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("writeUIntLE", 2, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(0, 0, 1)),
+ JS_CFUNC_MAGIC_DEF("writeIntBE", 2, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(0, 1, 0)),
+ JS_CFUNC_MAGIC_DEF("writeUIntBE", 2, qjs_buffer_prototype_write_int,
+ qjs_buffer_magic(0, 0, 0)),
+ JS_CFUNC_MAGIC_DEF("writeFloatLE", 2, qjs_buffer_prototype_write_float,
+ qjs_buffer_magic(4, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("writeFloatBE", 2, qjs_buffer_prototype_write_float,
+ qjs_buffer_magic(4, 1, 0)),
+ JS_CFUNC_MAGIC_DEF("writeDoubleLE", 2, qjs_buffer_prototype_write_float,
+ qjs_buffer_magic(8, 1, 1)),
+ JS_CFUNC_MAGIC_DEF("writeDoubleBE", 2, qjs_buffer_prototype_write_float,
+ qjs_buffer_magic(8, 1, 0)),
};
@@ -201,6 +343,288 @@ qjs_buffer(JSContext *ctx, JSValueConst this_val, int argc,
}
+static JSValue
+qjs_buffer_ctor(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv)
+{
+ JSValue ret, proto;
+
+ ret = qjs_new_uint8_array(ctx, argc, argv);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ proto = JS_GetClassProto(ctx, qjs_buffer_class_id);
+ JS_SetPrototype(ctx, ret, proto);
+ JS_FreeValue(ctx, proto);
+
+ return ret;
+}
+
+
+static JSValue
+qjs_bufferobj_alloc(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv, int ignored)
+{
+ JSValue buffer, ret;
+ uint32_t size;
+
+ if (!JS_IsNumber(argv[0])) {
+ return JS_ThrowTypeError(ctx, "The \"size\" argument must be of type"
+ " number");
+ }
+
+ if (JS_ToUint32(ctx, &size, argv[0])) {
+ return JS_EXCEPTION;
+ }
+
+ buffer = qjs_buffer_alloc(ctx, size);
+ if (JS_IsException(buffer)) {
+ return buffer;
+ }
+
+ if (!JS_IsUndefined(argv[1])) {
+ ret = qjs_buffer_fill(ctx, buffer, argv[1], argv[2], 0, size);
+ if (JS_IsException(ret)) {
+ JS_FreeValue(ctx, buffer);
+ return ret;
+ }
+ }
+
+ return buffer;
+}
+
+
+static JSValue
+qjs_buffer_byte_length(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv)
+{
+ size_t size;
+ JSValue ret;
+ njs_str_t src;
+ const qjs_buffer_encoding_t *encoding;
+
+ if (JS_GetArrayBuffer(ctx, &size, argv[0]) != NULL) {
+ return JS_NewInt32(ctx, size);
+ }
+
+ ret = JS_GetTypedArrayBuffer(ctx, argv[0], NULL, &size, NULL);
+ if (!JS_IsException(ret)) {
+ JS_FreeValue(ctx, ret);
+ return JS_NewInt32(ctx, size);
+ }
+
+ if (!JS_IsString(argv[0])) {
+ return JS_ThrowTypeError(ctx, "first argument is not a string "
+ "or Buffer-like object");
+ }
+
+ encoding = qjs_buffer_encoding(ctx, argv[1], 1);
+ if (encoding == NULL) {
+ return JS_EXCEPTION;
+ }
+
+ src.start = (u_char *) JS_ToCStringLen(ctx, &src.length, argv[0]);
+
+ if (encoding->decode_length != NULL) {
+ size = encoding->decode_length(ctx, &src);
+
+ } else {
+ size = src.length;
+ }
+
+ JS_FreeCString(ctx, (char *) src.start);
+
+ return JS_NewInt32(ctx, size);
+}
+
+
+static JSValue
+qjs_buffer_compare(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv)
+{
+ return qjs_buffer_compare_array(ctx, argv[0], argv[1], argv[2], argv[3],
+ argv[4], argv[5]);
+}
+
+
+static JSValue
+qjs_buffer_concat(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv)
+{
+ u_char *p;
+ size_t n;
+ JSValue list, length, val, ret, buffer;
+ uint32_t i, len, list_len;
+ njs_str_t buf, dst;
+
+ list = argv[0];
+
+ if (!JS_IsArray(ctx, list)) {
+ return JS_ThrowTypeError(ctx,
+ "\"list\" argument must be an instance of Array");
+ }
+
+ length = JS_GetPropertyStr(ctx, list, "length");
+ if (JS_IsException(length)) {
+ return JS_EXCEPTION;
+ }
+
+ len = 0;
+ if (JS_ToUint32(ctx, &list_len, length)) {
+ JS_FreeValue(ctx, length);
+ return JS_EXCEPTION;
+ }
+
+ JS_FreeValue(ctx, length);
+
+ if (JS_IsUndefined(argv[1])) {
+ for (i = 0; i < list_len; i++) {
+ val = JS_GetPropertyUint32(ctx, list, i);
+ if (JS_IsException(val)) {
+ return JS_EXCEPTION;
+ }
+
+ ret = qjs_typed_array_data(ctx, val, &buf);
+ JS_FreeValue(ctx, val);
+ if (JS_IsException(ret)) {
+ return JS_ThrowTypeError(ctx, "\"list[%d]\" argument must be an"
+ " instance of Buffer or Uint8Array", i);
+ }
+
+ if ((SIZE_MAX - len) < buf.length) {
+ return JS_ThrowTypeError(ctx,
+ "Total size of buffers is too large");
+ }
+
+ len += buf.length;
+ }
+
+ } else {
+ if (JS_ToUint32(ctx, &len, argv[1])) {
+ return JS_EXCEPTION;
+ }
+ }
+
+ buffer = qjs_buffer_alloc(ctx, len);
+ if (JS_IsException(buffer)) {
+ return JS_EXCEPTION;
+ }
+
+ ret = qjs_typed_array_data(ctx, buffer, &dst);
+ if (JS_IsException(ret)) {
+ JS_FreeValue(ctx, buffer);
+ return JS_EXCEPTION;
+ }
+
+ p = dst.start;
+
+ for (i = 0; len != 0 && i < list_len; i++) {
+ val = JS_GetPropertyUint32(ctx, list, i);
+ if (JS_IsException(val)) {
+ JS_FreeValue(ctx, buffer);
+ return JS_EXCEPTION;
+ }
+
+ ret = qjs_typed_array_data(ctx, val, &buf);
+ if (JS_IsException(ret)) {
+ JS_FreeValue(ctx, buffer);
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
+
+ JS_FreeValue(ctx, val);
+
+ n = njs_min((size_t) len, buf.length);
+ p = njs_cpymem(p, buf.start, n);
+
+ len -= n;
+ }
+
+ if (len != 0) {
+ njs_memzero(p, len);
+ }
+
+ return buffer;
+}
+
+
+static JSValue
+qjs_buffer_fill(JSContext *ctx, JSValueConst buffer, JSValueConst fill,
+ JSValueConst encode, uint64_t offset, uint64_t end)
+{
+ JSValue ret, fill_buf;
+ uint32_t n;
+ njs_str_t dst, src;
+
+ ret = qjs_typed_array_data(ctx, buffer, &dst);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ if (end > dst.length) {
+ return JS_ThrowRangeError(ctx, "\"end\" is out of range");
+ }
+
+ if (offset >= end) {
+ return buffer;
+ }
+
+ if (JS_IsNumber(fill)) {
+ if (JS_ToUint32(ctx, &n, fill)) {
+ return JS_EXCEPTION;
+ }
+
+ memset(dst.start + offset, n & 0xff, end - offset);
+ return buffer;
+ }
+
+ fill_buf = JS_UNDEFINED;
+
+ if (JS_IsString(fill)) {
+ fill_buf = qjs_buffer_from_string(ctx, fill, encode);
+ if (JS_IsException(fill_buf)) {
+ return fill_buf;
+ }
+
+ fill = fill_buf;
+ }
+
+ ret = qjs_typed_array_data(ctx, fill, &src);
+ if (JS_IsException(ret)) {
+ JS_FreeValue(ctx, fill_buf);
+ return ret;
+ }
+
+ if (src.length == 0) {
+ memset(dst.start + offset, 0, end - offset);
+ JS_FreeValue(ctx, fill_buf);
+ return buffer;
+ }
+
+ if (src.start >= (dst.start + dst.length)
+ || dst.start >= (dst.start + dst.length))
+ {
+ while (offset < end) {
+ n = njs_min(src.length, end - offset);
+ memcpy(dst.start + offset, src.start, n);
+ offset += n;
+ }
+
+ } else {
+ while (offset < end) {
+ n = njs_min(src.length, end - offset);
+ memmove(dst.start + offset, src.start, n);
+ offset += n;
+ }
+ }
+
+ JS_FreeValue(ctx, fill_buf);
+
+ return buffer;
+}
+
+
static JSValue
qjs_buffer_from(JSContext *ctx, JSValueConst this_val, int argc,
JSValueConst *argv)
@@ -230,188 +654,1223 @@ qjs_buffer_from(JSContext *ctx, JSValueConst this_val, int argc,
return ctor;
}
- name = JS_GetPropertyStr(ctx, ctor, "name");
- if (JS_IsException(name)) {
- JS_FreeValue(ctx, ret);
- return name;
- }
+ name = JS_GetPropertyStr(ctx, ctor, "name");
+ if (JS_IsException(name)) {
+ JS_FreeValue(ctx, ret);
+ return name;
+ }
+
+ JS_FreeValue(ctx, ctor);
+ str = JS_ToCString(ctx, name);
+
+ if (strncmp(str, "Float32Array", 12) == 0) {
+ float32 = 1;
+ }
+
+ JS_FreeCString(ctx, str);
+ JS_FreeValue(ctx, name);
+ }
+
+ return qjs_buffer_from_typed_array(ctx, ret, off, size, bytes, float32);
+
+ } else if ((buf = JS_GetArrayBuffer(ctx, &size, argv[0])) != NULL) {
+ return qjs_buffer_ctor(ctx, JS_UNDEFINED, argc, argv);
+
+ } else if (JS_IsObject(argv[0])) {
+ obj = argv[0];
+ valueOf = JS_GetPropertyStr(ctx, obj, "valueOf");
+ if (JS_IsException(valueOf)) {
+ return valueOf;
+ }
+
+ if (JS_IsFunction(ctx, valueOf)) {
+ ret = JS_Call(ctx, valueOf, obj, 0, NULL);
+ JS_FreeValue(ctx, valueOf);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ if (JS_IsString(ret)) {
+ obj = ret;
+ ret = qjs_buffer_from_string(ctx, obj, argv[1]);
+ JS_FreeValue(ctx, obj);
+ return ret;
+ }
+
+ if (JS_IsObject(ret)
+ && JS_VALUE_GET_PTR(ret) != JS_VALUE_GET_PTR(obj))
+ {
+ obj = ret;
+ ret = qjs_buffer_from_object(ctx, obj);
+ JS_FreeValue(ctx, obj);
+ return ret;
+ }
+
+ JS_FreeValue(ctx, ret);
+ }
+
+ return qjs_buffer_from_object(ctx, obj);
+ }
+
+ JS_ThrowTypeError(ctx, "first argument is not a string "
+ "or Buffer-like object");
+ return JS_EXCEPTION;
+}
+
+
+static JSValue
+qjs_buffer_is_buffer(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue proto, buffer_proto, ret;
+
+ proto = JS_GetPrototype(ctx, argv[0]);
+ buffer_proto = JS_GetClassProto(ctx, qjs_buffer_class_id);
+
+ ret = JS_NewBool(ctx, JS_VALUE_GET_TAG(argv[0]) == JS_TAG_OBJECT &&
+ JS_VALUE_GET_OBJ(buffer_proto) == JS_VALUE_GET_OBJ(proto));
+
+ JS_FreeValue(ctx, buffer_proto);
+ JS_FreeValue(ctx, proto);
+
+ return ret;
+}
+
+
+static JSValue
+qjs_buffer_is_encoding(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ return JS_NewBool(ctx, qjs_buffer_encoding(ctx, argv[0], 0) != NULL);
+}
+
+
+static JSValue
+qjs_buffer_array_range(JSContext *ctx, njs_str_t *array, JSValueConst start,
+ JSValueConst end, const char *name)
+{
+ int64_t num_start, num_end;
+
+ num_start = 0;
+
+ if (!JS_IsUndefined(start)) {
+ if (JS_ToInt64(ctx, &num_start, start)) {
+ return JS_EXCEPTION;
+ }
+ }
+
+ if (num_start < 0 || (size_t) num_start > array->length) {
+ return JS_ThrowRangeError(ctx, "\"%sStart\" is out of range: %ld",
+ name, num_start);
+ }
+
+ num_end = array->length;
+
+ if (!JS_IsUndefined(end)) {
+ if (JS_ToInt64(ctx, &num_end, end)) {
+ return JS_EXCEPTION;
+ }
+ }
+
+ if (num_end < 0 || (size_t) num_end > array->length) {
+ return JS_ThrowRangeError(ctx, "\"%sEnd\" is out of range: %ld",
+ name, num_end);
+ }
+
+ if (num_start > num_end) {
+ num_end = num_start;
+ }
+
+ array->start += num_start;
+ array->length = num_end - num_start;
+
+ return JS_UNDEFINED;
+}
+
+
+static JSValue
+qjs_buffer_compare_array(JSContext *ctx, JSValue val1, JSValue val2,
+ JSValueConst target_start, JSValueConst target_end,
+ JSValueConst source_start, JSValueConst source_end)
+{
+ int rc;
+ size_t size;
+ JSValue ret;
+ njs_str_t src, target;
+
+ ret = qjs_typed_array_data(ctx, val1, &src);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ ret = qjs_typed_array_data(ctx, val2, &target);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ ret = qjs_buffer_array_range(ctx, &src, source_start, source_end, "source");
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ ret = qjs_buffer_array_range(ctx, &target, target_start, target_end,
+ "target");
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ size = njs_min(src.length, target.length);
+
+ rc = memcmp(src.start, target.start, size);
+
+ if (rc != 0) {
+ return JS_NewInt32(ctx, (rc < 0) ? -1 : 1);
+ }
+
+ if (target.length > src.length) {
+ rc = -1;
+
+ } else if (target.length < src.length) {
+ rc = 1;
+ }
+
+ return JS_NewInt32(ctx, rc);
+}
+
+
+static JSValue
+qjs_buffer_prototype_compare(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv)
+{
+ return qjs_buffer_compare_array(ctx, this_val, argv[0], argv[1], argv[2],
+ argv[3], argv[4]);
+}
+
+
+static JSValue
+qjs_buffer_prototype_copy(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv)
+{
+ size_t size;
+ JSValue ret;
+ njs_str_t src, target;
+
+ ret = qjs_typed_array_data(ctx, this_val, &src);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ ret = qjs_typed_array_data(ctx, argv[0], &target);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ ret = qjs_buffer_array_range(ctx, &target, argv[1], JS_UNDEFINED, "target");
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ ret = qjs_buffer_array_range(ctx, &src, argv[2], argv[3], "source");
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ size = njs_min(src.length, target.length);
+
+ if (src.start >= (target.start + size)
+ || target.start >= (src.start + size))
+ {
+ memcpy(target.start, src.start, size);
+
+ } else {
+ memmove(target.start, src.start, size);
+ }
+
+ return JS_NewInt32(ctx, size);
+}
+
+
+static JSValue
+qjs_buffer_prototype_equals(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv)
+{
+ JSValue ret;
+
+ ret = qjs_buffer_compare_array(ctx, this_val, argv[0], JS_UNDEFINED,
+ JS_UNDEFINED, JS_UNDEFINED, JS_UNDEFINED);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ return JS_NewBool(ctx, JS_VALUE_GET_INT(ret) == 0);
+}
+
+
+static JSValue
+qjs_buffer_prototype_fill(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv)
+{
+ JSValue ret, encode;
+ uint64_t offset, end;
+ njs_str_t dst;
+
+ offset = 0;
+ encode = argv[3];
+
+ ret = qjs_typed_array_data(ctx, this_val, &dst);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ end = dst.length;
+
+ if (!JS_IsUndefined(argv[1])) {
+ if (JS_IsString(argv[0]) && JS_IsString(argv[1])) {
+ encode = argv[1];
+ goto fill;
+ }
+
+ if (JS_ToIndex(ctx, &offset, argv[1])) {
+ return JS_EXCEPTION;
+ }
+ }
+
+ if (!JS_IsUndefined(argv[2])) {
+ if (JS_IsString(argv[0]) && JS_IsString(argv[2])) {
+ encode = argv[2];
+ goto fill;
+ }
+
+ if (JS_ToIndex(ctx, &end, argv[2])) {
+ return JS_EXCEPTION;
+ }
+ }
+
+fill:
+
+ ret = qjs_buffer_fill(ctx, this_val, argv[0], encode, offset, end);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ JS_DupValue(ctx, ret);
+
+ return ret;
+}
+
+
+static JSValue
+qjs_buffer_prototype_includes(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv)
+{
+ JSValue ret;
+
+ ret = qjs_buffer_prototype_index_of(ctx, this_val, argc, argv, 0);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ return JS_NewBool(ctx, JS_VALUE_GET_INT(ret) != -1);
+}
+
+
+static JSValue
+qjs_buffer_prototype_index_of(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv, int last)
+{
+ JSValue ret, buffer, encode, value;
+ int64_t from, to, increment, length, i;
+ uint32_t byte;
+ njs_str_t self, str;
+ const qjs_buffer_encoding_t *encoding;
+
+ ret = qjs_typed_array_data(ctx, this_val, &self);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ length = self.length;
+
+ if (length == 0) {
+ return JS_NewInt32(ctx, -1);
+ }
+
+ if (last) {
+ from = length - 1;
+ to = -1;
+ increment = -1;
+
+ } else {
+ from = 0;
+ to = length;
+ increment = 1;
+ }
+
+ encode = argv[2];
+
+ if (!JS_IsUndefined(argv[1])) {
+ if (JS_IsString(argv[0]) && JS_IsString(argv[1])) {
+ encode = argv[1];
+ goto encoding;
+ }
+
+ if (JS_ToInt64(ctx, &from, argv[1])) {
+ return JS_EXCEPTION;
+ }
+
+ if (last) {
+ if (from >= 0) {
+ from = njs_min(from, length - 1);
+
+ } else if (from < 0) {
+ from += length;
+ }
+
+ if (from <= to) {
+ return JS_NewInt32(ctx, -1);
+ }
+
+ } else {
+ if (from < 0) {
+ from += length;
+
+ if (from < 0) {
+ from = 0;
+ }
+ }
+
+ if (from >= to) {
+ return JS_NewInt32(ctx, -1);
+ }
+ }
+ }
+
+ if (JS_IsNumber(argv[0])) {
+ if (JS_ToUint32(ctx, &byte, argv[0])) {
+ return JS_EXCEPTION;
+ }
+
+ for (i = from; i != to; i += increment) {
+ if (self.start[i] == (uint8_t) byte) {
+ return JS_NewInt32(ctx, i);
+ }
+ }
+
+ return JS_NewInt32(ctx, -1);
+ }
+
+encoding:
+
+ buffer = JS_UNDEFINED;
+ value = argv[0];
+
+ if (JS_IsString(value)) {
+ encoding = qjs_buffer_encoding(ctx, encode, 1);
+ if (encoding == NULL) {
+ return JS_EXCEPTION;
+ }
+
+ buffer = qjs_buffer_from_string(ctx, value, encode);
+ if (JS_IsException(buffer)) {
+ return buffer;
+ }
+
+ value = buffer;
+ }
+
+ ret = qjs_typed_array_data(ctx, value, &str);
+ if (JS_IsException(ret)) {
+ JS_FreeValue(ctx, buffer);
+ return JS_ThrowTypeError(ctx, "\"value\" argument is not a string "
+ "or Buffer-like object");
+ }
+
+ if (str.length == 0) {
+ JS_FreeValue(ctx, buffer);
+ return JS_NewInt32(ctx, (last) ? length : 0);
+ }
+
+ if (str.length > (size_t) length) {
+ JS_FreeValue(ctx, buffer);
+ return JS_NewInt32(ctx, -1);
+ }
+
+ if (last) {
+ from -= str.length - 1;
+ from = njs_max(from, 0);
+
+ } else {
+ to -= str.length - 1;
+ to = njs_min(to, length);
+ }
+
+ for (i = from; i != to; i += increment) {
+ if (memcmp(&self.start[i], str.start, str.length) == 0) {
+ JS_FreeValue(ctx, buffer);
+ return JS_NewInt32(ctx, i);
+ }
+ }
+
+ JS_FreeValue(ctx, buffer);
+ return JS_NewInt32(ctx, -1);
+}
+
+
+static JSValue
+qjs_buffer_prototype_read_float(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic)
+{
+ double v;
+ JSValue ret;
+ uint32_t u32;
+ uint64_t u64, index, size;
+ njs_str_t self;
+ njs_bool_t little, swap;
+ njs_conv_f32_t conv_f32;
+ njs_conv_f64_t conv_f64;
+
+ ret = qjs_typed_array_data(ctx, this_val, &self);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ if (JS_ToIndex(ctx, &index, argv[0])) {
+ return JS_EXCEPTION;
+ }
+
+ size = magic >> 2;
+
+ if (size + index > self.length) {
+ return JS_ThrowRangeError(ctx, "index %lu is outside the bound of the"
+ " buffer", index);
+ }
+
+ little = magic & 1;
+ swap = little;
+
+#if NJS_HAVE_LITTLE_ENDIAN
+ swap = !swap;
+#endif
+
+ switch (size) {
+ case 4:
+ u32 = *((uint32_t *) &self.start[index]);
+
+ if (swap) {
+ u32 = njs_bswap_u32(u32);
+ }
+
+ conv_f32.u = u32;
+ v = conv_f32.f;
+ break;
+
+ case 8:
+ default:
+ u64 = *((uint64_t *) &self.start[index]);
+
+ if (swap) {
+ u64 = njs_bswap_u64(u64);
+ }
+
+ conv_f64.u = u64;
+ v = conv_f64.f;
+ break;
+ }
+
+ return JS_NewFloat64(ctx, v);
+}
+
+
+static JSValue
+qjs_buffer_prototype_read_int(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic)
+{
+ JSValue ret;
+ uint32_t u32;
+ uint64_t u64, index, size;
+ njs_str_t self;
+ njs_bool_t little, swap, sign;
+
+ ret = qjs_typed_array_data(ctx, this_val, &self);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ if (JS_ToIndex(ctx, &index, argv[0])) {
+ return JS_EXCEPTION;
+ }
+
+ size = magic >> 2;
+
+ if (!size) {
+ if (!JS_IsNumber(argv[1])) {
+ return JS_ThrowTypeError(ctx, "\"byteLength\" is not a number");
+ }
+
+ if (JS_ToIndex(ctx, &size, argv[1])) {
+ return JS_EXCEPTION;
+ }
+
+ if (size > 6) {
+ return JS_ThrowRangeError(ctx, "\"byteLength\" must be <= 6");
+ }
+ }
+
+ if (size + index > self.length) {
+ return JS_ThrowRangeError(ctx, "index %lu is outside the bound of the"
+ " buffer", index);
+ }
+
+ sign = (magic >> 1) & 1;
+ little = magic & 1;
+ swap = little;
+
+#if NJS_HAVE_LITTLE_ENDIAN
+ swap = !swap;
+#endif
+
+ switch (size) {
+ case 1:
+ if (sign) {
+ return JS_NewInt32(ctx, (int8_t) self.start[index]);
+ }
+
+ return JS_NewUint32(ctx, self.start[index]);
+
+ case 2:
+ u32 = njs_get_u16(&self.start[index]);
+
+ if (swap) {
+ u32 = njs_bswap_u16(u32);
+ }
+
+ if (sign) {
+ /* Sign extension. */
+ u32 |= (u32 & (INT16_MAX + 1ULL)) * UINT32_MAX;
+
+ return JS_NewInt32(ctx, (int16_t) u32);
+ }
+
+ return JS_NewUint32(ctx, u32);
+
+ case 3:
+
+ if (little) {
+ u32 = (self.start[index + 2] << 16)
+ | (self.start[index + 1] << 8)
+ | self.start[index];
+
+ } else {
+ u32 = (self.start[index] << 16)
+ | (self.start[index + 1] << 8)
+ | self.start[index + 2];
+ }
+
+ if (sign) {
+ /* Sign extension. */
+ u32 |= (u32 & (INT24_MAX + 1ULL)) * UINT32_MAX;
+
+ return JS_NewInt32(ctx, (int32_t) u32);
+ }
+
+ return JS_NewUint32(ctx, u32);
+
+ case 4:
+ u32 = njs_get_u32(&self.start[index]);
+
+ if (swap) {
+ u32 = njs_bswap_u32(u32);
+ }
+
+ if (sign) {
+ /* Sign extension. */
+ u32 |= (u32 & (INT32_MAX + 1ULL)) * UINT32_MAX;
+
+ return JS_NewInt32(ctx, (int32_t) u32);
+ }
+
+ return JS_NewUint32(ctx, u32);
+
+ case 5:
+ if (little) {
+ u64 = ((uint64_t) self.start[index + 4] << 32)
+ | ((uint64_t) self.start[index + 3] << 24)
+ | (self.start[index + 2] << 16)
+ | (self.start[index + 1] << 8)
+ | self.start[index];
+
+ } else {
+ u64 = ((uint64_t) self.start[index] << 32)
+ | ((uint64_t) self.start[index + 1] << 24)
+ | (self.start[index + 2] << 16)
+ | (self.start[index + 3] << 8)
+ | self.start[index + 4];
+ }
+
+ if (sign) {
+ /* Sign extension. */
+ u64 |= (u64 & (INT40_MAX + 1ULL)) * UINT64_MAX;
+
+ return JS_NewFloat64(ctx, (int64_t) u64);
+ }
+
+ return JS_NewFloat64(ctx, u64);
+
+ case 6:
+ default:
+ if (little) {
+ u64 = ((uint64_t) self.start[index + 5] << 40)
+ | ((uint64_t) self.start[index + 4] << 32)
+ | ((uint64_t) self.start[index + 3] << 24)
+ | (self.start[index + 2] << 16)
+ | (self.start[index + 1] << 8)
+ | self.start[index];
+
+ } else {
+ u64 = ((uint64_t) self.start[index] << 40)
+ | ((uint64_t) self.start[index + 1] << 32)
+ | ((uint64_t) self.start[index + 2] << 24)
+ | (self.start[index + 3] << 16)
+ | (self.start[index + 4] << 8)
+ | self.start[index + 5];
+ }
+
+ if (sign) {
+ /* Sign extension. */
+ u64 |= (u64 & (INT48_MAX + 1ULL)) * UINT64_MAX;
+
+ return JS_NewFloat64(ctx, (int64_t) u64);
+ }
+
+ return JS_NewFloat64(ctx, u64);
+ }
+}
+
+
+static JSValue
+qjs_buffer_prototype_to_json(JSContext *ctx, JSValueConst this_val, int argc,
+ JSValueConst *argv)
+{
+ int rc;
+ JSValue obj, data, ret;
+ njs_str_t src;
+ njs_uint_t i;
+
+ ret = qjs_typed_array_data(ctx, this_val, &src);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ obj = JS_NewObject(ctx);
+ if (JS_IsException(obj)) {
+ return obj;
+ }
+
+ data = JS_NewArray(ctx);
+ if (JS_IsException(data)) {
+ JS_FreeValue(ctx, obj);
+ return data;
+ }
+
+ rc = JS_DefinePropertyValueStr(ctx, obj, "type",
+ JS_NewString(ctx, "Buffer"),
+ JS_PROP_ENUMERABLE);
+ if (rc == -1) {
+ JS_FreeValue(ctx, obj);
+ JS_FreeValue(ctx, data);
+ return ret;
+ }
+
+ rc = JS_DefinePropertyValueStr(ctx, obj, "data", data, JS_PROP_ENUMERABLE);
+ if (rc == -1) {
+ JS_FreeValue(ctx, obj);
+ JS_FreeValue(ctx, data);
+ return ret;
+ }
+
+ for (i = 0; i < src.length; i++) {
+ rc = JS_SetPropertyUint32(ctx, data, i, JS_NewInt32(ctx, src.start[i]));
+ if (rc == -1) {
+ JS_FreeValue(ctx, obj);
+ JS_FreeValue(ctx, data);
+ return ret;
+ }
+ }
+
+ return obj;
+}
+
+
+static JSValue
+qjs_buffer_prototype_swap(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int size)
+{
+ uint8_t *p, *end;
+ JSValue ret;
+ njs_str_t self;
+
+ ret = qjs_typed_array_data(ctx, this_val, &self);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ if ((self.length % size) != 0) {
+ return JS_ThrowRangeError(ctx, "Buffer size must be a multiple "
+ "of %d-bits", (int) (size << 3));
+ }
+
+ p = self.start;
+ end = p + self.length;
+
+ switch (size) {
+ case 2:
+ for (; p < end; p += 2) {
+ njs_set_u16(p, njs_bswap_u16(njs_get_u16(p)));
+ }
+
+ break;
+
+ case 4:
+ for (; p < end; p += 4) {
+ njs_set_u32(p, njs_bswap_u32(njs_get_u32(p)));
+ }
+
+ break;
+
+ case 8:
+ default:
+ for (; p < end; p += 8) {
+ njs_set_u64(p, njs_bswap_u64(njs_get_u64(p)));
+ }
+ }
+
+ JS_DupValue(ctx, this_val);
+
+ return this_val;
+}
+
+
+static JSValue
+qjs_buffer_prototype_to_string(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue ret;
+ njs_str_t src, data;
+ const qjs_buffer_encoding_t *encoding;
+
+ ret = qjs_typed_array_data(ctx, this_val, &src);
+ if (JS_IsException(ret)) {
+ return JS_ThrowTypeError(ctx, "method toString() called on incompatible"
+ " object");
+ }
+
+ if (JS_IsUndefined(argv[0]) || src.length == 0) {
+ return JS_NewStringLen(ctx, (char *) src.start, src.length);
+ }
+
+ encoding = qjs_buffer_encoding(ctx, argv[0], 1);
+ if (njs_slow_path(encoding == NULL)) {
+ return JS_EXCEPTION;
+ }
+
+ if (encoding->encode_length == NULL) {
+ return JS_NewStringLen(ctx, (char *) src.start, src.length);
+ }
+
+ data.length = encoding->encode_length(ctx, &src);
+ data.start = js_malloc(ctx, data.length);
+ if (njs_slow_path(data.start == NULL)) {
+ JS_ThrowOutOfMemory(ctx);
+ return JS_EXCEPTION;
+ }
+
+ if (encoding->encode(ctx, &src, &data) != 0) {
+ js_free(ctx, data.start);
+ JS_ThrowTypeError(ctx, "failed to encode buffer");
+ return JS_EXCEPTION;
+ }
+
+ ret = JS_NewStringLen(ctx, (char *) data.start, data.length);
+
+ js_free(ctx, data.start);
+
+ return ret;
+}
+
+
+static JSValue
+qjs_buffer_prototype_write(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue ret, buffer, encode;
+ uint64_t offset, max_length;
+ njs_str_t self, src;
+ const uint8_t *p, *end, *prev;
+ const qjs_buffer_encoding_t *encoding;
+
+ ret = qjs_typed_array_data(ctx, this_val, &self);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ offset = 0;
+ max_length = self.length;
+ encode = argv[3];
+
+ if (!JS_IsUndefined(argv[1])) {
+ if (JS_IsString(argv[0]) && JS_IsString(argv[1])) {
+ encode = argv[1];
+ goto write;
+ }
+
+ if (JS_ToIndex(ctx, &offset, argv[1])) {
+ return JS_EXCEPTION;
+ }
+
+ max_length = self.length - offset;
+ }
+
+ if (!JS_IsUndefined(argv[2])) {
+ if (JS_IsString(argv[0]) && JS_IsString(argv[2])) {
+ encode = argv[2];
+ goto write;
+ }
+
+ if (JS_ToIndex(ctx, &max_length, argv[2])) {
+ return JS_EXCEPTION;
+ }
+ }
+
+write:
+
+ encoding = qjs_buffer_encoding(ctx, encode, 1);
+ if (encoding == NULL) {
+ return JS_EXCEPTION;
+ }
+
+ buffer = qjs_buffer_from_string(ctx, argv[0], encode);
+ if (JS_IsException(buffer)) {
+ return buffer;
+ }
+
+ (void) qjs_typed_array_data(ctx, buffer, &src);
+
+ if (offset > self.length) {
+ JS_FreeValue(ctx, buffer);
+ return JS_ThrowRangeError(ctx, "\"offset\" is out of range");
+ }
+
+ if (src.length == 0) {
+ JS_FreeValue(ctx, buffer);
+ return JS_NewInt32(ctx, 0);
+ }
+
+ if (max_length > self.length - offset) {
+ JS_FreeValue(ctx, buffer);
+ return JS_ThrowRangeError(ctx, "\"length\" is out of range");
+ }
+
+ max_length = njs_min(max_length, src.length);
+
+ if (encoding->decode == NULL) {
+ /* Avoid writing incomplete UTF-8 characters. */
+ p = prev = src.start;
+ end = p + max_length;
+
+ while (p < end) {
+ p = njs_utf8_next(p, src.start + src.length);
+ if (p <= end) {
+ prev = p;
+ }
+ }
+
+ max_length = prev - src.start;
+ }
+
+ memcpy(&self.start[offset], src.start, max_length);
+
+ JS_FreeValue(ctx, buffer);
+
+ return JS_NewInt32(ctx, max_length);
+}
+
+
+static JSValue
+qjs_buffer_prototype_write_int(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic)
+{
+ JSValue ret;
+ int64_t i64;
+ uint32_t u32;
+ uint64_t index, size;
+ njs_str_t self;
+ njs_bool_t little, swap, sign;
+
+ ret = qjs_typed_array_data(ctx, this_val, &self);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ if (JS_ToIndex(ctx, &index, argv[1])) {
+ return JS_EXCEPTION;
+ }
+
+ size = magic >> 2;
+
+ if (!size) {
+ if (JS_ToIndex(ctx, &size, argv[2])) {
+ return JS_EXCEPTION;
+ }
+
+ if (size > 6) {
+ return JS_ThrowRangeError(ctx, "\"byteLength\" must be <= 6");
+ }
+ }
+
+ if (size + index > self.length) {
+ return JS_ThrowRangeError(ctx, "index %lu is outside the bound of the"
+ " buffer", index);
+ }
+
+ little = magic & 1;
+ sign = (magic >> 1) & 1;
+ swap = little;
+
+#if NJS_HAVE_LITTLE_ENDIAN
+ swap = !swap;
+#endif
- JS_FreeValue(ctx, ctor);
- str = JS_ToCString(ctx, name);
+ if (JS_ToInt64(ctx, &i64, argv[0])) {
+ return JS_EXCEPTION;
+ }
- if (strncmp(str, "Float32Array", 12) == 0) {
- float32 = 1;
+ switch (size) {
+ case 1:
+ if (sign) {
+ if (i64 < INT8_MIN || i64 > INT8_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
}
- JS_FreeCString(ctx, str);
- JS_FreeValue(ctx, name);
+ } else {
+ if (i64 < 0 || i64 > UINT8_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
+ }
}
- return qjs_buffer_from_typed_array(ctx, ret, off, size, bytes, float32);
-
- } else if ((buf = JS_GetArrayBuffer(ctx, &size, argv[0])) != NULL) {
- return qjs_buffer_from_array_buffer(ctx, buf, size, argv[1], argv[2]);
+ self.start[index] = (uint8_t) i64;
+ break;
- } else if (JS_IsObject(argv[0])) {
- obj = argv[0];
- valueOf = JS_GetPropertyStr(ctx, obj, "valueOf");
- if (JS_IsException(valueOf)) {
- return valueOf;
- }
+ case 2:
+ u32 = (uint16_t) i64;
- if (JS_IsFunction(ctx, valueOf)) {
- ret = JS_Call(ctx, valueOf, obj, 0, NULL);
- JS_FreeValue(ctx, valueOf);
- if (JS_IsException(ret)) {
- return ret;
+ if (sign) {
+ if (i64 < INT16_MIN || i64 > INT16_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
}
- if (JS_IsString(ret)) {
- obj = ret;
- ret = qjs_buffer_from_string(ctx, obj, argv[1]);
- JS_FreeValue(ctx, obj);
- return ret;
+ } else {
+ if (i64 < 0 || i64 > UINT16_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
}
+ }
- if (JS_IsObject(ret)
- && JS_VALUE_GET_PTR(ret) != JS_VALUE_GET_PTR(obj))
- {
- obj = ret;
- ret = qjs_buffer_from_object(ctx, obj);
- JS_FreeValue(ctx, obj);
- return ret;
+ if (swap) {
+ u32 = njs_bswap_u16(u32);
+ }
+
+ njs_set_u16(&self.start[index], u32);
+ break;
+
+ case 3:
+ if (sign) {
+ if (i64 < INT24_MIN || i64 > INT24_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
}
- JS_FreeValue(ctx, ret);
+ } else {
+ if (i64 < 0 || i64 > UINT24_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
+ }
}
- return qjs_buffer_from_object(ctx, obj);
- }
+ if (little) {
+ self.start[index] = i64; i64 >>= 8;
+ self.start[index + 1] = i64; i64 >>= 8;
+ self.start[index + 2] = i64;
- JS_ThrowTypeError(ctx, "first argument is not a string "
- "or Buffer-like object");
- return JS_EXCEPTION;
-}
+ } else {
+ self.start[index + 2] = i64; i64 >>= 8;
+ self.start[index + 1] = i64; i64 >>= 8;
+ self.start[index] = i64;
+ }
+ break;
-static JSValue
-qjs_buffer_is_buffer(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue proto, buffer_proto, ret;
+ case 4:
+ u32 = i64;
- proto = JS_GetPrototype(ctx, argv[0]);
- buffer_proto = JS_GetClassProto(ctx, qjs_buffer_class_id);
+ if (sign) {
+ if (i64 < INT32_MIN || i64 > INT32_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
+ }
- ret = JS_NewBool(ctx, JS_VALUE_GET_TAG(argv[0]) == JS_TAG_OBJECT &&
- JS_VALUE_GET_OBJ(buffer_proto) == JS_VALUE_GET_OBJ(proto));
+ } else {
+ if (i64 < 0 || i64 > UINT32_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
+ }
+ }
- JS_FreeValue(ctx, buffer_proto);
- JS_FreeValue(ctx, proto);
+ if (swap) {
+ u32 = njs_bswap_u32(u32);
+ }
- return ret;
-}
+ njs_set_u32(&self.start[index], u32);
+ break;
+ case 5:
+ if (sign) {
+ if (i64 < INT40_MIN || i64 > INT40_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
+ }
-static JSValue
-qjs_buffer_prototype_to_json(JSContext *ctx, JSValueConst this_val, int argc,
- JSValueConst *argv)
-{
- int rc;
- JSValue obj, data, ret;
- njs_str_t src;
- njs_uint_t i;
+ } else {
+ if (i64 < 0 || i64 > UINT40_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
+ }
+ }
- ret = qjs_typed_array_data(ctx, this_val, &src);
- if (JS_IsException(ret)) {
- return ret;
- }
+ if (little) {
+ self.start[index] = i64; i64 >>= 8;
+ self.start[index + 1] = i64; i64 >>= 8;
+ self.start[index + 2] = i64; i64 >>= 8;
+ self.start[index + 3] = i64; i64 >>= 8;
+ self.start[index + 4] = i64;
- obj = JS_NewObject(ctx);
- if (JS_IsException(obj)) {
- return obj;
- }
+ } else {
+ self.start[index + 4] = i64; i64 >>= 8;
+ self.start[index + 3] = i64; i64 >>= 8;
+ self.start[index + 2] = i64; i64 >>= 8;
+ self.start[index + 1] = i64; i64 >>= 8;
+ self.start[index] = i64;
+ }
- data = JS_NewArray(ctx);
- if (JS_IsException(data)) {
- JS_FreeValue(ctx, obj);
- return data;
- }
+ break;
- rc = JS_DefinePropertyValueStr(ctx, obj, "type",
- JS_NewString(ctx, "Buffer"),
- JS_PROP_ENUMERABLE);
- if (rc == -1) {
- JS_FreeValue(ctx, obj);
- JS_FreeValue(ctx, data);
- return ret;
- }
+ case 6:
+ default:
+ if (sign) {
+ if (i64 < INT48_MIN || i64 > INT48_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
+ }
- rc = JS_DefinePropertyValueStr(ctx, obj, "data", data, JS_PROP_ENUMERABLE);
- if (rc == -1) {
- JS_FreeValue(ctx, obj);
- JS_FreeValue(ctx, data);
- return ret;
- }
+ } else {
+ if (i64 < 0 || i64 > UINT48_MAX) {
+ return JS_ThrowRangeError(ctx, "value is outside the range of"
+ " representable values");
+ }
+ }
- for (i = 0; i < src.length; i++) {
- rc = JS_SetPropertyUint32(ctx, data, i, JS_NewInt32(ctx, src.start[i]));
- if (rc == -1) {
- JS_FreeValue(ctx, obj);
- JS_FreeValue(ctx, data);
- return ret;
+ if (little) {
+ self.start[index] = i64; i64 >>= 8;
+ self.start[index + 1] = i64; i64 >>= 8;
+ self.start[index + 2] = i64; i64 >>= 8;
+ self.start[index + 3] = i64; i64 >>= 8;
+ self.start[index + 4] = i64; i64 >>= 8;
+ self.start[index + 5] = i64;
+
+ } else {
+ self.start[index + 5] = i64; i64 >>= 8;
+ self.start[index + 4] = i64; i64 >>= 8;
+ self.start[index + 3] = i64; i64 >>= 8;
+ self.start[index + 2] = i64; i64 >>= 8;
+ self.start[index + 1] = i64; i64 >>= 8;
+ self.start[index] = i64;
}
+
+ break;
}
- return obj;
+ return JS_NewInt32(ctx, size + index);
}
-
static JSValue
-qjs_buffer_prototype_to_string(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+qjs_buffer_prototype_write_float(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic)
{
- JSValue ret;
- njs_str_t src, data;
- const qjs_buffer_encoding_t *encoding;
-
- ret = qjs_typed_array_data(ctx, this_val, &src);
+ double v;
+ JSValue ret;
+ uint32_t u32;
+ uint64_t u64, index, size;
+ njs_str_t self;
+ njs_bool_t little, swap;
+ njs_conv_f32_t conv_f32;
+ njs_conv_f64_t conv_f64;
+
+ ret = qjs_typed_array_data(ctx, this_val, &self);
if (JS_IsException(ret)) {
return ret;
}
- if (JS_IsUndefined(argv[0]) || src.length == 0) {
- return JS_NewStringLen(ctx, (char *) src.start, src.length);
+ if (JS_ToFloat64(ctx, &v, argv[0])) {
+ return JS_EXCEPTION;
}
- encoding = qjs_buffer_encoding(ctx, argv[0], 1);
- if (njs_slow_path(encoding == NULL)) {
+ if (JS_ToIndex(ctx, &index, argv[1])) {
return JS_EXCEPTION;
}
- if (encoding->encode_length == NULL) {
- return JS_NewStringLen(ctx, (char *) src.start, src.length);
- }
+ size = magic >> 2;
- data.length = encoding->encode_length(ctx, &src);
- data.start = js_malloc(ctx, data.length);
- if (njs_slow_path(data.start == NULL)) {
- JS_ThrowOutOfMemory(ctx);
- return JS_EXCEPTION;
+ if (size + index > self.length) {
+ return JS_ThrowRangeError(ctx, "index %lu is outside the bound of the"
+ " buffer", index);
}
- if (encoding->encode(ctx, &src, &data) != 0) {
- js_free(ctx, data.start);
- JS_ThrowTypeError(ctx, "failed to encode buffer");
- return JS_EXCEPTION;
- }
+ little = magic & 1;
+ swap = little;
- ret = JS_NewStringLen(ctx, (char *) data.start, data.length);
+#if NJS_HAVE_LITTLE_ENDIAN
+ swap = !swap;
+#endif
- js_free(ctx, data.start);
+ switch (size) {
+ case 4:
+ conv_f32.f = (float) v;
- return ret;
+ if (swap) {
+ conv_f32.u = njs_bswap_u32(conv_f32.u);
+ }
+
+ u32 = conv_f32.u;
+ memcpy(&self.start[index], &u32, size);
+ break;
+
+ case 8:
+ default:
+ conv_f64.f = v;
+
+ if (swap) {
+ conv_f64.u = njs_bswap_u64(conv_f64.u);
+ }
+
+ u64 = conv_f64.u;
+ memcpy(&self.start[index], &u64, size);
+ break;
+ }
+
+ return JS_NewInt32(ctx, size + index);
}
@@ -424,6 +1883,11 @@ qjs_buffer_from_string(JSContext *ctx, JSValueConst str,
njs_str_t src, dst;
const qjs_buffer_encoding_t *encoding;
+ if (!JS_IsString(str)) {
+ JS_ThrowTypeError(ctx, "first argument is not a string");
+ return JS_EXCEPTION;
+ }
+
encoding = qjs_buffer_encoding(ctx, enc, 1);
if (njs_slow_path(encoding == NULL)) {
return JS_EXCEPTION;
@@ -552,57 +2016,6 @@ qjs_buffer_from_typed_array(JSContext *ctx, JSValueConst arr_buf,
return buffer;
}
-static JSValue
-qjs_buffer_from_array_buffer(JSContext *ctx, u_char *buf, size_t size,
- JSValueConst offset, JSValueConst length)
-{
- JSValue buffer, ret;
- int64_t len;
- uint64_t off;
- njs_str_t dst;
-
- if (JS_ToIndex(ctx, &off, offset)) {
- return JS_EXCEPTION;
- }
-
- if ((size_t) off > size) {
- JS_ThrowRangeError(ctx, "\"offset\" is outside of buffer bounds");
- return JS_EXCEPTION;
- }
-
- if (JS_IsUndefined(length)) {
- len = size - off;
-
- } else {
- if (JS_ToInt64(ctx, &len, length)) {
- return JS_EXCEPTION;
- }
-
- if (len < 0) {
- len = 0;
- }
-
- if ((size_t) (off + len) > size) {
- JS_ThrowRangeError(ctx, "\"length\" is outside of buffer bounds");
- return JS_EXCEPTION;
- }
- }
-
- buffer = qjs_buffer_alloc(ctx, len);
- if (JS_IsException(buffer)) {
- return buffer;
- }
-
- ret = qjs_typed_array_data(ctx, buffer, &dst);
- if (JS_IsException(ret)) {
- return ret;
- }
-
- memcpy(dst.start, buf + off, len);
-
- return buffer;
-}
-
static JSValue
qjs_buffer_from_object(JSContext *ctx, JSValueConst obj)
@@ -872,7 +2285,7 @@ qjs_base64_decode_length(JSContext *ctx, const njs_str_t *src)
static int
qjs_base64url_encode(JSContext *ctx, const njs_str_t *src, njs_str_t *dst)
{
- qjs_base64_encode_core(dst, src, qjs_basis64url_enc, 1);
+ qjs_base64_encode_core(dst, src, qjs_basis64url_enc, 0);
return 0;
}
@@ -1004,9 +2417,11 @@ qjs_hex_encode_length(JSContext *ctx, const njs_str_t *src)
JSValue
qjs_buffer_alloc(JSContext *ctx, size_t size)
{
- JSValue ret, proto;
+ JSValue ret, proto, value;
+
+ value = JS_NewInt64(ctx, size);
- ret = qjs_new_uint8_array(ctx, size);
+ ret = qjs_new_uint8_array(ctx, 1, &value);
if (JS_IsException(ret)) {
return ret;
}
@@ -1019,6 +2434,29 @@ qjs_buffer_alloc(JSContext *ctx, size_t size)
}
+
+JSValue
+qjs_buffer_create(JSContext *ctx, u_char *start, size_t size)
+{
+ JSValue buffer, ret;
+ njs_str_t dst;
+
+ buffer = qjs_buffer_alloc(ctx, size);
+ if (JS_IsException(buffer)) {
+ return buffer;
+ }
+
+ ret = qjs_typed_array_data(ctx, buffer, &dst);
+ if (JS_IsException(ret)) {
+ return ret;
+ }
+
+ memcpy(dst.start, start, size);
+
+ return buffer;
+}
+
+
JSValue
qjs_buffer_chb_alloc(JSContext *ctx, njs_chb_t *chain)
{
@@ -1047,24 +2485,20 @@ qjs_buffer_chb_alloc(JSContext *ctx, njs_chb_t *chain)
static JSValue
-qjs_new_uint8_array(JSContext *ctx, size_t size)
+qjs_new_uint8_array(JSContext *ctx, int argc, JSValueConst *argv)
{
- JSValue ret, value;
-
- value = JS_NewInt64(ctx, size);
+ JSValue ret;
#ifdef NJS_HAVE_QUICKJS_NEW_TYPED_ARRAY
- ret = JS_NewTypedArray(ctx, 1, &value, JS_TYPED_ARRAY_UINT8);
+ ret = JS_NewTypedArray(ctx, argc, argv, JS_TYPED_ARRAY_UINT8);
#else
JSValue ctor;
ctor = JS_GetClassProto(ctx, qjs_uint8_array_ctor_id);
- ret = JS_CallConstructor(ctx, ctor, 1, &value);
+ ret = JS_CallConstructor(ctx, ctor, argc, argv);
JS_FreeValue(ctx, ctor);
#endif
- JS_FreeValue(ctx, value);
-
return ret;
}
@@ -1073,18 +2507,19 @@ static int
qjs_buffer_builtin_init(JSContext *ctx)
{
int rc;
- JSValue global_obj, buffer, proto, ctor, ta, ta_proto;
+ JSAtom species_atom;
+ JSValue global_obj, buffer, proto, ctor, ta, ta_proto, symbol, species;
JSClassID u8_ta_class_id;
JS_NewClassID(&qjs_buffer_class_id);
JS_NewClass(JS_GetRuntime(ctx), qjs_buffer_class_id, &qjs_buffer_class);
+ global_obj = JS_GetGlobalObject(ctx);
+
proto = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, proto, qjs_buffer_proto,
njs_nitems(qjs_buffer_proto));
- global_obj = JS_GetGlobalObject(ctx);
-
ctor = JS_GetPropertyStr(ctx, global_obj, "Uint8Array");
#ifndef NJS_HAVE_QUICKJS_NEW_TYPED_ARRAY
@@ -1110,15 +2545,29 @@ qjs_buffer_builtin_init(JSContext *ctx)
JS_SetClassProto(ctx, qjs_buffer_class_id, proto);
- buffer = JS_NewCFunction2(ctx, qjs_buffer, "Buffer", 0,
- JS_CFUNC_generic, 0);
+ buffer = JS_NewCFunction2(ctx, qjs_buffer, "Buffer", 3,
+ JS_CFUNC_constructor, 0);
if (JS_IsException(buffer)) {
return -1;
}
+ JS_SetConstructor(ctx, buffer, proto);
+
JS_SetPropertyFunctionList(ctx, buffer, qjs_buffer_props,
njs_nitems(qjs_buffer_props));
+ symbol = JS_GetPropertyStr(ctx, global_obj, "Symbol");
+ species = JS_GetPropertyStr(ctx, symbol, "species");
+ JS_FreeValue(ctx, symbol);
+ species_atom = JS_ValueToAtom(ctx, species);
+ JS_FreeValue(ctx, species);
+
+ ctor = JS_NewCFunction2(ctx, qjs_buffer_ctor, "Buffer species ctor", 3,
+ JS_CFUNC_constructor, 0);
+
+ JS_SetProperty(ctx, buffer, species_atom, ctor);
+ JS_FreeAtom(ctx, species_atom);
+
rc = JS_SetPropertyStr(ctx, global_obj, "Buffer", buffer);
if (rc == -1) {
return -1;
diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c
index c6979c13..10ee6c1e 100644
--- a/src/test/njs_unit_test.c
+++ b/src/test/njs_unit_test.c
@@ -21015,817 +21015,6 @@ static njs_unit_test_t njs_querystring_module_test[] =
};
-static njs_unit_test_t njs_buffer_module_test[] =
-{
- { njs_str("new Buffer();"),
- njs_str("TypeError: Buffer is not a constructor") },
-
- { njs_str("var buf = Buffer.alloc();"),
- njs_str("TypeError: \"size\" argument must be of type number") },
-
- { njs_str("var buf = Buffer.alloc('best buffer');"),
- njs_str("TypeError: \"size\" argument must be of type number") },
-
- { njs_str("var buf = Buffer.alloc(-1);"),
- njs_str("RangeError: invalid size") },
-
- { njs_str("var buf = Buffer.alloc(4); njs.dump(buf)"),
- njs_str("Buffer [0,0,0,0]") },
-
- { njs_str("var buf = Buffer.alloc(4, 88); buf"),
- njs_str("XXXX") },
-
- { njs_str("var buf = Buffer.alloc(4, 945); njs.dump(buf)"),
- njs_str("Buffer [177,177,177,177]") },
-
- { njs_str("var buf = Buffer.alloc(4, -1); njs.dump(buf)"),
- njs_str("Buffer [255,255,255,255]") },
-
- { njs_str("var buf = Buffer.alloc(4, -1, 'utf-128'); njs.dump(buf)"),
- njs_str("Buffer [255,255,255,255]") },
-
- { njs_str("var buf = Buffer.alloc(10, 'α'); buf"),
- njs_str("ααααα") },
-
- { njs_str("var buf = Buffer.alloc(4, 'α'); njs.dump(buf)"),
- njs_str("Buffer [206,177,206,177]") },
-
- { njs_str("var buf = Buffer.alloc(2, 'ααααα'); njs.dump(buf)"),
- njs_str("Buffer [206,177]") },
-
- { njs_str("var buf = Buffer.alloc(1, 'α'); njs.dump(buf)"),
- njs_str("Buffer [206]") },
-
- { njs_str("var buf = Buffer.alloc(4, 'ZXZpbA==', 'base64'); buf"),
- njs_str("evil") },
-
- { njs_str("var buf = Buffer.alloc(8, 'ZXZpbA==', 'base64'); buf"),
- njs_str("evilevil") },
-
- { njs_str("var buf = Buffer.alloc(8, 'evil', 'utf-128'); buf"),
- njs_str("TypeError: \"utf-128\" encoding is not supported") },
-
- { njs_str("var foo = new Uint8Array(10).fill(88);"
- "var buf = Buffer.alloc(8, foo); buf"),
- njs_str("XXXXXXXX") },
-
- { njs_str("[1,2,10,20].every(v => {"
- " var src = new Uint16Array(v).fill(0xB1CE);"
- " var buf = Buffer.alloc(10, src);"
- " return buf.toString() === " njs_evar("'ααααα'", "'�αααα�'")
- "})"),
- njs_str("true") },
-
- { njs_str("var foo = Buffer.alloc(10, 'α');"
- "var buf = Buffer.alloc(4, foo); buf"),
- njs_str("αα") },
-
- { njs_str("var buf = Buffer.allocUnsafe(10).fill('α'); buf"),
- njs_str("ααααα") },
-
- { njs_str("var buf = Buffer.allocUnsafe(-1)"),
- njs_str("RangeError: invalid size") },
-
- { njs_str("["
- " ['6576696c', 'hex', 4],"
- " ['6576696', 'hex', 3],"
- " ['', 'hex', 0],"
- " ['', 'base64', 0],"
- " ['ZXZpbA==', 'base64', 4],"
- " ['ZXZpbA', 'base64url', 4],"
- " ['ααααα', undefined, 10],"
- "].every(args => Buffer.byteLength(args[0], args[1]) == args[2])"),
- njs_str("true") },
-
- { njs_str("var foo = new Uint8Array(5);"
- "foo[0] = 1; foo[1] = 2; foo[2] = 3; foo[3] = 4; foo[4] = 5;"
- "foo = foo.subarray(1, 3);"
- "var buf = Buffer.from(foo); njs.dump(buf)"),
- njs_str("Buffer [2,3]") },
-
- { njs_str("['utf8', 'utf-8', 'hex', 'base64', 'base64url', 'utf-88', '1hex']"
- ".map(v=>Buffer.isEncoding(v))"),
- njs_str("true,true,true,true,true,false,false") },
-
- { njs_str("["
- " ['ABC', 'ABCD', -1],"
- " ['ABCD', 'ABC', 1],"
- " ['ABC', 'ACB', -1],"
- " ['ACB', 'ABC', 1],"
- " ['ABC', 'ABC', 0],"
- " ['', 'ABC', -1],"
- " ['', '', 0],"
- "].every(args => {"
- " if (Buffer.compare(Buffer.from(args[0]), Buffer.from(args[1])) != args[2]) {"
- " throw new TypeError("
- " `Buffer.compare(Buffer.from(${args[0]}), Buffer.from(${args[1]})) != ${args[2]}`);"
- " }"
- " return true;"
- "})"),
- njs_str("true") },
-
- { njs_str("["
- " ['ABC', 'ABCD', -1],"
- " ['ABCD', 'ABC', 1],"
- " ['ABC', 'ACB', -1],"
- " ['ACB', 'ABC', 1],"
- " ['ABC', 'ABC', 0],"
- " ['', 'ABC', -1],"
- " ['', '', 0],"
- "].every(args => {"
- " if (Buffer.from(args[0]).compare(Buffer.from(args[1])) != args[2]) {"
- " throw new TypeError("
- " `Buffer.from(${args[0]}).compare(Buffer.from(${args[1]})) != ${args[2]}`);"
- " }"
- " return true;"
- "})"),
- njs_str("true") },
-
- { njs_str("var buf = Buffer.from('ABCD');"
- "["
- " [0,3,0,2, -1],"
- " [0,2,0,3, 1],"
- " [3,4,3,4, 0],"
- " [undefined, undefined, undefined, undefined, 0],"
- " [-1, undefined, undefined, undefined, 'invalid index'],"
- " [0, -1, undefined, undefined, 'invalid index'],"
- " [0, 0, -1, undefined, 'invalid index'],"
- " [0, 0, 0, -1, 'invalid index'],"
- "]"
- ".every(as => {"
- " try {"
- " if (buf.compare(buf, as[0], as[1], as[2], as[3]) != as[4]) {"
- " throw new TypeError("
- " `buf.compare(${as[0]}, ${as[1]}, ${as[2]}, ${as[3]}) != ${as[4]}`);"
- " }"
- " } catch (e) { return e.message == as[4]}"
- " return true;"
- "})"),
- njs_str("true") },
-
- { njs_str("var buf1 = Buffer.from('ABCD');"
- "var buf2 = Buffer.from('ABCD');"
- "buf1.compare(buf2, 5)"),
- njs_str("RangeError: \"targetStart\" is out of range: 5") },
-
- { njs_str("var buf1 = Buffer.from('ABCD');"
- "var buf2 = Buffer.from('ABCD');"
- "buf1.compare(buf2, 0, 3, 5)"),
- njs_str("RangeError: \"sourceStart\" is out of range: 5") },
-
- { njs_str("var arr = new Uint8Array(4);"
- "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;"
- "arr = arr.subarray(1, 4);"
- "var buf = Buffer.from('ABCD');"
- "buf.compare(arr, 0, 3, 1, 4)"),
- njs_str("0") },
-
- { njs_str("['123', 'abc', '124', '', 'AB', 'ABCD']"
- ".map(v=>Buffer.from(v)).sort(Buffer.compare).map(v=>v.toString())"),
- njs_str(",123,124,AB,ABCD,abc") },
-
- { njs_str("Buffer.compare(Buffer.alloc(1), 'text')"),
- njs_str("TypeError: \"target\" argument must be an instance of Buffer or Uint8Array") },
-
- { njs_str("Buffer.compare('text', Buffer.from('ACB'))"),
- njs_str("TypeError: \"source\" argument must be an instance of Buffer or Uint8Array") },
-
- { njs_str("Buffer.concat()"),
- njs_str("TypeError: \"list\" argument must be an instance of Array") },
-
- { njs_str("Buffer.concat([])"),
- njs_str("") },
-
- { njs_str("Buffer.concat([new Uint16Array(10)])"),
- njs_str("TypeError: \"list[0]\" argument must be an instance of Buffer or Uint8Array") },
-
- { njs_str("Buffer.concat([new Uint8Array(2), new Uint8Array(1)]).fill('abc')"),
- njs_str("abc") },
-
- { njs_str("Buffer.concat([Buffer.from('AB'), Buffer.from('CD')])"),
- njs_str("ABCD") },
-
- { njs_str("Buffer.concat([new Uint8Array(2), new Uint8Array(1)], 2).fill('abc')"),
- njs_str("ab") },
-
- { njs_str("Buffer.concat([new Uint8Array(2), new Uint8Array(1)], 6).fill('abc')"),
- njs_str("abcabc") },
-
- { njs_str("Buffer.concat([Buffer.from('ABCD').slice(2,4), Buffer.from('ABCD').slice(0,2)])"),
- njs_str("CDAB") },
-
- { njs_str(njs_declare_sparse_array("list", 2)
- "list[0] = Buffer.from('ABCD').slice(2,4);"
- "list[1] = Buffer.from('ABCD').slice(0,2);"
- "Buffer.concat(list);"),
- njs_str("CDAB") },
-
- { njs_str(njs_declare_sparse_array("list", 2)
- "list[0] = new Uint8Array(2); list[1] = new Uint8Array(3);"
- "Buffer.concat(list).fill('ab');"),
- njs_str("ababa") },
-
- { njs_str("Buffer.concat([], '123')"),
- njs_str("TypeError: \"length\" argument must be of type number") },
-
- { njs_str("Buffer.concat([], -1)"),
- njs_str("RangeError: \"length\" is out of range") },
-
- { njs_str("var buf = Buffer.from('α'); buf[1]"),
- njs_str("177") },
-
- { njs_str("var buf = Buffer.from('α'); buf[1] = 1; njs.dump(buf)"),
- njs_str("Buffer [206,1]") },
-
- { njs_str("var arrBuf = new ArrayBuffer(16);"
- "var buf = Buffer.from(arrBuf); buf.buffer === arrBuf"),
- njs_str("true") },
-
- { njs_str("["
- " [[0], 4, '65,66,67,68,0,0,0,0,0,0'],"
- " [[5], 4, '0,0,0,0,0,65,66,67,68,0'],"
- " [[8], 2, '0,0,0,0,0,0,0,0,65,66'],"
- " [[8,2,4], 2, '0,0,0,0,0,0,0,0,67,68'],"
- " [[10], 0, '0,0,0,0,0,0,0,0,0,0'],"
- "]"
- ".every(args => {"
- " var buf1 = Buffer.from('ABCD');"
- " var buf2 = Buffer.alloc(10, 0);"
- " var as = args[0];"
- " var length = buf1.copy(buf2, as[0], as[1], as[2]);"
- ""
- " if (length != args[1]) {"
- " throw new TypeError(`buf1.copy(buf2, ${as[0]}, ${as[1]}, ${as[2]}): ${length} != ${args[1]}`)"
- " }"
- ""
- " if (njs.dump(buf2) != `Buffer [${args[2]}]`) {"
- " throw new TypeError("
- " `buf1.copy(buf2, ${as[0]}, ${as[1]}, ${as[2]}): ${njs.dump(buf2)} != Buffer [${args[2]}]`);"
- " }"
- " return true;"
- "})"),
- njs_str("true") },
-
- { njs_str("["
- " [[0], 'ABCDEF'],"
- " [[0,2], 'CDEFEF'],"
- " [[0,2,6], 'CDEFEF'],"
- " [[1,2,4], 'ACDDEF'],"
- " [[1,2,3], 'ACCDEF']"
- "]"
- ".every(args => {"
- " var buf = Buffer.from('ABCDEF');"
- " var as = args[0];"
- " buf.copy(buf, as[0], as[1], as[2]);"
- ""
- " if (buf.toString() != args[1]) {"
- " throw new TypeError("
- " `buf.copy(buf, ${as[0]}, ${as[1]}, ${as[2]}): buf.toString() != ${args[1]}`);"
- " }"
- " return true;"
- "})"),
- njs_str("true") },
-
- { njs_str("var buf1 = Buffer.from('ABCD');"
- "var buf2 = Buffer.alloc(10, 0);"
- "buf1.copy(buf2, -1)"),
- njs_str("RangeError: invalid index") },
-
- { njs_str("var buf1 = Buffer.from('ABCD');"
- "var buf2 = Buffer.alloc(10, 0);"
- "buf1.copy(buf2, 0, -1)"),
- njs_str("RangeError: invalid index") },
-
- { njs_str("var buf1 = Buffer.from('ABCD');"
- "var buf2 = Buffer.alloc(10, 0);"
- "buf1.copy(buf2, 0, 5)"),
- njs_str("RangeError: \"sourceStart\" is out of range: 5") },
-
- { njs_str("var arr = new Uint8Array(4);"
- "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;"
- "arr = arr.subarray(1, 4);"
- "var buf1 = Buffer.from(arr);"
- "var buf2 = Buffer.alloc(10, 0);"
- "var length = buf1.copy(buf2, 1, 1, 2); [length, njs.dump(buf2)]"),
- njs_str("1,Buffer [0,67,0,0,0,0,0,0,0,0]") },
-
- { njs_str("var arr = new Uint8Array(4);"
- "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;"
- "arr = arr.subarray(1, 4);"
- "var buf1 = Buffer.from(arr);"
- "var buf2 = Buffer.alloc(10, 0);"
- "var length = buf1.copy(buf2, 1, 1, 2); [length, njs.dump(buf2)]"),
- njs_str("1,Buffer [0,67,0,0,0,0,0,0,0,0]") },
-
- { njs_str("["
- " ['ABC', 'ABCD', false],"
- " ['ABCD', 'ABC', false],"
- " ['ABC', 'ACB', false],"
- " ['ACB', 'ABC', false],"
- " ['ABC', 'ABC', true],"
- " ['', 'ABC', false],"
- " ['', '', true],"
- "].every(args => {"
- " if (Buffer.from(args[0]).equals(Buffer.from(args[1])) != args[2]) {"
- " throw new TypeError("
- " `Buffer.from(${args[0]}).compare(Buffer.from(${args[1]})) != ${args[2]}`);"
- " }"
- " return true;"
- "})"),
- njs_str("true") },
-
- { njs_str("Buffer.from([1,2]).equals(new ArrayBuffer(1))"),
- njs_str("TypeError: \"target\" argument must be an instance of Buffer or Uint8Array") },
-
- { njs_str("Buffer.from([1,2]).equals(1)"),
- njs_str("TypeError: \"target\" argument must be an instance of Buffer or Uint8Array") },
-
- { njs_str("var buf = Buffer.alloc(4);"
- "buf.fill('ZXZpbA==', 'base64')"),
- njs_str("evil") },
-
- { njs_str("var buf = Buffer.alloc(4);"
- "buf.fill('6576696c', 'hex')"),
- njs_str("evil") },
-
- { njs_str("var buf = Buffer.alloc(4);"
- "buf.fill('ZXZpbA==', '')"),
- njs_str("TypeError: \"\" encoding is not supported") },
-
- { njs_str("var buf = Buffer.alloc(8);"
- "buf.fill('6576696c', 'hex')"),
- njs_str("evilevil") },
-
- { njs_str("var buf = Buffer.alloc(10);"
- "buf.fill('evil')"),
- njs_str("evilevilev") },
-
- { njs_str("var buf = Buffer.allocUnsafe(5);"
- "buf[3] = 1;"
- "buf.fill(''); njs.dump(buf)"),
- njs_str("Buffer [0,0,0,0,0]") },
-
- { njs_str("var arr = new Uint8Array(4);"
- "arr[0] = 0x41; arr[1] = 0x42; arr[2] = 0x43; arr[3] = 0x44;"
- "arr = arr.subarray(1, 4);"
- "var buf = Buffer.allocUnsafe(6);"
- "buf.fill(arr); njs.dump(buf)"),
- njs_str("Buffer [66,67,68,66,67,68]") },
-
- { njs_str("var buf = Buffer.alloc(6, 'ABCDEF');"
- "buf.fill(buf, 2, 6)"),
- njs_str("ABABCD") },
-
- { njs_str("Buffer.alloc(6).fill(0x41)"),
- njs_str("AAAAAA") },
-
- { njs_str("Buffer.alloc(6).fill({valueOf(){return 0x42}})"),
- njs_str("BBBBBB") },
-
- { njs_str("njs.dump(Buffer.alloc(3).fill(-1))"),
- njs_str("Buffer [255,255,255]") },
-
- { njs_str("[NaN, Infinity, -Infinity, undefined, null, {}]"
- ".every(v => njs.dump(Buffer.alloc(3).fill(v)) == 'Buffer [0,0,0]')"),
- njs_str("true") },
-
- { njs_str("njs.dump(Buffer.alloc(6).fill({valueOf(){throw 'Oops'}}, 4,3))"),
- njs_str("Buffer [0,0,0,0,0,0]") },
-
- { njs_str("njs.dump(Buffer.alloc(6).fill({valueOf(){throw 'Oops'}}, 3,3))"),
- njs_str("Buffer [0,0,0,0,0,0]") },
-
- { njs_str("njs.dump(Buffer.alloc(6).fill({valueOf(){throw 'Oops'}}, 2,3))"),
- njs_str("Oops") },
-
- { njs_str("njs.dump(Buffer.alloc(5).fill('α'))"),
- njs_str("Buffer [206,177,206,177,206]") },
-
- { njs_str("Buffer.alloc(4).fill('ABCD', -1)"),
- njs_str("RangeError: invalid index") },
-
- { njs_str("Buffer.alloc(4).fill('ABCD', 5)"),
- njs_str("RangeError: \"offset\" is out of range") },
-
- { njs_str("Buffer.alloc(4).fill('ABCD', 0, -1)"),
- njs_str("RangeError: invalid index") },
-
- { njs_str("Buffer.alloc(4).fill('ABCD', 0, 5)"),
- njs_str("RangeError: \"end\" is out of range") },
-
- { njs_str("Buffer.alloc(513).fill('A'.repeat(512)).length"),
- njs_str("513") },
-
- { njs_str("njs.dump(Buffer.alloc(4).fill((new Uint8Array(5)).fill(1)))"),
- njs_str("Buffer [1,1,1,1]") },
-
- { njs_str("var src = new Uint8Array(10).fill(255);"
- "var u8 = new Uint8Array(src.buffer, 1, 8);"
- "u8.set([1,2,3,4,5,6,7,8]);"
- "njs.dump(Buffer.alloc(9).fill(u8))"),
- njs_str("Buffer [1,2,3,4,5,6,7,8,1]") },
-
- { njs_str("Buffer.alloc(513).fill((new Uint8Array(512)).fill(1)).length"),
- njs_str("513") },
-
- { njs_str("Buffer.alloc(4).fill('ABCD', undefined, undefined, 'utf-128')"),
- njs_str("TypeError: \"utf-128\" encoding is not supported") },
-
- { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 3);"
- "buf1.fill('B', 1, 2); njs.dump(buf1)"),
- njs_str("Buffer [66,66]") },
-
- { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 3);"
- "buf1.fill(0x42, 1, 2); njs.dump(buf1)"),
- njs_str("Buffer [66,66]") },
-
- { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 2);"
- "var buf2 = Buffer.from('ABCD').subarray(1, 3);"
- "buf2.fill(buf1, 1, 2); njs.dump(buf2)"),
- njs_str("Buffer [66,66]") },
-
- { njs_str("var buf = Buffer.from('ABCD');"
- "['BC', 'CB', 'ABCD', 'ABCDE', ''].map(v=>buf.indexOf(v))"),
- njs_str("1,-1,0,-1,0") },
-
- { njs_str("var buf = Buffer.from('ABCD');"
- "[0,5,-2,-1].map(v=>buf.indexOf('C', v))"),
- njs_str("2,-1,2,-1") },
-
- { njs_str("var buf = Buffer.from('evil');"
- "buf.indexOf('ZXZpbA==', undefined, 'base64')"),
- njs_str("0") },
-
- { njs_str("var buf = Buffer.from('evil');"
- "buf.indexOf('6576696c', undefined, 'hex')"),
- njs_str("0") },
-
- { njs_str("var buf = Buffer.from('ABCD');"
- "buf.indexOf('C', undefined, 'utf-128')"),
- njs_str("TypeError: \"utf-128\" encoding is not supported") },
-
- { njs_str("var buf = Buffer.from('ABCDABC');"
- "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.indexOf(Buffer.from(v)))"),
- njs_str("1,-1,0,-1,0,2,-1") },
-
- { njs_str("var buf = Buffer.from('ABCDABC');"
- "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.includes(Buffer.from(v)))"),
- njs_str("true,false,true,false,true,true,false") },
-
- { njs_str("var buf = Buffer.from('ZABCDABC').subarray(1);"
- "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.indexOf(Buffer.from(v)))"),
- njs_str("1,-1,0,-1,0,2,-1") },
-
- { njs_str("var buf = Buffer.from('ABCD');"
- "buf.indexOf(0x43)"),
- njs_str("2") },
-
- { njs_str("var buf = Buffer.from('ABCD');"
- "buf.indexOf(0x43, -2)"),
- njs_str("2") },
-
- { njs_str("var buf = Buffer.from('ABCD');"
- "buf.indexOf(0x43, -1)"),
- njs_str("-1") },
-
- { njs_str("var buf1 = Buffer.from('ABCD');"
- "var buf2 = Buffer.from('XXCX').subarray(2, 3);"
- "buf1.indexOf(buf2)"),
- njs_str("2") },
-
- { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 4);"
- "buf1.indexOf(0x43)"),
- njs_str("1") },
-
- { njs_str("var buf1 = Buffer.from('ABCD').subarray(1, 4);"
- "buf1.indexOf('C')"),
- njs_str("1") },
-
- { njs_str("var buf = Buffer.from('ABCDABC');"
- "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(v))"),
- njs_str("5,-1,0,-1,7,6,-1") },
-
- { njs_str("var buf = Buffer.from('ABCDABC');"
- "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(Buffer.from(v)))"),
- njs_str("5,-1,0,-1,7,6,-1") },
-
- { njs_str("var buf = Buffer.from('ZABCDABC').subarray(1);"
- "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(v))"),
- njs_str("5,-1,0,-1,7,6,-1") },
-
- { njs_str("var buf = Buffer.from('ZABCDABC').subarray(1);"
- "['BC', 'CB', 'ABCD', 'ABCDE', '', 'C', 'ABCDABCD'].map(v=>buf.lastIndexOf(Buffer.from(v)))"),
- njs_str("5,-1,0,-1,7,6,-1") },
-
- { njs_str("var buf = Buffer.from('CABCD');"
- "[2,-2,1,-10,10,-5,-4,0].map(v=>buf.lastIndexOf('C', v))"),
- njs_str("0,3,0,-1,3,0,0,0") },
-
- { njs_str("var buf = Buffer.from('CABCD');"
- "[2,-2,1,-10,10,-5,-4,0].map(v=>buf.lastIndexOf(Buffer.from('CZ').subarray(0,1), v))"),
- njs_str("0,3,0,-1,3,0,0,0") },
-
- { njs_str("var buf = Buffer.from('CABCD');"
- "buf.lastIndexOf(0x43)"),
- njs_str("3") },
-
- { njs_str("var buf = Buffer.from('CABCD');"
- "[2,1,0,4,5,-1,-5].map(v=>buf.lastIndexOf(0x43, v))"),
- njs_str("0,0,0,3,3,3,0") },
-
- { njs_str("var buf1 = Buffer.from('ACBCD').subarray(1, 4);"
- "var buf2 = Buffer.from('C');"
- "buf1.lastIndexOf(buf2)"),
- njs_str("2") },
-
- { njs_str("var buf1 = Buffer.from('XXCXX').subarray(2,3);"
- "buf1.lastIndexOf(Buffer.from('X'))"),
- njs_str("-1") },
-
- { njs_str("var buf = Buffer.from('ACBCD').subarray(1, 4);"
- "buf.lastIndexOf(0x43)"),
- njs_str("2") },
-
- { njs_str("var buf = Buffer.from('ACBCD').subarray(1, 4);"
- "buf.lastIndexOf('C')"),
- njs_str("2") },
-
- { njs_str("Buffer.from('abcdef').lastIndexOf('abc', 1)"),
- njs_str("0") },
-
- { njs_str("['swap16', 'swap32', 'swap64'].every(method => {"
- " var buf = Buffer.from([]);"
- " buf[method]();"
- " return njs.dump(buf) === 'Buffer []';"
- "})"),
- njs_str("true") },
-
- { njs_str("['swap16', 'swap32', 'swap64'].every(method => {"
- " var buf = Buffer.from([1,2,3]);"
- " try { buf[method]() } "
- " catch(e) {return e.message === `Buffer size must be a multiple of ${method.substr(4)}-bits`};"
- "})"),
- njs_str("true") },
-
- { njs_str("['swap16', 'swap32', 'swap64'].map(method => {"
- " var buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);"
- " buf[method]();"
- " return njs.dump(buf);"
- "})"),
- njs_str("Buffer [2,1,4,3,6,5,8,7],"
- "Buffer [4,3,2,1,8,7,6,5],"
- "Buffer [8,7,6,5,4,3,2,1]") },
-
- { njs_str("['swap16', 'swap32', 'swap64'].map(method => {"
- " var u8 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8]);"
- " var buf = Buffer.from(u8.buffer, 1);"
- " buf[method]();"
- " return njs.dump(buf);"
- "})"),
- njs_str("Buffer [2,1,4,3,6,5,8,7],"
- "Buffer [4,3,2,1,8,7,6,5],"
- "Buffer [8,7,6,5,4,3,2,1]") },
-
- { njs_str("["
- " [['base64'], 'ZXZpbA=='],"
- " [['base64url'], 'ZXZpbA'],"
- " [['hex'], '6576696c'],"
- " [[undefined,1,3], 'vi'],"
- " [[undefined,5], ''],"
- " [[undefined,undefined,5], 'evil'],"
- " [[undefined,undefined,undefined], 'evil'],"
- "].every(args => {"
- " var buf = Buffer.from('evil');"
- " var as = args[0];"
- " if (buf.toString(as[0], as[1], as[2]) != args[1]) {"
- " throw new TypeError("
- " `buf.toString(${as[0]}, ${as[1]}, ${as[2]}) != ${args[1]}`);"
- " }"
- " return true;"
- "})"),
- njs_str("true") },
-
- { njs_str("var buf = Buffer.allocUnsafe(4);"
- "var len = buf.write('ZXZpbA==', 'base64'); [len, buf]"),
- njs_str("4,evil") },
-
- { njs_str("var buf = Buffer.allocUnsafe(4);"
- "var len = buf.write('ZXZpbA==', undefined, 'base64'); [len, buf]"),
- njs_str("4,evil") },
-
- { njs_str("var buf = Buffer.allocUnsafe(4);"
- "var len = buf.write('ZXZpbA==', undefined, undefined, 'base64'); [len, buf]"),
- njs_str("4,evil") },
-
- { njs_str("Buffer.allocUnsafe(4).write()"),
- njs_str("TypeError: first argument must be a string") },
-
- { njs_str("Buffer.allocUnsafe(4).write({a: 1})"),
- njs_str("TypeError: first argument must be a string") },
-
- { njs_str("Buffer.alloc(4).write('evil', 4, 1);"),
- njs_str("RangeError: \"offset\" is out of range") },
-
- { njs_str("Buffer.alloc(4).write('evil', -1);"),
- njs_str("RangeError: invalid index") },
-
- { njs_str("var buf = Buffer.alloc(4);"
- "var len = buf.write('evil', 3, 1); [len, njs.dump(buf)]"),
- njs_str("1,Buffer [0,0,0,101]") },
-
- { njs_str("var buf = Buffer.alloc(4);"
- "var len = buf.write('evil', 0, 5); [len, buf]"),
- njs_str("4,evil") },
-
- { njs_str("Buffer.alloc(4).write('evil', undefined, -1);"),
- njs_str("RangeError: invalid index") },
-
- { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);"
- "[1,2,3,4,5,6].map(byte => [buf.readUIntLE(0, byte), buf.readUIntLE(1, byte)])"),
- njs_str("250,251,"
- "64506,64763,"
- "16579578,16645371,"
- "4261215226,4278058235,"
- "1095182908410,1099494718715,"
- "281470647991290,274877890034939") },
-
- { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);"
- "[1,2,3,4,5,6].map(byte => [buf.readIntLE(0, byte), buf.readIntLE(1, byte)])"),
- njs_str("-6,-5,"
- "-1030,-773,"
- "-197638,-131845,"
- "-33752070,-16909061,"
- "-4328719366,-16909061,"
- "-4328719366,-6597086675717") },
-
- { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);"
- "[1,2,3,4,5,6].map(byte => [buf.readUIntBE(0, byte), buf.readUIntBE(1, byte)])"),
- njs_str("250,251,"
- "64251,64508,"
- "16448508,16514301,"
- "4210818301,4227661310,"
- "1077969485310,1082281295615,"
- "275960188239615,277064011677689") },
-
- { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);"
- "[1,2,3,4,5,6].map(byte => [buf.readIntBE(0, byte), buf.readIntBE(1, byte)])"),
- njs_str("-6,-5,"
- "-1285,-1028,"
- "-328708,-262915,"
- "-84148995,-67305986,"
- "-21542142466,-17230332161,"
- "-5514788471041,-4410965032967") },
-
- { njs_str("var buf = Buffer.from([0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xF9, 0xf8]);"
- "function t(sign, endianness, offset) { "
- " return [1,2,4].every(size => {"
- " var method = `read${sign}Int${size * 8}`;"
- " if (size > 1) { method += endianness};"
- " var gmethod = `read${sign}Int${endianness}`;"
- " var gv = buf[gmethod](offset, size);"
- " var sv = buf[method](offset);"
- " if (gv != sv) {throw Error(`${gmethod}(${offset},${size}):${gv} != ${method}(${offset}):${sv}`)}"
- " return true;"
- " });"
- "}; "
- "t('U', 'LE', 0) && t('U', 'LE', 1)"
- "&& t('', 'LE', 0) && t('', 'LE', 1)"
- "&& t('U', 'BE', 0) && t('U', 'BE', 1)"
- "&& t('', 'BE', 0) && t('', 'BE', 1)"),
- njs_str("true") },
-
- { njs_str("var buf = Buffer.alloc(9);"
- "function t(sign, endianness, offset) { "
- " return [1,2,4].every(size => {"
- " var rgmethod = `read${sign}Int${endianness}`;"
- " var wgmethod = `write${sign}Int${endianness}`;"
- " var rmethod = `read${sign}Int${size * 8}`;"
- " var wmethod = `write${sign}Int${size * 8}`;"
- " if (size > 1) { rmethod += endianness; wmethod += endianness; };"
- " var v = 0x7abbccddeeff & (size * 8 - 1);"
- ""
- " var ret = buf[wgmethod](v, offset, size);"
- " if(ret !== offset + size) {"
- " throw Error(`${wgmethod} returned ${ret}, need ${offset + size}`);"
- " }"
- ""
- " var gv = buf[rgmethod](offset, size);"
- ""
- " buf.fill(0);"
- " buf[wmethod](v, offset);"
- " var sv = buf[rmethod](offset);"
- " if (gv != sv) {throw Error(`${wmethod}(${v}, ${offset}):${sv} != ${wgmethod}(${v},${offset}):${gv}`)}"
- " return true;"
- " });"
- "}; "
- "t('U', 'LE', 0) && t('U', 'LE', 1)"
- "&& t('', 'LE', 0) && t('', 'LE', 1)"
- "&& t('U', 'BE', 0) && t('U', 'BE', 1)"
- "&& t('', 'BE', 0) && t('', 'BE', 1)"),
- njs_str("true") },
-
- { njs_str(njs_buffer_byte_map("writeUIntLE", "+", 1)),
- njs_str("Buffer [128,0,0,0,0,0],"
- "Buffer [0,64,0,0,0,0],"
- "Buffer [0,0,32,0,0,0],"
- "Buffer [0,0,0,16,0,0],"
- "Buffer [0,0,0,0,8,0],"
- "Buffer [0,0,0,0,0,4]") },
-
- { njs_str(njs_buffer_byte_map("writeUIntBE", "+", 1)),
- njs_str("Buffer [128,0,0,0,0,0],"
- "Buffer [64,0,0,0,0,0],"
- "Buffer [32,0,0,0,0,0],"
- "Buffer [16,0,0,0,0,0],"
- "Buffer [8,0,0,0,0,0],"
- "Buffer [4,0,0,0,0,0]") },
-
- { njs_str(njs_buffer_byte_map("writeIntLE", "-", 2)),
- njs_str("Buffer [192,0,0,0,0,0],"
- "Buffer [0,224,0,0,0,0],"
- "Buffer [0,0,240,0,0,0],"
- "Buffer [0,0,0,248,0,0],"
- "Buffer [0,0,0,0,252,0],"
- "Buffer [0,0,0,0,0,254]") },
-
- { njs_str(njs_buffer_byte_map("writeIntBE", "-", 2)),
- njs_str("Buffer [192,0,0,0,0,0],"
- "Buffer [224,0,0,0,0,0],"
- "Buffer [240,0,0,0,0,0],"
- "Buffer [248,0,0,0,0,0],"
- "Buffer [252,0,0,0,0,0],"
- "Buffer [254,0,0,0,0,0]") },
-
- { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleBE()"),
- njs_str("8.20788039913184e-304") },
-
- { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleLE()"),
- njs_str("5.447603722011605e-270") },
-
- { njs_str("Buffer.from([1, 2, 3, 4]).readFloatBE()"),
- njs_str("2.387939260590663e-38") },
-
- { njs_str("Buffer.from([1, 2, 3, 4]).readFloatLE()"),
- njs_str("1.539989614439558e-36") },
-
- { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleBE(1)"),
- njs_str("RangeError: index 1 is outside the bound of the buffer") },
-
- { njs_str("Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]).readDoubleLE(1)"),
- njs_str("RangeError: index 1 is outside the bound of the buffer") },
-
- { njs_str("Buffer.from([1, 2, 3, 4]).readFloatBE(1)"),
- njs_str("RangeError: index 1 is outside the bound of the buffer") },
-
- { njs_str("Buffer.from([1, 2, 3, 4]).readFloatLE(1)"),
- njs_str("RangeError: index 1 is outside the bound of the buffer") },
-
- { njs_str("var buf = Buffer.allocUnsafe(8);"
- "buf.writeDoubleBE(123.456); njs.dump(buf)"),
- njs_str("Buffer [64,94,221,47,26,159,190,119]") },
-
- { njs_str("var buf = Buffer.allocUnsafe(8);"
- "buf.writeDoubleLE(123.456); njs.dump(buf)"),
- njs_str("Buffer [119,190,159,26,47,221,94,64]") },
-
- { njs_str("var buf = Buffer.allocUnsafe(4);"
- "buf.writeFloatBE(123.456); njs.dump(buf)"),
- njs_str("Buffer [66,246,233,121]") },
-
- { njs_str("var buf = Buffer.allocUnsafe(4);"
- "buf.writeFloatLE(123.456); njs.dump(buf)"),
- njs_str("Buffer [121,233,246,66]") },
-
- { njs_str("var buf = Buffer.allocUnsafe(8).writeDoubleBE(123.456, 1)"),
- njs_str("RangeError: index 1 is outside the bound of the buffer") },
-
- { njs_str("var buf = Buffer.allocUnsafe(8).writeDoubleLE(123.456, 1)"),
- njs_str("RangeError: index 1 is outside the bound of the buffer") },
-
- { njs_str("var buf = Buffer.allocUnsafe(4).writeFloatBE(123.456, 1)"),
- njs_str("RangeError: index 1 is outside the bound of the buffer") },
-
- { njs_str("var buf = Buffer.allocUnsafe(4).writeFloatLE(123.456, 1)"),
- njs_str("RangeError: index 1 is outside the bound of the buffer") },
-
- { njs_str("var buffer = require('buffer');"
- "buffer.Buffer.alloc(5).fill('ABC')"),
- njs_str("ABCAB") },
-
- { njs_str("var buffer = require('buffer');"
- "typeof buffer.kMaxLength === 'number' "),
- njs_str("true") },
-
- { njs_str("var buffer = require('buffer');"
- "typeof buffer.constants.MAX_LENGTH === 'number' "),
- njs_str("true") },
-
- { njs_str("var buffer = require('buffer');"
- "typeof buffer.constants.MAX_STRING_LENGTH === 'number' "),
- njs_str("true") },
-};
-
-
static njs_unit_test_t njs_webcrypto_test[] =
{
/* Statistic test
@@ -24891,12 +24080,6 @@ static njs_test_suite_t njs_suites[] =
njs_nitems(njs_querystring_module_test),
njs_unit_test },
- { njs_str("buffer module"),
- { .repeat = 1, .unsafe = 1 },
- njs_buffer_module_test,
- njs_nitems(njs_buffer_module_test),
- njs_unit_test },
-
{ njs_str("externals"),
{ .externals = 1, .repeat = 1, .unsafe = 1 },
njs_externals_test,
diff --git a/test/buffer.t.js b/test/buffer.t.js
index 1d96d342..55227b3a 100644
--- a/test/buffer.t.js
+++ b/test/buffer.t.js
@@ -1,5 +1,5 @@
/*---
-includes: [compatBuffer.js, runTsuite.js]
+includes: [compatBuffer.js, runTsuite.js, compareArray.js]
flags: [async]
---*/
@@ -10,6 +10,297 @@ function p(args, default_opts) {
return params;
}
+let alloc_tsuite = {
+ name: "Buffer.alloc() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = Buffer.alloc(params.size, params.fill, params.encoding);
+
+ if (r.toString() !== params.expected) {
+ throw Error(`unexpected output "${r.toString()}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: { encoding: 'utf-8' },
+
+ tests: [
+ { size: 3, fill: 0x61, expected: 'aaa' },
+ { size: 3, fill: 'A', expected: 'AAA' },
+ { size: 3, fill: 'ABCD', expected: 'ABC' },
+ { size: 3, fill: '414243', encoding: 'hex', expected: 'ABC' },
+ { size: 4, fill: '414243', encoding: 'hex', expected: 'ABCA' },
+ { size: 3, fill: 'QUJD', encoding: 'base64', expected: 'ABC' },
+ { size: 3, fill: 'QUJD', encoding: 'base64url', expected: 'ABC' },
+ { size: 3, fill: Buffer.from('ABCD'), encoding: 'utf-8', expected: 'ABC' },
+ { size: 3, fill: Buffer.from('ABCD'), encoding: 'utf8', expected: 'ABC' },
+ { size: 3, fill: 'ABCD', encoding: 'utf-128',
+ exception: 'TypeError: "utf-128" encoding is not supported' },
+ { size: 3, fill: Buffer.from('def'), expected: 'def' },
+ ],
+};
+
+
+let byteLength_tsuite = {
+ name: "Buffer.byteLength() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = Buffer.byteLength(params.value, params.encoding);
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: { encoding: 'utf-8' },
+
+ tests: [
+ { value: 'abc', expected: 3 },
+ { value: 'αβγ', expected: 6 },
+ { value: 'αβγ', encoding: 'utf-8', expected: 6 },
+ { value: 'αβγ', encoding: 'utf8', expected: 6 },
+ { value: 'αβγ', encoding: 'utf-128', exception: 'TypeError: "utf-128" encoding is not supported' },
+ { value: '414243', encoding: 'hex', expected: 3 },
+ { value: 'QUJD', encoding: 'base64', expected: 3 },
+ { value: 'QUJD', encoding: 'base64url', expected: 3 },
+ { value: Buffer.from('αβγ'), expected: 6 },
+ { value: Buffer.alloc(3).buffer, expected: 3 },
+ { value: Buffer.from(new Uint8Array([0x60, 0x61, 0x62, 0x63]).buffer, 1), expected: 3 },
+ ],
+};
+
+
+let concat_tsuite = {
+ name: "Buffer.concat() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = Buffer.concat(params.buffers, params.length);
+
+ if (r.toString() !== params.expected) {
+ throw Error(`unexpected output "${r.toString()}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+ tests: [
+ { buffers: [ Buffer.from('abc'),
+ Buffer.from(new Uint8Array([0x64, 0x65, 0x66]).buffer, 1) ],
+ expected: 'abcef' },
+ { buffers: [ Buffer.from('abc'), Buffer.from('def'), Buffer.from('') ],
+ expected: 'abcdef' },
+ { buffers: [ Buffer.from(''), Buffer.from('abc'), Buffer.from('def') ],
+ length: 4, expected: 'abcd' },
+ ],
+};
+
+
+let compare_tsuite = {
+ name: "Buffer.compare() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = Buffer.compare(params.buf1, params.buf2);
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { buf1: Buffer.from('abc'), buf2: Buffer.from('abc'), expected: 0 },
+ { buf1: Buffer.from('abc'),
+ buf2: Buffer.from(new Uint8Array([0x60, 0x61, 0x62, 0x63]).buffer, 1),
+ expected: 0 },
+ { buf1: Buffer.from(new Uint8Array([0x60, 0x61, 0x62, 0x63]).buffer, 1),
+ buf2: Buffer.from('abc'),
+ expected: 0 },
+ { buf1: Buffer.from('abc'), buf2: Buffer.from('def'), expected: -1 },
+ { buf1: Buffer.from('def'), buf2: Buffer.from('abc'), expected: 1 },
+ { buf1: Buffer.from('abc'), buf2: Buffer.from('abcd'), expected: -1 },
+ { buf1: Buffer.from('abcd'), buf2: Buffer.from('abc'), expected: 1 },
+ { buf1: Buffer.from('abc'), buf2: Buffer.from('ab'), expected: 1 },
+ { buf1: Buffer.from('ab'), buf2: Buffer.from('abc'), expected: -1 },
+ { buf1: Buffer.from('abc'), buf2: Buffer.from(''), expected: 1 },
+ { buf1: Buffer.from(''), buf2: Buffer.from('abc'), expected: -1 },
+ { buf1: Buffer.from(''), buf2: Buffer.from(''), expected: 0 },
+ ],
+};
+
+
+let comparePrototype_tsuite = {
+ name: "buf.compare() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = params.buf.compare(params.target, params.tStart, params.tEnd,
+ params.sStart, params.sEnd);
+
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { buf: Buffer.from('abc'), target: Buffer.from('abc'), expected: 0 },
+ { buf: Buffer.from('abc'),
+ target: Buffer.from(new Uint8Array([0x60, 0x61, 0x62, 0x63]).buffer, 1),
+ expected: 0 },
+ { buf: Buffer.from(new Uint8Array([0x60, 0x61, 0x62, 0x63]).buffer, 1),
+ target: Buffer.from('abc'), expected: 0 },
+ { buf: Buffer.from('abc'), target: Buffer.from('def'), expected: -1 },
+ { buf: Buffer.from('def'), target: Buffer.from('abc'), expected: 1 },
+ { buf: Buffer.from('abc'), target: Buffer.from('abcd'), expected: -1 },
+ { buf: Buffer.from('abcd'), target: Buffer.from('abc'), expected: 1 },
+ { buf: Buffer.from('abc'), target: Buffer.from('ab'), expected: 1 },
+ { buf: Buffer.from('ab'), target: Buffer.from('abc'), expected: -1 },
+ { buf: Buffer.from('abc'), target: Buffer.from(''), expected: 1 },
+ { buf: Buffer.from(''), target: Buffer.from('abc'), expected: -1 },
+ { buf: Buffer.from(''), target: Buffer.from(''), expected: 0 },
+
+ { buf: Buffer.from('abcdef'), target: Buffer.from('abc'),
+ sEnd: 3, expected: 0 },
+ { buf: Buffer.from('abcdef'), target: Buffer.from('def'),
+ sStart: 3, expected: 0 },
+ { buf: Buffer.from('abcdef'), target: Buffer.from('abc'),
+ sStart: 0, sEnd: 3, expected: 0 },
+ { buf: Buffer.from('abcdef'), target: Buffer.from('def'),
+ sStart: 3, sEnd: 6, expected: 0 },
+ { buf: Buffer.from('abcdef'), target: Buffer.from('def'),
+ sStart: 3, sEnd: 5, tStart: 0, tEnd: 2, expected: 0 },
+ ],
+};
+
+
+let copy_tsuite = {
+ name: "buf.copy() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = params.buf.copy(params.target, params.tStart, params.sStart, params.sEnd);
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ if (params.target.toString() !== params.expected_buf) {
+ throw Error(`unexpected buf "${params.target.toString()}" != "${params.expected_buf}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { buf: Buffer.from('abcdef'), target: Buffer.from('123456'),
+ expected: 6, expected_buf: 'abcdef' },
+ { buf: Buffer.from('abcdef'), target: Buffer.from('123456'),
+ tStart: 0, expected: 6, expected_buf: 'abcdef' },
+ { buf: Buffer.from('abc'), target: Buffer.from('123456789'),
+ tStart: 5, expected: 3, expected_buf: '12345abc9' },
+ { buf: Buffer.from('abcdef'), target: Buffer.from('123456'),
+ tStart: 0, sStart: 0, expected: 6, expected_buf: 'abcdef' },
+ { buf: Buffer.from('abcdef'), target: Buffer.from('123456'),
+ tStart: 0, sStart: 0, sEnd: 3, expected: 3, expected_buf: 'abc456' },
+ { buf: Buffer.from('abcdef'), target: Buffer.from('123456'),
+ tStart: 2, sStart: 2, sEnd: 3, expected: 1, expected_buf: '12c456' },
+ { buf: Buffer.from('abcdef'), target: Buffer.from('123456'),
+ tStart: 7, exception: 'RangeError: \"targetStart\" is out of bounds' },
+ { buf: Buffer.from('abcdef'), target: Buffer.from('123456'),
+ sStart: 7, exception: 'RangeError: \"sourceStart\" is out of bounds' },
+ ],
+};
+
+
+let equals_tsuite = {
+ name: "buf.equals() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = params.buf1.equals(params.buf2);
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+ tests: [
+
+ { buf1: Buffer.from('abc'), buf2: Buffer.from('abc'), expected: true },
+ { buf1: Buffer.from('abc'),
+ buf2: Buffer.from(new Uint8Array([0x60, 0x61, 0x62, 0x63]).buffer, 1),
+ expected: true },
+ { buf1: Buffer.from(new Uint8Array([0x60, 0x61, 0x62, 0x63]).buffer, 1),
+ buf2: Buffer.from('abc'), expected: true },
+ { buf1: Buffer.from('abc'), buf2: Buffer.from('def'), expected: false },
+ { buf1: Buffer.from('def'), buf2: Buffer.from('abc'), expected: false },
+ { buf1: Buffer.from('abc'), buf2: Buffer.from('abcd'), expected: false },
+ { buf1: Buffer.from('abcd'), buf2: Buffer.from('abc'), expected: false },
+ { buf1: Buffer.from('abc'), buf2: Buffer.from('ab'), expected: false },
+ { buf1: Buffer.from('ab'), buf2: Buffer.from('abc'), expected: false },
+ { buf1: Buffer.from('abc'), buf2: Buffer.from(''), expected: false },
+ { buf1: Buffer.from(''), buf2: Buffer.from('abc'), expected: false },
+ { buf1: Buffer.from(''), buf2: Buffer.from(''), expected: true },
+ ],
+};
+
+
+let fill_tsuite = {
+ name: "buf.fill() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = params.buf.fill(params.value, params.offset, params.end);
+
+ if (r.toString() !== params.expected) {
+ throw Error(`unexpected output "${r.toString()}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+ tests: [
+ { buf: Buffer.from('abc'), value: 0x61, expected: 'aaa' },
+ { buf: Buffer.from('abc'), value: 0x61, expected: 'aaa', offset: 0, end: 3 },
+ { buf: Buffer.from('abc'), value: 0x61, expected: 'abc', offset: 0, end: 0 },
+ { buf: Buffer.from('abc'), value: 'A', expected: 'AAA' },
+ { buf: Buffer.from('abc'), value: 'ABCD', expected: 'ABC' },
+ { buf: Buffer.from('abc'), value: '414243', offset: 'hex', expected: 'ABC' },
+ { buf: Buffer.from('abc'), value: '414243', offset: 'utf-128',
+ exception: 'TypeError: "utf-128" encoding is not supported' },
+ { buf: Buffer.from('abc'), value: 'ABCD', offset: 1, expected: 'aAB' },
+ { buf: Buffer.from('abc'), value: Buffer.from('def'), expected: 'def' },
+ { buf: Buffer.from('def'),
+ value: Buffer.from(new Uint8Array([0x60, 0x61, 0x62, 0x63]).buffer, 1),
+ expected: 'abc' },
+ { buf: Buffer.from(new Uint8Array([0x60, 0x61, 0x62, 0x63]).buffer, 1),
+ value: Buffer.from('def'),
+ expected: 'def' },
+ ],
+};
+
+
let from_tsuite = {
name: "Buffer.from() tests",
skip: () => (!has_buffer()),
@@ -20,6 +311,12 @@ let from_tsuite = {
params.modify(buf);
}
+ if (params.args[0] instanceof ArrayBuffer) {
+ if (buf.buffer !== params.args[0]) {
+ throw Error(`unexpected buffer "${buf.buffer}" != "${params.args[0]}"`);
+ }
+ }
+
let r = buf.toString(params.fmt);
if (r.length !== params.expected.length) {
@@ -48,7 +345,6 @@ let from_tsuite = {
{ args: [(new Uint8Array([0xaa, 0xbb, 0xcc])).buffer, 1, 1], fmt: "hex", expected: 'bb' },
{ args: [(new Uint8Array([0xaa, 0xbb, 0xcc])).buffer, '1', '1'], fmt: "hex", expected: 'bb' },
{ args: [(new Uint8Array([0xaa, 0xbb, 0xcc])).buffer, 1, 0], fmt: "hex", expected: '' },
- { args: [(new Uint8Array([0xaa, 0xbb, 0xcc])).buffer, 1, -1], fmt: "hex", expected: '' },
{ args: [(new Uint8Array([0xaa, 0xbb, 0xcc])).buffer], fmt: "hex",
modify: (buf) => { buf[1] = 0; },
@@ -128,6 +424,68 @@ let from_tsuite = {
{ args: ['QUJDRA#', "base64url"], expected: 'ABCD' },
]};
+
+let includes_tsuite = {
+ name: "buf.includes() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = params.buf.includes(params.value, params.offset, params.encoding);
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { buf: Buffer.from('abcdef'), value: 'abc', expected: true },
+ { buf: Buffer.from('abcdef'), value: 'def', expected: true },
+ { buf: Buffer.from('abcdef'), value: 'abc', offset: 1, expected: false },
+ { buf: Buffer.from('abcdef'), value: {},
+ exception: 'TypeError: "value" argument must be of type string or an instance of Buffer' },
+ ],
+};
+
+
+let indexOf_tsuite = {
+ name: "buf.indexOf() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = params.buf.indexOf(params.value, params.offset, params.encoding);
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { buf: Buffer.from('abcdef'), value: 'abc', expected: 0 },
+ { buf: Buffer.from('abcdef'), value: 'def', expected: 3 },
+ { buf: Buffer.from('abcdef'), value: 'abc', offset: 1, expected: -1 },
+ { buf: Buffer.from('abcdef'), value: 'def', offset: 1, expected: 3 },
+ { buf: Buffer.from('abcdef'), value: 'def', offset: -3, expected: 3 },
+ { buf: Buffer.from('abcdef'), value: '626364', encoding: 'hex', expected: 1 },
+ { buf: Buffer.from('abcdef'), value: '626364', encoding: 'utf-128',
+ exception: 'TypeError: "utf-128" encoding is not supported' },
+ { buf: Buffer.from('abcdef'), value: 0x62, expected: 1 },
+ { buf: Buffer.from('abcabc'), value: 0x61, offset: 1, expected: 3 },
+ { buf: Buffer.from('abcdef'), value: Buffer.from('def'), expected: 3 },
+ { buf: Buffer.from('abcdef'), value: Buffer.from(new Uint8Array([0x60, 0x62, 0x63]).buffer, 1), expected: 1 },
+ { buf: Buffer.from('abcdef'), value: {},
+ exception: 'TypeError: "value" argument must be of type string or an instance of Buffer' },
+ ],
+};
+
+
let isBuffer_tsuite = {
name: "Buffer.isBuffer() tests",
skip: () => (!has_buffer()),
@@ -151,6 +509,33 @@ let isBuffer_tsuite = {
]};
+let isEncoding_tsuite = {
+ name: "Buffer.isEncoding() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = Buffer.isEncoding(params.value);
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { value: 'utf-8', expected: true },
+ { value: 'utf8', expected: true },
+ { value: 'utf-128', expected: false },
+ { value: 'hex', expected: true },
+ { value: 'base64', expected: true },
+ { value: 'base64url', expected: true },
+ ],
+};
+
+
function compare_object(a, b) {
if (a === b) {
return true;
@@ -175,6 +560,264 @@ function compare_object(a, b) {
}
+let lastIndexOf_tsuite = {
+ name: "buf.lastIndexOf() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = params.buf.lastIndexOf(params.value, params.offset, params.encoding);
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { buf: Buffer.from('abcdef'), value: 'abc', expected: 0 },
+ { buf: Buffer.from('abcabc'), value: 'abc', expected: 3 },
+ { buf: Buffer.from('abcdef'), value: 'def', expected: 3 },
+ { buf: Buffer.from('abcdef'), value: 'abc', offset: 1, expected: 0 },
+ { buf: Buffer.from('abcdef'), value: 'def', offset: 1, expected: -1 },
+ { buf: Buffer.from(Buffer.alloc(7).fill('Zabcdef').buffer, 1), value: 'abcdef', expected: 0 },
+ { buf: Buffer.from(Buffer.alloc(7).fill('Zabcdef').buffer, 1), value: 'abcdefg', expected: -1 },
+ { buf: Buffer.from('abcdef'), value: '626364', encoding: 'hex', expected: 1 },
+ { buf: Buffer.from('abcdef'), value: '626364', encoding: 'utf-128',
+ exception: 'TypeError: "utf-128" encoding is not supported' },
+ { buf: Buffer.from('abcabc'), value: 0x61, expected: 3 },
+ { buf: Buffer.from('abcabc'), value: 0x61, offset: 1, expected: 0 },
+ { buf: Buffer.from('abcdef'), value: Buffer.from('def'), expected: 3 },
+ { buf: Buffer.from('abcdef'), value: Buffer.from(new Uint8Array([0x60, 0x62, 0x63]).buffer, 1), expected: 1 },
+ { buf: Buffer.from('abcdef'), value: {},
+ exception: 'TypeError: "value" argument must be of type string or an instance of Buffer' },
+ ],
+};
+
+
+let readXIntXX_tsuite = {
+ name: "buf.readXIntXX() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let b = params.buf;
+ let r = [
+ b.readInt8(params.offset),
+ b.readUInt8(params.offset),
+ b.readInt16LE(params.offset),
+ b.readInt16BE(params.offset),
+ b.readUInt16LE(params.offset),
+ b.readUInt16BE(params.offset),
+ b.readInt32LE(params.offset),
+ b.readInt32BE(params.offset),
+ b.readUInt32LE(params.offset),
+ b.readUInt32BE(params.offset),
+ ];
+
+
+ if (!compareArray(r, params.expected)) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 0,
+ expected: [ -86,170,-17494,-21829,48042,43707,-573785174,-1430532899,3721182122,2864434397 ] },
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 1,
+ expected: [ -69,187,-13125,-17460,52411,48076,-287454021,-1144201746,4007513275,3150765550 ] },
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 2,
+ expected: [ -52,204,-8756,-13091,56780,52445,-1122868,-857870593,4293844428,3437096703 ] },
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 3,
+ exception: 'RangeError: Index out of range' },
+ ],
+};
+
+
+let readFloat_tsuite = {
+ name: "buf.readFloat() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let b = Buffer.alloc(9);
+ let r = b.writeFloatLE(123.125, 0);
+ if (r !== 4) {
+ throw Error(`unexpected output "${r}" != "4"`);
+ }
+
+ if (b.readFloatLE(0) !== 123.125) {
+ throw Error(`unexpected output "${b.readFloatLE(0)}" != "123.125"`);
+ }
+
+ r = b.writeFloatBE(123.125, 0);
+ if (r !== 4) {
+ throw Error(`unexpected output "${r}" != "4"`);
+ }
+
+ if (b.readFloatBE(0) !== 123.125) {
+ throw Error(`unexpected output "${b.readFloatBE(0)}" != "123.125"`);
+ }
+
+ r = b.writeDoubleLE(123.125, 1);
+ if (r !== 9) {
+ throw Error(`unexpected output "${r}" != "9"`);
+ }
+
+ if (b.readDoubleLE(1) !== 123.125) {
+ throw Error(`unexpected output "${b.readDoubleLE(1)}" != "123.125"`);
+ }
+
+ r = b.writeDoubleBE(123.125, 1);
+ if (r !== 9) {
+ throw Error(`unexpected output "${r}" != "9"`);
+ }
+
+ if (b.readDoubleBE(1) !== 123.125) {
+ throw Error(`unexpected output "${b.readDoubleBE(1)}" != "123.125"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ {}
+ ],
+};
+
+
+let readGeneric_tsuite = {
+ name: "buf.readGeneric() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let b = params.buf;
+ let r = [
+ b.readUIntLE(params.offset, params.length),
+ b.readUIntBE(params.offset, params.length),
+ b.readIntLE(params.offset, params.length),
+ b.readIntBE(params.offset, params.length),
+ ];
+
+
+ if (!compareArray(r, params.expected)) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 0, length: 1,
+ expected: [ 170, 170, -86, -86 ] },
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 1, length: 2,
+ expected: [ 52411,48076,-13125,-17460 ] },
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 2, length: 3,
+ expected: [ 15654348,13426158,-1122868,-3351058 ] },
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 3, length: 4,
+ exception: 'RangeError: Index out of range' },
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 0, length: 0,
+ exception: 'RangeError: byteLength must be <= 6' },
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 0, length: 5,
+ expected: [ 1025923398570,733295205870,-73588229206,-366216421906 ] },
+ { buf: Buffer.from([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), offset: 0, length: 6,
+ expected: [ 281401388481450,187723572702975,-73588229206,-93751404007681 ] },
+ ],
+};
+
+
+let slice_tsuite = {
+ name: "buf.slice() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = params.buf.slice(params.start, params.end);
+
+ if (r.toString() !== params.expected) {
+ throw Error(`unexpected output "${r.toString()}" != "${params.expected}"`);
+ }
+
+ params.buf[2] = 0x5a;
+
+ if (r.constructor.name !== 'Buffer' || r.__proto__ !== params.buf.__proto__) {
+ throw Error(`unexpected output "${r.constructor.name}" != "Buffer"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { buf: Buffer.from('abcdef'), start: 1, expected: 'bcdef' },
+ { buf: Buffer.from('abcdef'), start: 1, end: 3, expected: 'bc' },
+ ],
+};
+
+
+let subarray_tsuite = {
+ name: "buf.subarray() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = params.buf.subarray(params.start, params.end);
+
+ params.buf[0] = 0x5a;
+
+ if (r.toString() !== params.expected) {
+ throw Error(`unexpected output "${r.toString()}" != "${params.expected}"`);
+ }
+
+ if (r.constructor.name !== 'Buffer' || r.__proto__ !== params.buf.__proto__) {
+ throw Error(`unexpected output "${r.constructor.name}" != "Buffer"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { buf: Buffer.from('abcdef'), start: 0, end: 3, expected: 'Zbc' },
+ { buf: Buffer.from('abcdef'), start: 1, expected: 'bcdef' },
+ ],
+};
+
+
+let swap_tsuite = {
+ name: "buf.swap() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let r = Buffer.from(params.value, 'hex')[params.swap]();
+
+ if (r.toString('hex') !== params.expected) {
+ throw Error(`unexpected output "${r.toString('hex')}" != "${params.expected}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: { swap: 'swap16' },
+
+ tests: [
+ { value: '01020304', expected: '02010403' },
+ { value: '010203', exception: 'RangeError: Buffer size must be a multiple of 2' },
+ { value: 'aabbccddeeff0011', swap: 'swap32', expected: 'ddccbbaa1100ffee' },
+ { value: 'aabbcc', swap: 'swap32', exception: 'RangeError: Buffer size must be a multiple of 4' },
+ { value: 'aabbccddeeff00112233445566778899', swap: 'swap64', expected: '1100ffeeddccbbaa9988776655443322' },
+ ],
+};
+
+
let toJSON_tsuite = {
name: "Buffer.toJSON() tests",
skip: () => (!has_buffer()),
@@ -224,13 +867,181 @@ let toString_tsuite = {
{ value: new Uint8Array([0xff, 0xde, 0xba]), fmt: "hex", expected: 'ffdeba' },
{ value: new Uint8Array([0xff, 0xde, 0xba]), fmt: "base64", expected: '/966' },
{ value: new Uint8Array([0xff, 0xde, 0xba]), fmt: "base64url", expected: '_966' },
+ { value: "ABCD", fmt: "base64", expected: 'QUJDRA==' },
+ { value: "ABCD", fmt: "base64url", expected: 'QUJDRA' },
{ value: '', fmt: "utf-128", exception: 'TypeError: "utf-128" encoding is not supported' },
]};
+
+let write_tsuite = {
+ name: "buf.write() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let b = Buffer.alloc(10).fill('Z');
+ let r;
+
+ if (typeof params.offset != 'undefined' && typeof params.length != 'undefined') {
+ r = b.write(params.value, params.offset, params.length, params.encoding);
+
+ } else if (typeof params.offset != 'undefined') {
+ r = b.write(params.value, params.offset, params.encoding);
+
+ } else {
+ r = b.write(params.value, params.encoding);
+ }
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ if (b.toString() !== params.expected_buf) {
+ throw Error(`unexpected output "${b.toString()}" != "${params.expected_buf}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { value: 'abc', expected: 3, expected_buf: 'abcZZZZZZZ' },
+ { value: 'abc', offset: 1, expected: 3, expected_buf: 'ZabcZZZZZZ' },
+ { value: 'abc', offset: 1, length: 2, expected: 2, expected_buf: 'ZabZZZZZZZ' },
+ { value: 'αβγ', offset: 1, expected: 6, expected_buf: 'ZαβγZZZ' },
+ { value: 'αβγ', offset: 1, length: 1, expected: 0, expected_buf: 'ZZZZZZZZZZ' },
+ { value: 'αβγ', offset: 1, length: 2, expected: 2, expected_buf: 'ZαZZZZZZZ' },
+ { value: '414243', encoding: 'hex', expected: 3, expected_buf: 'ABCZZZZZZZ' },
+ { value: '414243', encoding: 'hex', offset: 8, expected: 2, expected_buf: 'ZZZZZZZZAB' },
+ { value: "x".repeat(12), expected: 10, expected_buf: 'xxxxxxxxxx' },
+ { value: "x".repeat(12), offset: 1, expected: 9, expected_buf: 'Zxxxxxxxxx' },
+ { value: "x", offset: 1, length: 2, encoding: 'utf-128',
+ exception: 'TypeError: "utf-128" encoding is not supported' },
+ { value: "x".repeat(10), offset: 10, expected: 0, expected_buf: 'ZZZZZZZZZZ' },
+ { value: "x".repeat(10), offset: 11, exception: 'RangeError: Index out of range' },
+ ],
+};
+
+
+let writeXIntXX_tsuite = {
+ name: "buf.writeXIntXX() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let b = Buffer.alloc(10).fill('Z');
+ let r = b[params.write](params.value, params.offset);
+
+ if (params.exception) {
+ throw Error(`expected exception "${params.exception}"`);
+ }
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ if (b.toString('hex') !== params.expected_buf) {
+ throw Error(`unexpected output "${b.toString('hex')}" != "${params.expected_buf}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { write: 'writeInt8', value: 0xaa, exception: 'RangeError: Index out of range' },
+ { write: 'writeInt8', value: 0x00, offset: 3, expected: 4, expected_buf: '5a5a5a005a5a5a5a5a5a' },
+ { write: 'writeUInt8', value: 0xaa, offset: 0, expected: 1, expected_buf: 'aa5a5a5a5a5a5a5a5a5a' },
+ { write: 'writeInt16LE', value: 0xaabb, exception: 'RangeError: Index out of range' },
+ { write: 'writeInt16BE', value: 0x7788, offset: 1, expected: 3, expected_buf: '5a77885a5a5a5a5a5a5a' },
+ { write: 'writeUInt16LE', value: 0xaabb, offset: 0, expected: 2, expected_buf: 'bbaa5a5a5a5a5a5a5a5a' },
+ { write: 'writeUInt16BE', value: 0x7788, offset: 1, expected: 3, expected_buf: '5a77885a5a5a5a5a5a5a' },
+ { write: 'writeInt32LE', value: 0xaabbccdd, exception: 'RangeError: Index out of range' },
+ { write: 'writeInt32BE', value: 0x778899aa, offset: 1, expected: 5, expected_buf: '5a778899aa5a5a5a5a5a' },
+ { write: 'writeUInt32LE', value: 0xaabbccdd, offset: 0, expected: 4, expected_buf: 'ddccbbaa5a5a5a5a5a5a' },
+ { write: 'writeUInt32BE', value: 0x778899aa, offset: 1, expected: 5, expected_buf: '5a778899aa5a5a5a5a5a' },
+ ],
+};
+
+
+let writeGeneric_tsuite = {
+ name: "buf.writeGeneric() tests",
+ skip: () => (!has_buffer()),
+ T: async (params) => {
+ let b = Buffer.alloc(10).fill('Z');
+ let r = b[params.write](params.value, params.offset, params.length);
+
+ if (params.exception) {
+ throw Error(`expected exception "${params.exception}"`);
+ }
+
+ if (r !== params.expected) {
+ throw Error(`unexpected output "${r}" != "${params.expected}"`);
+ }
+
+ if (b.toString('hex') !== params.expected_buf) {
+ throw Error(`unexpected output "${b.toString('hex')}" != "${params.expected_buf}"`);
+ }
+
+ return 'SUCCESS';
+ },
+
+ prepare_args: p,
+ opts: {},
+
+ tests: [
+ { write: 'writeUIntLE', value: 0xaa, length: 1,
+ exception: 'RangeError: Index out of range' },
+ { write: 'writeUIntLE', value: 0x44, length: 1, offset: 3,
+ expected: 4, expected_buf: '5a5a5a445a5a5a5a5a5a' },
+ { write: 'writeUIntBE', value: 0xaabb, length: 2, offset: 0,
+ expected: 2, expected_buf: 'aabb5a5a5a5a5a5a5a5a' },
+ { write: 'writeUIntBE', value: 0x7788, length: 2, offset: 1,
+ expected: 3, expected_buf: '5a77885a5a5a5a5a5a5a' },
+ { write: 'writeIntLE', value: 0x445566, length: 3, offset: 5,
+ expected: 8, expected_buf: '5a5a5a5a5a6655445a5a' },
+ { write: 'writeIntBE', value: 0x778899, length: 3, offset: 1,
+ expected: 4, expected_buf: '5a7788995a5a5a5a5a5a' },
+ { write: 'writeIntLE', value: 0x44556677, length: 4, offset: 5,
+ expected: 9, expected_buf: '5a5a5a5a5a776655445a' },
+ { write: 'writeIntBE', value: 0xaabbccdd, length: 4, offset: 1,
+ exception: 'RangeError: Index out of range' },
+ { write: 'writeUIntLE', value: 0xaabbccddee, length: 5, offset: 0,
+ expected: 5, expected_buf: 'eeddccbbaa5a5a5a5a5a' },
+ { write: 'writeUIntBE', value: 0x778899aabbcc, length: 6, offset: 1,
+ expected: 7, expected_buf: '5a778899aabbcc5a5a5a' },
+ { write: 'writeUIntBE', value: 0, length: 7,
+ exception: 'The value of "byteLength" is out of range' },
+
+ ],
+};
+
+
run([
+ alloc_tsuite,
+ byteLength_tsuite,
+ concat_tsuite,
+ compare_tsuite,
+ comparePrototype_tsuite,
+ copy_tsuite,
+ equals_tsuite,
+ fill_tsuite,
from_tsuite,
+ includes_tsuite,
+ indexOf_tsuite,
isBuffer_tsuite,
+ isEncoding_tsuite,
+ lastIndexOf_tsuite,
+ readXIntXX_tsuite,
+ readFloat_tsuite,
+ readGeneric_tsuite,
+ slice_tsuite,
+ subarray_tsuite,
+ swap_tsuite,
toJSON_tsuite,
toString_tsuite,
+ write_tsuite,
+ writeXIntXX_tsuite,
+ writeGeneric_tsuite,
])
.then($DONE, $DONE);
diff --git a/test/harness/runTsuite.js b/test/harness/runTsuite.js
index dc2034fd..aa3f5c0f 100644
--- a/test/harness/runTsuite.js
+++ b/test/harness/runTsuite.js
@@ -48,6 +48,9 @@ function merge(to, from) {
} else if (from[v] instanceof Uint8Array) {
r[v] = new Uint8Array(from[v]);
+ } else if (from[v] instanceof ArrayBuffer) {
+ r[v] = new ArrayBuffer(from[v].byteLength);
+
} else {
r[v] = Object.assign(Array.isArray(from[v]) ? [] : {}, from[v]);
}
More information about the nginx-devel
mailing list