diff --git a/api-test.c b/api-test.c index 7aa7dc8a6..a45dfb3ac 100644 --- a/api-test.c +++ b/api-test.c @@ -956,6 +956,68 @@ static void immutable_array_buffer(void) JS_FreeRuntime(rt); } +static void *sab_test_alloc(void *opaque, size_t size) +{ + return malloc(size); +} + +static void sab_test_free(void *opaque, void *ptr) +{ + free(ptr); +} + +static void shared_array_buffer_growth(void) +{ + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + JSValue ret, exception; + + ret = eval(ctx, "new SharedArrayBuffer(16)"); + assert(!JS_IsException(ret)); + JS_FreeValue(ctx, ret); + + ret = eval(ctx, + "const sab = new SharedArrayBuffer(16, { maxByteLength: 16 });" + "sab.grow(16);" + "sab.byteLength === 16 && sab.maxByteLength === 16"); + assert(!JS_IsException(ret)); + assert(JS_IsBool(ret)); + assert(JS_VALUE_GET_BOOL(ret)); + JS_FreeValue(ctx, ret); + + ret = eval(ctx, "new SharedArrayBuffer(16, { maxByteLength: 16384 })"); + assert(JS_IsException(ret)); + assert(JS_HasException(ctx)); + exception = JS_GetException(ctx); + assert(JS_IsError(exception)); + JS_FreeValue(ctx, exception); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + + JSSharedArrayBufferFunctions funcs = { + .sab_alloc = sab_test_alloc, + .sab_free = sab_test_free, + .sab_dup = NULL, + .sab_opaque = NULL, + }; + + rt = new_runtime(); + JS_SetSharedArrayBufferFunctions(rt, &funcs); + ctx = JS_NewContext(rt); + ret = eval(ctx, + "const sab = new SharedArrayBuffer(16, { maxByteLength: 16384 });" + "const u8 = new Uint8Array(sab);" + "sab.grow(16384);" + "u8[1024] === 0 && u8.byteLength === 16384"); + assert(!JS_IsException(ret)); + assert(JS_IsBool(ret)); + assert(JS_VALUE_GET_BOOL(ret)); + JS_FreeValue(ctx, ret); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + static void get_uint8array(void) { JSRuntime *rt = new_runtime(); @@ -1088,6 +1150,7 @@ int main(void) global_object_prototype(); slice_string_tocstring(); immutable_array_buffer(); + shared_array_buffer_growth(); get_uint8array(); new_symbol(); return 0; diff --git a/quickjs.c b/quickjs.c index 38a724fbb..11caae0e3 100644 --- a/quickjs.c +++ b/quickjs.c @@ -57748,6 +57748,13 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, JS_ThrowRangeError(ctx, "invalid max array buffer length"); goto fail; } + if (alloc_flag && class_id == JS_CLASS_SHARED_ARRAY_BUFFER && max_len && + *max_len > len && !rt->sab_funcs.sab_alloc) { + JS_ThrowTypeError(ctx, + "growable SharedArrayBuffer requires " + "SAB allocator hooks"); + goto fail; + } abuf = js_malloc(ctx, sizeof(*abuf)); if (!abuf) goto fail;