Skip to content

Commit 795f516

Browse files
committed
[immutable-arraybuffer] TypedArray canonical in-bounds index properties being defined are validated against descriptors for immutable properties
1 parent 01675ce commit 795f516

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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-defineownproperty
6+
description: >
7+
When the backing buffer is immutable, properties for in-bounds indexes are
8+
validated to be non-configurable, enumerable, non-writable, and
9+
value-preserving.
10+
info: |
11+
[[DefineOwnProperty]] ( P, Desc )
12+
1. If P is a String, then
13+
a. Let numericIndex be CanonicalNumericIndexString(P).
14+
b. If numericIndex is not undefined, then
15+
i. If IsValidIntegerIndex(O, numericIndex) is false, return false.
16+
ii. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
17+
1. Let current be ! O.[[GetOwnProperty]](P).
18+
2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
19+
3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
20+
4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
21+
features: [TypedArray, immutable-arraybuffer]
22+
includes: [testTypedArray.js, compareArray.js, deepEqual.js]
23+
---*/
24+
25+
function reprDesc(desc) {
26+
var str = JSON.stringify(desc, function(_key, value) {
27+
if (typeof value === "bigint") return String(value) + "n";
28+
if (typeof value === "number" && (1 / value === -Infinity)) return "-0";
29+
return value;
30+
});
31+
return str.replace(/"([0-9]+n|-0)"/, "$1");
32+
}
33+
34+
testWithAllTypedArrayConstructors(function(TA, makeCtorArg) {
35+
var sample = new TA(makeCtorArg(["0", "1"]));
36+
var descriptor = Object.getOwnPropertyDescriptor(sample, "0");
37+
38+
// Reuse of existing property attributes (possibly partial) succeeds but has
39+
// no effect.
40+
for (var v = 0; v < 2; v++) {
41+
for (var c = 0; c < 2; c++) {
42+
for (var e = 0; e < 2; e++) {
43+
for (var w = 0; w < 2; w++) {
44+
var newDesc = {};
45+
if (v) newDesc.value = descriptor.value;
46+
if (c) newDesc.configurable = descriptor.configurable;
47+
if (e) newDesc.enumerable = descriptor.enumerable;
48+
if (w) newDesc.writable = descriptor.writable;
49+
50+
if (typeof Reflect !== "undefined" && Reflect.defineProperty) {
51+
assert.sameValue(Reflect.defineProperty(sample, "0", newDesc), true,
52+
"Reflect.defineProperty " + reprDesc(newDesc));
53+
assert.deepEqual(Object.getOwnPropertyDescriptor(sample, "0"), descriptor,
54+
"results of Reflect.defineProperty " + reprDesc(newDesc));
55+
}
56+
Object.defineProperty(sample, "0", newDesc);
57+
assert.deepEqual(Object.getOwnPropertyDescriptor(sample, "0"), descriptor,
58+
"results of Object.defineProperty " + reprDesc(newDesc));
59+
}
60+
}
61+
}
62+
}
63+
64+
// Extension of each of the above to include one or invalidating attributes fails
65+
// with no effect.
66+
var badValues = ["0", -0];
67+
for (var v = 0; v < 2; v++) {
68+
for (var c = 0; c < 2; c++) {
69+
for (var e = 0; e < 2; e++) {
70+
for (var w = 0; w < 2; w++) {
71+
for (var vx = 0; vx <= badValues.length; vx++) {
72+
for (var cx = 0; cx < 2; cx++) {
73+
for (var ex = 0; ex < 2; ex++) {
74+
for (var wx = 0; wx < 2; wx++) {
75+
// Require at least one bad attribute.
76+
if (!vx && !cx && !ex && !wx) continue;
77+
// To avoid redundancy, introduce bad attributes only additively
78+
// (i.e., rather than by overwriting a good attribute).
79+
if ((v && vx) || (c && cx) || (e && ex) || (w && wx)) continue;
80+
81+
var badDesc = {};
82+
83+
if (v) badDesc.value = descriptor.value;
84+
if (c) badDesc.configurable = descriptor.configurable;
85+
if (e) badDesc.enumerable = descriptor.enumerable;
86+
if (w) badDesc.writable = descriptor.writable;
87+
88+
if (vx) badDesc.value = badValues[vx - 1];
89+
if (cx) badDesc.configurable = !descriptor.configurable;
90+
if (ex) badDesc.enumerable = !descriptor.enumerable;
91+
if (wx) badDesc.writable = !descriptor.writable;
92+
93+
if (typeof Reflect !== "undefined" && Reflect.defineProperty) {
94+
assert.sameValue(Reflect.defineProperty(sample, "0", badDesc), false,
95+
"Reflect.defineProperty " + reprDesc(badDesc));
96+
assert.deepEqual(Object.getOwnPropertyDescriptor(sample, "0"), descriptor,
97+
"results of Reflect.defineProperty " + reprDesc(badDesc));
98+
}
99+
assert.throws(TypeError, function() {
100+
Object.defineProperty(sample, "0", badDesc);
101+
}, "Object.defineProperty " + reprDesc(badDesc));
102+
assert.deepEqual(Object.getOwnPropertyDescriptor(sample, "0"), descriptor,
103+
"results of Object.defineProperty " + reprDesc(badDesc));
104+
}
105+
}
106+
}
107+
}
108+
}
109+
}
110+
}
111+
}
112+
}, null, ["immutable"]);

0 commit comments

Comments
 (0)