Skip to content

Commit 6c1af9d

Browse files
authored
Implement immutable ArrayBuffers (#1331)
The TC39 proposal is at stage 2.7 but it seems useful, isn't very hard to add, and interacts with the stage 4 uint8array-base64 proposal that I plan to implement sometime Real Soon Now.
1 parent 2c307d2 commit 6c1af9d

File tree

3 files changed

+147
-18
lines changed

3 files changed

+147
-18
lines changed

quickjs.c

Lines changed: 124 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ typedef struct JSArrayBuffer {
841841
int byte_length; /* 0 if detached */
842842
int max_byte_length; /* -1 if not resizable; >= byte_length otherwise */
843843
uint8_t detached;
844+
uint8_t immutable;
844845
uint8_t shared; /* if shared, the array buffer cannot be detached */
845846
uint8_t *data; /* NULL if detached */
846847
struct list_head array_list;
@@ -1342,9 +1343,11 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx,
13421343
JSValueConst src_obj,
13431344
int classid, uint32_t len);
13441345
static bool is_typed_array(JSClassID class_id);
1346+
static bool typed_array_is_immutable(JSObject *p);
13451347
static bool typed_array_is_oob(JSObject *p);
13461348
static uint32_t typed_array_length(JSObject *p);
13471349
static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx);
1350+
static JSValue JS_ThrowTypeErrorImmutableArrayBuffer(JSContext *ctx);
13481351
static JSValue JS_ThrowTypeErrorArrayBufferOOB(JSContext *ctx);
13491352
static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx,
13501353
bool is_arg);
@@ -9182,6 +9185,10 @@ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc,
91829185
if (desc) {
91839186
desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE |
91849187
JS_PROP_CONFIGURABLE;
9188+
if (is_typed_array(p->class_id) && typed_array_is_immutable(p)) {
9189+
desc->flags &= ~JS_PROP_WRITABLE;
9190+
desc->flags &= ~JS_PROP_CONFIGURABLE;
9191+
}
91859192
desc->getter = JS_UNDEFINED;
91869193
desc->setter = JS_UNDEFINED;
91879194
desc->value = JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);
@@ -10180,6 +10187,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
1018010187
case JS_CLASS_UINT8C_ARRAY:
1018110188
if (JS_ToUint8ClampFree(ctx, &v, val))
1018210189
goto ta_cvt_fail;
10190+
if (typed_array_is_immutable(p))
10191+
goto ta_immutable;
1018310192
/* Note: the conversion can detach the typed array, so the
1018410193
array bound check must be done after */
1018510194
if (unlikely(idx >= (uint32_t)p->u.array.count))
@@ -10190,6 +10199,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
1019010199
case JS_CLASS_UINT8_ARRAY:
1019110200
if (JS_ToInt32Free(ctx, &v, val))
1019210201
goto ta_cvt_fail;
10202+
if (typed_array_is_immutable(p))
10203+
goto ta_immutable;
1019310204
if (unlikely(idx >= (uint32_t)p->u.array.count))
1019410205
goto ta_out_of_bound;
1019510206
p->u.array.u.uint8_ptr[idx] = v;
@@ -10198,6 +10209,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
1019810209
case JS_CLASS_UINT16_ARRAY:
1019910210
if (JS_ToInt32Free(ctx, &v, val))
1020010211
goto ta_cvt_fail;
10212+
if (typed_array_is_immutable(p))
10213+
goto ta_immutable;
1020110214
if (unlikely(idx >= (uint32_t)p->u.array.count))
1020210215
goto ta_out_of_bound;
1020310216
p->u.array.u.uint16_ptr[idx] = v;
@@ -10206,6 +10219,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
1020610219
case JS_CLASS_UINT32_ARRAY:
1020710220
if (JS_ToInt32Free(ctx, &v, val))
1020810221
goto ta_cvt_fail;
10222+
if (typed_array_is_immutable(p))
10223+
goto ta_immutable;
1020910224
if (unlikely(idx >= (uint32_t)p->u.array.count))
1021010225
goto ta_out_of_bound;
1021110226
p->u.array.u.uint32_ptr[idx] = v;
@@ -10217,6 +10232,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
1021710232
int64_t v;
1021810233
if (JS_ToBigInt64Free(ctx, &v, val))
1021910234
goto ta_cvt_fail;
10235+
if (typed_array_is_immutable(p))
10236+
goto ta_immutable;
1022010237
if (unlikely(idx >= (uint32_t)p->u.array.count))
1022110238
goto ta_out_of_bound;
1022210239
p->u.array.u.uint64_ptr[idx] = v;
@@ -10225,13 +10242,17 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
1022510242
case JS_CLASS_FLOAT16_ARRAY:
1022610243
if (JS_ToFloat64Free(ctx, &d, val))
1022710244
goto ta_cvt_fail;
10245+
if (typed_array_is_immutable(p))
10246+
goto ta_immutable;
1022810247
if (unlikely(idx >= (uint32_t)p->u.array.count))
1022910248
goto ta_out_of_bound;
1023010249
p->u.array.u.fp16_ptr[idx] = tofp16(d);
1023110250
break;
1023210251
case JS_CLASS_FLOAT32_ARRAY:
1023310252
if (JS_ToFloat64Free(ctx, &d, val))
1023410253
goto ta_cvt_fail;
10254+
if (typed_array_is_immutable(p))
10255+
goto ta_immutable;
1023510256
if (unlikely(idx >= (uint32_t)p->u.array.count))
1023610257
goto ta_out_of_bound;
1023710258
p->u.array.u.float_ptr[idx] = d;
@@ -10245,6 +10266,10 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
1024510266
}
1024610267
return -1;
1024710268
}
10269+
if (typed_array_is_immutable(p)) {
10270+
ta_immutable:
10271+
return false;
10272+
}
1024810273
if (unlikely(idx >= (uint32_t)p->u.array.count)) {
1024910274
ta_out_of_bound:
1025010275
if (typed_array_is_oob(p))
@@ -55442,6 +55467,7 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx,
5544255467
}
5544355468
init_list_head(&abuf->array_list);
5544455469
abuf->detached = false;
55470+
abuf->immutable = false;
5544555471
abuf->shared = (class_id == JS_CLASS_SHARED_ARRAY_BUFFER);
5544655472
abuf->opaque = opaque;
5544755473
abuf->free_func = free_func;
@@ -55611,6 +55637,11 @@ static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx)
5561155637
return JS_ThrowTypeError(ctx, "ArrayBuffer is detached");
5561255638
}
5561355639

