Skip to content

Commit

Permalink
Implement ArrayBuffer.prototype.transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy committed Nov 21, 2023
1 parent b56a82d commit 10d173f
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 1 deletion.
62 changes: 62 additions & 0 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -47230,6 +47230,19 @@ static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx)
return JS_ThrowTypeError(ctx, "ArrayBuffer is detached");
}

// #sec-get-arraybuffer.prototype.detached
static JSValue js_array_buffer_get_detached(JSContext *ctx,
JSValueConst this_val,
int class_id)
{
JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id);
if (!abuf)
return JS_EXCEPTION;
if (abuf->shared)
return JS_ThrowTypeError(ctx, "detached called on SharedArrayBuffer");
return JS_NewBool(ctx, abuf->detached);
}

static JSValue js_array_buffer_get_byteLength(JSContext *ctx,
JSValueConst this_val,
int class_id)
Expand All @@ -47241,6 +47254,16 @@ static JSValue js_array_buffer_get_byteLength(JSContext *ctx,
return JS_NewUint32(ctx, abuf->byte_length);
}

/* WARNING: 'p' must be an array buffer */
static void array_buffer_transfer_detached(JSContext *ctx, JSArrayBuffer *abuf)
{
if (!abuf->detached) {
abuf->data = NULL;
abuf->byte_length = 0;
abuf->detached = TRUE;
}
}

void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj)
{
JSArrayBuffer *abuf = JS_GetOpaque(obj, JS_CLASS_ARRAY_BUFFER);
Expand Down Expand Up @@ -47302,6 +47325,42 @@ uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj)
return NULL;
}

// ES #sec-arraybuffer.prototype.transfer
static JSValue js_array_buffer_transfer(JSContext *ctx,
JSValueConst this_val,
int argc, JSValueConst *argv, int class_id)
{
JSArrayBuffer *abuf;
uint64_t new_len;
uint8_t *bs;

abuf = JS_GetOpaque2(ctx, this_val, class_id);
if (!abuf)
return JS_EXCEPTION;
if (abuf->shared)
return JS_ThrowTypeError(ctx, "cannot transfer a SharedArrayBuffer");
if (argc < 1 || JS_IsUndefined(argv[0]))
new_len = abuf->byte_length;
else if (JS_ToIndex(ctx, &new_len, argv[0]))
return JS_EXCEPTION;
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
bs = abuf->data;
/* create an empty AB */
if (new_len == 0) {
JS_DetachArrayBuffer(ctx, this_val);
return js_array_buffer_constructor2(ctx, JS_UNDEFINED, 0, class_id);
}
array_buffer_transfer_detached(ctx, abuf);
/* If length mismatch, realloc. Otherwise, use the same backing buffer. */
if (new_len != abuf->byte_length)
bs = js_realloc(ctx, bs, new_len);
return js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len,
JS_CLASS_ARRAY_BUFFER,
bs, abuf->free_func,
NULL, FALSE);
}

static JSValue js_array_buffer_slice(JSContext *ctx,
JSValueConst this_val,
int argc, JSValueConst *argv, int class_id)
Expand Down Expand Up @@ -47370,7 +47429,10 @@ static JSValue js_array_buffer_slice(JSContext *ctx,

static const JSCFunctionListEntry js_array_buffer_proto_funcs[] = {
JS_CGETSET_MAGIC_DEF("byteLength", js_array_buffer_get_byteLength, NULL, JS_CLASS_ARRAY_BUFFER ),
JS_CGETSET_MAGIC_DEF("detached", js_array_buffer_get_detached, NULL, JS_CLASS_ARRAY_BUFFER ),
JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_ARRAY_BUFFER ),
JS_CFUNC_MAGIC_DEF("transfer", 0, js_array_buffer_transfer, JS_CLASS_ARRAY_BUFFER ),
JS_CFUNC_MAGIC_DEF("transferToFixedLength", 0, js_array_buffer_transfer, JS_CLASS_ARRAY_BUFFER ),
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "ArrayBuffer", JS_PROP_CONFIGURABLE ),
};

Expand Down
2 changes: 1 addition & 1 deletion test262.conf
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Array.prototype.flatten
Array.prototype.includes
Array.prototype.values
ArrayBuffer
arraybuffer-transfer=skip
arraybuffer-transfer
arrow-function
async-functions
async-iteration
Expand Down

0 comments on commit 10d173f

Please sign in to comment.