Skip to content

Commit 0d34aa0

Browse files
gibson042ptomato
authored andcommitted
Cover mutating TypedArray methods backed by an immutable ArrayBuffer
1 parent aedef87 commit 0d34aa0

File tree

5 files changed

+239
-0
lines changed

5 files changed

+239
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (C) 2025 Richard Gibson. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
/*---
5+
esid: sec-%typedarray%.prototype.copywithin
6+
description: Throws a TypeError exception when the backing buffer is immutable
7+
info: |
8+
%TypedArray%.prototype.copyWithin ( target, start [ , end ] )
9+
1. Let O be the this value.
10+
2. Let taRecord be ? ValidateTypedArray(O, ~seq-cst~, ~write~).
11+
3. Let len be TypedArrayLength(taRecord).
12+
4. Let relativeTarget be ? ToIntegerOrInfinity(target).
13+
5. If relativeTarget = -∞, let targetIndex be 0.
14+
6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
15+
7. Else, let targetIndex be min(relativeTarget, len).
16+
8. Let relativeStart be ? ToIntegerOrInfinity(start).
17+
9. If relativeStart = -∞, let startIndex be 0.
18+
10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
19+
11. Else, let startIndex be min(relativeStart, len).
20+
12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
21+
22+
ValidateTypedArray ( O, order [ , accessMode ] )
23+
1. If accessMode is not present, set accessMode to read.
24+
2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
25+
3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
26+
4. If accessMode is ~write~ and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
27+
features: [TypedArray, immutable-arraybuffer]
28+
includes: [testTypedArray.js, compareArray.js]
29+
---*/
30+
31+
testWithAllTypedArrayConstructors((TA, makeCtorArg) => {
32+
var calls = [];
33+
34+
var ta = new TA(makeCtorArg(["1", "2", "3", "4"]));
35+
var target = {
36+
valueOf() {
37+
calls.push("target.valueOf");
38+
return 1;
39+
}
40+
};
41+
var start = {
42+
valueOf() {
43+
calls.push("start.valueOf");
44+
return 2;
45+
}
46+
};
47+
var end = {
48+
valueOf() {
49+
calls.push("end.valueOf");
50+
return 2;
51+
}
52+
};
53+
54+
assert.throws(TypeError, function() {
55+
ta.copyWithin(target, start, end);
56+
});
57+
assert.compareArray(calls, [], "Must verify mutability before reading arguments.");
58+
assert.compareArray(ta, new TA(["1", "2", "3", "4"]), "Must not mutate contents.");
59+
}, null, ["immutable"]);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (C) 2025 Richard Gibson. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
/*---
5+
esid: sec-%typedarray%.prototype.fill
6+
description: Throws a TypeError exception when the backing buffer is immutable
7+
info: |
8+
%TypedArray%.prototype.fill ( value [ , start [ , end ] ] )
9+
1. Let O be the this value.
10+
2. Let taRecord be ? ValidateTypedArray(O, ~seq-cst~, ~write~).
11+
3. Let len be TypedArrayLength(taRecord).
12+
4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
13+
5. Otherwise, set value to ? ToNumber(value).
14+
6. Let relativeStart be ? ToIntegerOrInfinity(start).
15+
7. If relativeStart = -∞, let startIndex be 0.
16+
8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
17+
9. Else, let startIndex be min(relativeStart, len).
18+
10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
19+
20+
ValidateTypedArray ( O, order [ , accessMode ] )
21+
1. If accessMode is not present, set accessMode to read.
22+
2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
23+
3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
24+
4. If accessMode is ~write~ and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
25+
features: [TypedArray, immutable-arraybuffer]
26+
includes: [testTypedArray.js, compareArray.js]
27+
---*/
28+
29+
testWithAllTypedArrayConstructors((TA, makeCtorArg) => {
30+
var calls = [];
31+
32+
var ta = new TA(makeCtorArg(["1", "2", "3", "4"]));
33+
var value = {
34+
valueOf() {
35+
calls.push("value.valueOf");
36+
return "8";
37+
}
38+
};
39+
var start = {
40+
valueOf() {
41+
calls.push("start.valueOf");
42+
return 1;
43+
}
44+
};
45+
var end = {
46+
valueOf() {
47+
calls.push("end.valueOf");
48+
return 1;
49+
}
50+
};
51+
52+
assert.throws(TypeError, function() {
53+
ta.fill(value, start, end);
54+
});
55+
assert.compareArray(calls, [], "Must verify mutability before reading arguments.");
56+
assert.compareArray(ta, new TA(["1", "2", "3", "4"]), "Must not mutate contents.");
57+
}, null, ["immutable"]);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (C) 2025 Richard Gibson. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
/*---
5+
esid: sec-%typedarray%.prototype.reverse
6+
description: Throws a TypeError exception when the backing buffer is immutable
7+
info: |
8+
%TypedArray%.prototype.reverse ( )
9+
1. Let O be the this value.
10+
2. Let taRecord be ? ValidateTypedArray(O, ~seq-cst~, ~write~).
11+
12+
ValidateTypedArray ( O, order [ , accessMode ] )
13+
1. If accessMode is not present, set accessMode to read.
14+
2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
15+
3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
16+
4. If accessMode is ~write~ and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
17+
features: [TypedArray, immutable-arraybuffer]
18+
includes: [testTypedArray.js, compareArray.js]
19+
---*/
20+
21+
testWithAllTypedArrayConstructors((TA, makeCtorArg) => {
22+
var calls = [];
23+
24+
var ta = new TA(makeCtorArg(["1", "2", "3", "4"]));
25+
26+
assert.throws(TypeError, function() {
27+
ta.reverse();
28+
});
29+
assert.compareArray(calls, [], "Must verify mutability before reading arguments.");
30+
assert.compareArray(ta, new TA(["1", "2", "3", "4"]), "Must not mutate contents.");
31+
}, null, ["immutable"]);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (C) 2025 Richard Gibson. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
/*---
5+
esid: sec-%typedarray%.prototype.set
6+
description: Throws a TypeError exception when the backing buffer is immutable
7+
info: |
8+
%TypedArray%.prototype.set ( source [ , offset ] )
9+
1. Let target be the this value.
10+
...
11+
3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
12+
4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
13+
5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
14+
6. Let targetOffset be ? ToIntegerOrInfinity(offset).
15+
features: [TypedArray, immutable-arraybuffer]
16+
includes: [testTypedArray.js, compareArray.js]
17+
---*/
18+
19+
testWithAllTypedArrayConstructors((TA, makeCtorArg) => {
20+
var calls = [];
21+
22+
var ta = new TA(makeCtorArg(["1", "2", "3", "4"]));
23+
var source = {
24+
get length() {
25+
calls.push("get source.length");
26+
return 1;
27+
},
28+
get 0() {
29+
calls.push("get source[0]");
30+
return "8";
31+
},
32+
};
33+
var offset = {
34+
valueOf() {
35+
calls.push("offset.valueOf");
36+
return 1;
37+
}
38+
};
39+
40+
assert.throws(TypeError, function() {
41+
ta.set(source, offset);
42+
});
43+
assert.compareArray(calls, [], "Must verify mutability before reading arguments.");
44+
assert.compareArray(ta, new TA(["1", "2", "3", "4"]), "Must not mutate contents.");
45+
}, null, ["immutable"]);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (C) 2025 Richard Gibson. All rights reserved.
2+
// This code is governed by the BSD license found in the LICENSE file.
3+
4+
/*---
5+
esid: sec-%typedarray%.prototype.sort
6+
description: Throws a TypeError exception when the backing buffer is immutable
7+
info: |
8+
%TypedArray%.prototype.sort ( comparator )
9+
1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
10+
2. Let obj be the this value.
11+
3. Let taRecord be ? ValidateTypedArray(obj, ~seq-cst~, ~write~).
12+
4. Let len be TypedArrayLength(taRecord).
13+
5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
14+
6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
15+
a. Return ? CompareTypedArrayElements(x, y, comparator).
16+
7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, ~read-through-holes~).
17+
18+
ValidateTypedArray ( O, order [ , accessMode ] )
19+
1. If accessMode is not present, set accessMode to read.
20+
2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
21+
3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
22+
4. If accessMode is ~write~ and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
23+
features: [TypedArray, immutable-arraybuffer]
24+
includes: [testTypedArray.js, compareArray.js]
25+
---*/
26+
27+
testWithAllTypedArrayConstructors((TA, makeCtorArg) => {
28+
var calls = [];
29+
30+
var ta = new TA(makeCtorArg(["1", "2", "3", "4"]));
31+
function comparator() {
32+
calls.push("compare");
33+
return 0;
34+
}
35+
36+
assert.throws(TypeError, function() {
37+
ta.sort(comparator);
38+
});
39+
assert.compareArray(calls, [], "Must verify mutability before comparing.");
40+
assert.compareArray(ta, new TA(["1", "2", "3", "4"]), "Must not mutate contents.");
41+
42+
calls = [];
43+
var empty = new TA(makeCtorArg(0));
44+
assert.throws(TypeError, function() {
45+
empty.sort(comparator);
46+
}, "Must verify mutability even when receiver is length 0");
47+
}, null, ["immutable"]);

0 commit comments

Comments
 (0)