55640+
static JSValue JS_ThrowTypeErrorImmutableArrayBuffer(JSContext *ctx)
55641+
{
55642+
return JS_ThrowTypeError(ctx, "ArrayBuffer is immutable");
55643+
}
55644+
5561455645
static JSValue JS_ThrowTypeErrorArrayBufferOOB(JSContext *ctx)
5561555646
{
5561655647
return JS_ThrowTypeError(ctx, "ArrayBuffer is detached or resized");
@@ -55628,6 +55659,15 @@ static JSValue js_array_buffer_get_detached(JSContext *ctx,
5562855659
return js_bool(abuf->detached);
5562955660
}
5563055661

55662+
static JSValue js_array_buffer_get_immutable(JSContext *ctx,
55663+
JSValueConst this_val)
55664+
{
55665+
JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_BUFFER);
55666+
if (!abuf)
55667+
return JS_EXCEPTION;
55668+
return js_bool(abuf->immutable);
55669+
}
55670+
5563155671
static JSValue js_array_buffer_get_byteLength(JSContext *ctx,
5563255672
JSValueConst this_val,
5563355673
int class_id)
@@ -55764,28 +55804,38 @@ static void js_array_buffer_update_typed_arrays(JSArrayBuffer *abuf)
5576455804
}
5576555805
}
5576655806

