blob: 29a8b65ed12ca39bbc94a1c429ac49375d7dbe5b [file] [log] [blame]
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error(`Bad value: ${actual}!\ncreateTestObject:\n${createTestObject}\nmakeLengthReadOnly: ${makeLengthReadOnly}`);
};
function shouldThrow(func, reExpectedError) {
let errorThrown = false;
try {
func();
} catch (error) {
errorThrown = true;
if (!reExpectedError.test(error.toString()))
throw new Error(`Bad error: ${error}!\ncreateTestObject:\n${createTestObject}\nmakeLengthReadOnly: ${makeLengthReadOnly}`);
}
if (!errorThrown)
throw new Error(`Didn't throw!\ncreateTestObject: ${createTestObject}\nmakeLengthReadOnly: ${makeLengthReadOnly}`);
};
var createTestObject;
const createTestObjectFunctions = [
len => new Array(len),
len => new Proxy(new Array(len), {}),
len => { const obj = Object.create(Array.prototype); obj.length = len; return obj; },
];
var makeLengthReadOnly;
const makeLengthReadOnlyFunctions = [
arr => { Object.freeze(arr); },
arr => { Object.defineProperty(arr, "length", { writable: false }); },
];
var testObject;
const expectedTypeError = /^TypeError:.+/;
for (createTestObject of createTestObjectFunctions) {
for (makeLengthReadOnly of makeLengthReadOnlyFunctions) {
testObject = createTestObject(0);
makeLengthReadOnly(testObject);
shouldThrow(() => { "use strict"; testObject.length = 0; }, expectedTypeError);
shouldBe(testObject.length, 0);
testObject = createTestObject(0);
makeLengthReadOnly(testObject);
shouldThrow(() => { testObject.pop(); }, expectedTypeError);
shouldBe(testObject.length, 0);
testObject = createTestObject(1);
testObject[0] = 1;
makeLengthReadOnly(testObject);
shouldThrow(() => { testObject.pop(); }, expectedTypeError);
shouldBe(testObject.length, 1);
testObject = createTestObject(0);
makeLengthReadOnly(testObject);
shouldThrow(() => { testObject.push(); }, expectedTypeError);
shouldBe(testObject.length, 0);
testObject = createTestObject(0);
makeLengthReadOnly(testObject);
shouldThrow(() => { testObject.push(1); }, expectedTypeError);
shouldBe(testObject.length, 0);
testObject = createTestObject(0);
makeLengthReadOnly(testObject);
shouldThrow(() => { testObject.shift(); }, expectedTypeError);
shouldBe(testObject.length, 0);
testObject = createTestObject(1);
testObject[0] = 1;
makeLengthReadOnly(testObject);
shouldThrow(() => { testObject.shift(); }, expectedTypeError);
shouldBe(testObject.length, 1);
testObject = createTestObject(0);
makeLengthReadOnly(testObject);
shouldThrow(() => { testObject.unshift(); }, expectedTypeError);
shouldBe(testObject.length, 0);
testObject = createTestObject(0);
makeLengthReadOnly(testObject);
shouldThrow(() => { testObject.unshift(1); }, expectedTypeError);
shouldBe(testObject.length, 0);
}}
// let's have a bad time?
for (createTestObject of createTestObjectFunctions) {
for (makeLengthReadOnly of makeLengthReadOnlyFunctions) {
let arrayPrototypeGet0Calls = 0;
let arrayPrototypeSet0Calls = 0;
Object.defineProperty(Array.prototype, "0", {
get() {
Object.defineProperty(testObject, "length", { writable: false });
arrayPrototypeGet0Calls++;
},
set(_val) {
Object.defineProperty(testObject, "length", { writable: false });
arrayPrototypeSet0Calls++;
},
configurable: true,
});
testObject = createTestObject(1);
shouldThrow(() => { testObject.pop(); }, expectedTypeError);
shouldBe(arrayPrototypeGet0Calls, 1);
shouldBe(testObject.hasOwnProperty(0), false);
shouldBe(testObject.length, 1);
testObject = createTestObject(1);
shouldThrow(() => { testObject.shift(); }, expectedTypeError);
shouldBe(arrayPrototypeGet0Calls, 2);
shouldBe(testObject.hasOwnProperty(0), false);
shouldBe(testObject.length, 1);
testObject = createTestObject(0);
shouldThrow(() => { testObject.push(1); }, expectedTypeError);
shouldBe(arrayPrototypeSet0Calls, 1);
shouldBe(testObject.hasOwnProperty(0), false);
shouldBe(testObject.length, 0);
testObject = createTestObject(0);
shouldThrow(() => { testObject.unshift(1); }, expectedTypeError);
shouldBe(arrayPrototypeSet0Calls, 2);
shouldBe(testObject.hasOwnProperty(0), false);
shouldBe(testObject.length, 0);
}}
// [[DefineOwnProperty]] shouldn't fail
for (createTestObject of createTestObjectFunctions) {
for (makeLengthReadOnly of makeLengthReadOnlyFunctions) {
testObject = createTestObject(42);
makeLengthReadOnly(testObject);
Object.defineProperty(testObject, "length", { value: 42 }); // doesn't throw
shouldBe(Reflect.defineProperty(testObject, "length", { value: 42 }), true);
shouldBe(testObject.length, 42);
}}