@@ -51,6 +51,12 @@ static bool ReportDetachedArrayBuffer(JSContext* cx) {
51
51
return false ;
52
52
}
53
53
54
+ static bool ReportImmutableBuffer (JSContext* cx) {
55
+ JS_ReportErrorNumberASCII (cx, GetErrorMessage, nullptr ,
56
+ JSMSG_ARRAYBUFFER_IMMUTABLE);
57
+ return false ;
58
+ }
59
+
54
60
static bool ReportResizedArrayBuffer (JSContext* cx) {
55
61
JS_ReportErrorNumberASCII (cx, GetErrorMessage, nullptr ,
56
62
JSMSG_TYPED_ARRAY_RESIZED_BOUNDS);
@@ -64,15 +70,15 @@ static bool ReportOutOfRange(JSContext* cx) {
64
70
return false ;
65
71
}
66
72
67
- // ES2021 draft rev bd868f20b8c574ad6689fba014b62a1dba819e56
68
- // Plus: https://github.com/tc39/ecma262/pull/1908
69
- // 24.4.1.1 ValidateIntegerTypedArray ( typedArray [ , waitable ] )
73
+ enum class AccessMode { Read, Write };
74
+
75
+ // ES2026 draft rev affcec07523a45d40fb668689c07657412e772ac
76
+ // Plus: https://tc39.es/proposal-immutable-arraybuffer/
77
+ // 25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable )
70
78
static bool ValidateIntegerTypedArray (
71
- JSContext* cx, HandleValue typedArray, bool waitable,
79
+ JSContext* cx, HandleValue typedArray, bool waitable, AccessMode accessMode,
72
80
MutableHandle<TypedArrayObject*> unwrappedTypedArray) {
73
- // Step 1 (implicit).
74
-
75
- // Step 2.
81
+ // Steps 1-2.
76
82
auto * unwrapped = UnwrapAndTypeCheckValue<TypedArrayObject>(
77
83
cx, typedArray, [cx]() { ReportBadArrayType (cx); });
78
84
if (!unwrapped) {
@@ -83,7 +89,12 @@ static bool ValidateIntegerTypedArray(
83
89
return ReportDetachedArrayBuffer (cx);
84
90
}
85
91
86
- // Steps 3-6.
92
+ if (accessMode == AccessMode::Write &&
93
+ unwrapped->is <ImmutableTypedArrayObject>()) {
94
+ return ReportImmutableBuffer (cx);
95
+ }
96
+
97
+ // Steps 3-4.
87
98
if (waitable) {
88
99
switch (unwrapped->type ()) {
89
100
case Scalar::Int32:
@@ -108,7 +119,7 @@ static bool ValidateIntegerTypedArray(
108
119
}
109
120
}
110
121
111
- // Steps 7-9 (modified to return the TypedArray).
122
+ // Step 5 (modified to return the TypedArray).
112
123
unwrappedTypedArray.set (unwrapped);
113
124
return true ;
114
125
}
@@ -253,10 +264,12 @@ struct ArrayOps<uint64_t> {
253
264
// 24.4.4 Atomics.compareExchange ( typedArray, index, ... ), steps 1-2.
254
265
// 24.4.9 Atomics.store ( typedArray, index, value ), steps 1-2.
255
266
template <typename Op>
256
- bool AtomicAccess (JSContext* cx, HandleValue obj, HandleValue index, Op op) {
267
+ static bool AtomicAccess (JSContext* cx, HandleValue obj, HandleValue index,
268
+ AccessMode accessMode, Op op) {
257
269
// Step 1.
258
270
Rooted<TypedArrayObject*> unwrappedTypedArray (cx);
259
- if (!ValidateIntegerTypedArray (cx, obj, false , &unwrappedTypedArray)) {
271
+ if (!ValidateIntegerTypedArray (cx, obj, false , accessMode,
272
+ &unwrappedTypedArray)) {
260
273
return false ;
261
274
}
262
275
@@ -326,7 +339,7 @@ static bool atomics_compareExchange(JSContext* cx, unsigned argc, Value* vp) {
326
339
HandleValue index = args.get (1 );
327
340
328
341
return AtomicAccess (
329
- cx, typedArray, index,
342
+ cx, typedArray, index, AccessMode::Write,
330
343
[cx, &args](auto ops, Handle<TypedArrayObject*> unwrappedTypedArray,
331
344
size_t index) {
332
345
using T = typename decltype (ops)::Type;
@@ -363,7 +376,7 @@ static bool atomics_load(JSContext* cx, unsigned argc, Value* vp) {
363
376
HandleValue index = args.get (1 );
364
377
365
378
return AtomicAccess (
366
- cx, typedArray, index,
379
+ cx, typedArray, index, AccessMode::Read,
367
380
[cx, &args](auto ops, Handle<TypedArrayObject*> unwrappedTypedArray,
368
381
size_t index) {
369
382
using T = typename decltype (ops)::Type;
@@ -388,7 +401,7 @@ static bool atomics_store(JSContext* cx, unsigned argc, Value* vp) {
388
401
HandleValue index = args.get (1 );
389
402
390
403
return AtomicAccess (
391
- cx, typedArray, index,
404
+ cx, typedArray, index, AccessMode::Write,
392
405
[cx, &args](auto ops, Handle<TypedArrayObject*> unwrappedTypedArray,
393
406
size_t index) {
394
407
using T = typename decltype (ops)::Type;
@@ -418,7 +431,7 @@ static bool AtomicReadModifyWrite(JSContext* cx, const CallArgs& args,
418
431
HandleValue index = args.get (1 );
419
432
420
433
return AtomicAccess (
421
- cx, typedArray, index,
434
+ cx, typedArray, index, AccessMode::Write,
422
435
[cx, &args, op](auto ops, Handle<TypedArrayObject*> unwrappedTypedArray,
423
436
size_t index) {
424
437
using T = typename decltype (ops)::Type;
@@ -1303,7 +1316,8 @@ static bool DoWait(JSContext* cx, bool isAsync, HandleValue objv,
1303
1316
MutableHandleValue r) {
1304
1317
// Steps 1-2.
1305
1318
Rooted<TypedArrayObject*> unwrappedTypedArray (cx);
1306
- if (!ValidateIntegerTypedArray (cx, objv, true , &unwrappedTypedArray)) {
1319
+ if (!ValidateIntegerTypedArray (cx, objv, true , AccessMode::Read,
1320
+ &unwrappedTypedArray)) {
1307
1321
return false ;
1308
1322
}
1309
1323
MOZ_ASSERT (unwrappedTypedArray->type () == Scalar::Int32 ||
@@ -1472,7 +1486,8 @@ static bool atomics_notify(JSContext* cx, unsigned argc, Value* vp) {
1472
1486
1473
1487
// Step 1.
1474
1488
Rooted<TypedArrayObject*> unwrappedTypedArray (cx);
1475
- if (!ValidateIntegerTypedArray (cx, objv, true , &unwrappedTypedArray)) {
1489
+ if (!ValidateIntegerTypedArray (cx, objv, true , AccessMode::Read,
1490
+ &unwrappedTypedArray)) {
1476
1491
return false ;
1477
1492
}
1478
1493
MOZ_ASSERT (unwrappedTypedArray->type () == Scalar::Int32 ||
0 commit comments