55807+
enum {
55808+
JS_ARRAY_BUFFER_TRANSFER,
55809+
JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE,
55810+
JS_ARRAY_BUFFER_TRANSFER_TO_FIXED_LENGTH,
55811+
};
55812+
5576755813
// ES #sec-arraybuffer.prototype.transfer
5576855814
static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val,
5576955815
int argc, JSValueConst *argv, int magic)
5577055816
{
55771-
bool transfer_to_fixed_length = magic & 1;
5577255817
JSArrayBuffer *abuf;
5577355818
uint64_t new_len, old_len, max_len, *pmax_len;
5577455819
uint8_t *bs, *new_bs;
55820+
JSValue ret;
5577555821

5577655822
abuf = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_BUFFER);
5577755823
if (!abuf)
5577855824
return JS_EXCEPTION;
5577955825
if (abuf->shared)
5578055826
return JS_ThrowTypeError(ctx, "cannot transfer a SharedArrayBuffer");
55827+
if (magic == JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE && abuf->immutable)
55828+
return JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
5578155829
if (argc < 1 || JS_IsUndefined(argv[0]))
5578255830
new_len = abuf->byte_length;
5578355831
else if (JS_ToIndex(ctx, &new_len, argv[0]))
5578455832
return JS_EXCEPTION;
55833+
if (magic != JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE && abuf->immutable)
55834+
return JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
5578555835
if (abuf->detached)
5578655836
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
5578755837
pmax_len = NULL;
55788-
if (!transfer_to_fixed_length) {
55838+
if (magic == JS_ARRAY_BUFFER_TRANSFER) {
5578955839
if (array_buffer_is_resizable(abuf)) { // carry over maxByteLength
5579055840
max_len = abuf->max_byte_length;
5579155841
if (new_len > max_len)
@@ -55798,8 +55848,9 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val,
5579855848
/* create an empty AB */
5579955849
if (new_len == 0) {
5580055850
JS_DetachArrayBuffer(ctx, this_val);
55801-
return js_array_buffer_constructor2(ctx, JS_UNDEFINED, 0, pmax_len,
55802-
JS_CLASS_ARRAY_BUFFER);
55851+
ret = js_array_buffer_constructor2(ctx, JS_UNDEFINED, 0, pmax_len,
55852+
JS_CLASS_ARRAY_BUFFER);
55853+
goto fini;
5580355854
}
5580455855
bs = abuf->data;
5580555856
old_len = abuf->byte_length;
@@ -55817,10 +55868,20 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val,
5581755868
abuf->byte_length = 0;
5581855869
abuf->detached = true;
5581955870
js_array_buffer_update_typed_arrays(abuf);
55820-
return js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len, pmax_len,
55821-
JS_CLASS_ARRAY_BUFFER,
55822-
bs, abuf->free_func,
55823-
NULL, false);
55871+
ret = js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len, pmax_len,
55872+
JS_CLASS_ARRAY_BUFFER, bs,
55873+
abuf->free_func, NULL,
55874+
/*alloc_flag*/false);
55875+
fini:
55876+
if (magic == JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE) {
55877+
if (JS_IsException(ret))
55878+
return JS_EXCEPTION;
55879+
abuf = JS_GetOpaque2(ctx, ret, JS_CLASS_ARRAY_BUFFER);
55880+
if (!abuf)
55881+
return JS_EXCEPTION;
55882+
abuf->immutable = true;
55883+
}
55884+
return ret;
5582455885
}
5582555886

5582655887
static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val,
@@ -55833,6 +55894,8 @@ static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val,
5583355894
abuf = JS_GetOpaque2(ctx, this_val, class_id);
5583455895
if (!abuf)
5583555896
return JS_EXCEPTION;
55897+
if (abuf->immutable)
55898+
return JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
5583655899
if (JS_ToInt64(ctx, &len, argv[0]))
5583755900
return JS_EXCEPTION;
5583855901
if (abuf->detached)
@@ -55875,17 +55938,23 @@ static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val,
5587555938

5587655939
static JSValue js_array_buffer_slice(JSContext *ctx,
5587755940
JSValueConst this_val,
55878-
int argc, JSValueConst *argv, int class_id)
55941+
int argc, JSValueConst *argv, int magic)
5587955942
{
5588055943
JSArrayBuffer *abuf, *new_abuf;
5588155944
int64_t len, start, end, new_len;
5588255945
JSValue ctor, new_obj;
55946+
bool immutable;
55947+
int class_id;
5588355948

55949+
immutable = magic & 1;
55950+
class_id = magic >> 1;
5588455951
abuf = JS_GetOpaque2(ctx, this_val, class_id);
5588555952
if (!abuf)
5588655953
return JS_EXCEPTION;
5588755954
if (abuf->detached)
5588855955
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
55956+
if (abuf->immutable)
55957+
return JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
5588955958
len = abuf->byte_length;
5589055959

5589155960
if (JS_ToInt64Clamp(ctx, &start, argv[0], 0, len, len))
@@ -55897,9 +55966,15 @@ static JSValue js_array_buffer_slice(JSContext *ctx,
5589755966
return JS_EXCEPTION;
5589855967
}
5589955968
new_len = max_int64(end - start, 0);
55900-
ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED);
55901-
if (JS_IsException(ctor))
55902-
return ctor;
55969+
// note: difference between slice and sliceToImmutable is that the
55970+
// latter does not have this step:
55971+
// 1. Let _ctor_ be ? SpeciesConstructor(_O_, %ArrayBuffer%)
55972+
ctor = JS_UNDEFINED;
55973+
if (!immutable) {
55974+
ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED);
55975+
if (JS_IsException(ctor))
55976+
return ctor;
55977+
}
5590355978
if (JS_IsUndefined(ctor)) {
5590455979
new_obj = js_array_buffer_constructor2(ctx, JS_UNDEFINED, new_len,
5590555980
NULL, class_id);
@@ -55915,6 +55990,10 @@ static JSValue js_array_buffer_slice(JSContext *ctx,
5591555990
new_abuf = JS_GetOpaque2(ctx, new_obj, class_id);
5591655991
if (!new_abuf)
5591755992
goto fail;
55993+
if (new_abuf->immutable) {
55994+
JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
55995+
goto fail;
55996+
}
5591855997
if (js_same_value(ctx, new_obj, this_val)) {
5591955998
JS_ThrowTypeError(ctx, "cannot use identical ArrayBuffer");
5592055999
goto fail;
@@ -55933,6 +56012,7 @@ static JSValue js_array_buffer_slice(JSContext *ctx,
5593356012
goto fail;
5593456013
}
5593556014
memcpy(new_abuf->data, abuf->data + start, new_len);
56015+
new_abuf->immutable = immutable;
5593656016
return new_obj;
5593756017
fail:
5593856018
JS_FreeValue(ctx, new_obj);
@@ -55944,10 +56024,13 @@ static const JSCFunctionListEntry js_array_buffer_proto_funcs[] = {
5594456024
JS_CGETSET_MAGIC_DEF("maxByteLength", js_array_buffer_get_maxByteLength, NULL, JS_CLASS_ARRAY_BUFFER ),
5594556025
JS_CGETSET_MAGIC_DEF("resizable", js_array_buffer_get_resizable, NULL, JS_CLASS_ARRAY_BUFFER ),
5594656026
JS_CGETSET_DEF("detached", js_array_buffer_get_detached, NULL ),
56027+
JS_CGETSET_DEF("immutable", js_array_buffer_get_immutable, NULL ),
5594756028
JS_CFUNC_MAGIC_DEF("resize", 1, js_array_buffer_resize, JS_CLASS_ARRAY_BUFFER ),
55948-
JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_ARRAY_BUFFER ),
55949-
JS_CFUNC_MAGIC_DEF("transfer", 0, js_array_buffer_transfer, 0 ),
55950-
JS_CFUNC_MAGIC_DEF("transferToFixedLength", 0, js_array_buffer_transfer, 1 ),
56029+
JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_ARRAY_BUFFER*2 + /*immutable*/0 ),
56030+
JS_CFUNC_MAGIC_DEF("sliceToImmutable", 2, js_array_buffer_slice, JS_CLASS_ARRAY_BUFFER*2 + /*immutable*/1 ),
56031+
JS_CFUNC_MAGIC_DEF("transfer", 0, js_array_buffer_transfer, JS_ARRAY_BUFFER_TRANSFER ),
56032+
JS_CFUNC_MAGIC_DEF("transferToImmutable", 0, js_array_buffer_transfer, JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE ),
56033+
JS_CFUNC_MAGIC_DEF("transferToFixedLength", 0, js_array_buffer_transfer, JS_ARRAY_BUFFER_TRANSFER_TO_FIXED_LENGTH ),
5595156034
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "ArrayBuffer", JS_PROP_CONFIGURABLE ),
5595256035
};
5595356036

@@ -55962,7 +56045,7 @@ static const JSCFunctionListEntry js_shared_array_buffer_proto_funcs[] = {
5596256045
JS_CGETSET_MAGIC_DEF("maxByteLength", js_array_buffer_get_maxByteLength, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ),
5596356046
JS_CGETSET_MAGIC_DEF("growable", js_array_buffer_get_resizable, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ),
5596456047
JS_CFUNC_MAGIC_DEF("grow", 1, js_array_buffer_resize, JS_CLASS_SHARED_ARRAY_BUFFER ),
55965-
JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_SHARED_ARRAY_BUFFER ),
56048+
JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_SHARED_ARRAY_BUFFER*2 + /*immutable*/0 ),
5596656049
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "SharedArrayBuffer", JS_PROP_CONFIGURABLE ),
5596756050
};
5596856051

@@ -55971,6 +56054,18 @@ static bool is_typed_array(JSClassID class_id)
5597156054
return class_id >= JS_CLASS_UINT8C_ARRAY && class_id <= JS_CLASS_FLOAT64_ARRAY;
5597256055
}
5597356056

56057+
// |p| must be a typed array, *not* a DataView
56058+
static bool typed_array_is_immutable(JSObject *p)
56059+
{
56060+
JSArrayBuffer *abuf;
56061+
JSTypedArray *ta;
56062+
56063+
assert(is_typed_array(p->class_id));
56064+
ta = p->u.typed_array;
56065+
abuf = ta->buffer->u.array_buffer;
56066+
return abuf->immutable;
56067+
}
56068+
5597456069
// is the typed array detached or out of bounds relative to its RAB?
5597556070
// |p| must be a typed array, *not* a DataView
5597656071
static bool typed_array_is_oob(JSObject *p)
@@ -56161,6 +56256,10 @@ static JSValue js_typed_array_set_internal(JSContext *ctx,
5616156256
p = get_typed_array(ctx, dst);
5616256257
if (!p)
5616356258
goto fail;
56259+
if (typed_array_is_immutable(p)) {
56260+
JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
56261+
goto fail;
56262+
}
5616456263
if (JS_ToInt64Sat(ctx, &offset, off))
5616556264
goto fail;
5616656265
if (offset < 0)
@@ -56523,6 +56622,8 @@ static JSValue js_typed_array_copyWithin(JSContext *ctx, JSValueConst this_val,
5652356622
p = get_typed_array(ctx, this_val);
5652456623
if (!p)
5652556624
return JS_EXCEPTION;
56625+
if (typed_array_is_immutable(p))
56626+
return JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
5652656627
if (typed_array_is_oob(p))
5652756628
return JS_ThrowTypeErrorArrayBufferOOB(ctx);
5652856629
len = p->u.array.count;
@@ -56565,6 +56666,8 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val,
5656556666
p = get_typed_array(ctx, this_val);
5656656667
if (!p)
5656756668
return JS_EXCEPTION;
56669+
if (typed_array_is_immutable(p))
56670+
return JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
5656856671
if (typed_array_is_oob(p))
5656956672
return JS_ThrowTypeErrorArrayBufferOOB(ctx);
5657056673
len = p->u.array.count;
@@ -57472,6 +57575,8 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
5747257575
p = get_typed_array(ctx, this_val);
5747357576
if (!p)
5747457577
return JS_EXCEPTION;
57578+
if (typed_array_is_immutable(p))
57579+
return JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
5747557580
if (typed_array_is_oob(p))
5747657581
return JS_ThrowTypeErrorArrayBufferOOB(ctx);
5747757582

@@ -58263,6 +58368,9 @@ static JSValue js_dataview_setValue(JSContext *ctx,
5826358368
ta = JS_GetOpaque2(ctx, this_obj, JS_CLASS_DATAVIEW);
5826458369
if (!ta)
5826558370
return JS_EXCEPTION;
58371+
abuf = ta->buffer->u.array_buffer;
58372+
if (abuf->immutable)
58373+
return JS_ThrowTypeErrorImmutableArrayBuffer(ctx);
5826658374
size = 1 << typed_array_size_log2(class_id);
5826758375
if (JS_ToIndex(ctx, &pos, argv[0]))
5826858376
return JS_EXCEPTION;
@@ -58296,7 +58404,6 @@ static JSValue js_dataview_setValue(JSContext *ctx,
5829658404
}
5829758405
littleEndian = argc > 2 && JS_ToBool(ctx, argv[2]);
5829858406
is_swap = littleEndian ^ !is_be();
58299-
abuf = ta->buffer->u.array_buffer;
5830058407
if (abuf->detached)
5830158408
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
5830258409
// order matters: this check should come before the next one

0 commit comments

Comments
 (0)