Add test for holey non-extensible element

Bug: v8:6831
Change-Id: I4d4d9b65a346384b8f6c6dc2cfe0c1ce88116e18
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1574503
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60993}
This commit is contained in:
Z Duong Nguyen-Huu 2019-04-24 10:02:37 -07:00 committed by Commit Bot
parent 98bbe37e84
commit feba84a3f9
3 changed files with 467 additions and 2 deletions

View File

@ -574,3 +574,174 @@ arr[2] = 'c';
assertEquals(arr[2], undefined);
arr.length = 1;
assertEquals(arr.length, 2);
// Start testing with holey array
// Test holey element array built-in functions with freeze.
function testHoleyFrozenArray1(obj) {
assertTrue(Object.isSealed(obj));
// Verify that the value can't be written
obj1 = new Array(...obj);
var length = obj.length;
for (var i = 0; i < length-1; i++) {
obj[i] = 'new';
assertEquals(obj1[i], obj[i]);
}
// for symbol we cannot compare directly
assertTrue(typeof obj[length-1] == 'symbol');
// Verify that the length can't be written by builtins.
assertTrue(Array.isArray(obj));
assertThrows(function() { obj.pop(); }, TypeError);
assertThrows(function() { obj.push(); }, TypeError);
assertThrows(function() { obj.shift(); }, TypeError);
assertThrows(function() { obj.unshift(); }, TypeError);
assertThrows(function() { obj.copyWithin(0,0); }, TypeError);
assertThrows(function() { obj.fill(0); }, TypeError);
assertThrows(function() { obj.reverse(); }, TypeError);
assertThrows(function() { obj.sort(); }, TypeError);
assertThrows(function() { obj.splice(0); }, TypeError);
assertThrows(function() { obj.splice(0, 0); }, TypeError);
assertTrue(Object.isFrozen(obj));
// Verify search, filter, iterator
assertEquals(obj.lastIndexOf(1), 2);
assertEquals(obj.indexOf('a'), 5);
assertEquals(obj.indexOf(undefined), 0);
assertFalse(obj.includes(Symbol("test")));
assertTrue(obj.includes(undefined));
assertFalse(obj.includes(NaN));
assertTrue(obj.includes());
assertEquals(obj.find(x => x==0), undefined);
assertEquals(obj.findIndex(x => x=='a'), 5);
assertTrue(obj.some(x => typeof x == 'symbol'));
assertFalse(obj.every(x => x == -1));
var filteredArray = obj.filter(e => typeof e == "symbol");
assertEquals(filteredArray.length, 1);
assertEquals(obj.map(x => x), obj);
var countPositiveNumber = 0;
obj.forEach(function(item, index) {
if (item === 1) {
countPositiveNumber++;
assertEquals(index, 2);
}
});
assertEquals(countPositiveNumber, 1);
assertEquals(obj.length, obj.concat([]).length);
var iterator = obj.values();
assertEquals(iterator.next().value, undefined);
assertEquals(iterator.next().value, null);
var iterator = obj.keys();
assertEquals(iterator.next().value, 0);
assertEquals(iterator.next().value, 1);
var iterator = obj.entries();
assertEquals(iterator.next().value, [0, undefined]);
assertEquals(iterator.next().value, [1, null]);
}
obj = [undefined, null, 1, , -1, 'a', Symbol("test")];
assertTrue(%HasHoleyElements(obj));
Object.freeze(obj);
testHoleyFrozenArray1(obj);
// Verify change from sealed to frozen
obj = [undefined, null, 1, , -1, 'a', Symbol("test")];
assertTrue(%HasHoleyElements(obj));
Object.seal(obj);
Object.freeze(obj);
assertTrue(Object.isSealed(obj));
testHoleyFrozenArray1(obj);
// Verify change from non-extensible to frozen
obj = [undefined, null, 1, ,-1, 'a', Symbol("test")];
assertTrue(%HasHoleyElements(obj));
Object.preventExtensions(obj);
Object.freeze(obj);
assertTrue(Object.isSealed(obj));
testHoleyFrozenArray1(obj);
// Verify flat, map, slice, flatMap, join, reduce, reduceRight for frozen packed array
function testHoleyFrozenArray2(arr) {
assertTrue(Object.isFrozen(arr));
assertTrue(Array.isArray(arr));
assertEquals(arr.map(x => [x]), [, ['a'], ['b'], ['c']]);
assertEquals(arr.flatMap(x => [x]), ["a", "b", "c"]);
assertEquals(arr.flat(), ["a", "b", "c"]);
assertEquals(arr.join('-'), "-a-b-c");
const reducer = (accumulator, currentValue) => accumulator + currentValue;
assertEquals(arr.reduce(reducer), "abc");
assertEquals(arr.reduceRight(reducer), "cba");
assertEquals(arr.slice(0, 1), [,]);
assertEquals(arr.slice(1, 2), ["a"]);
}
var arr1 = [, 'a', 'b', 'c'];
assertTrue(%HasHoleyElements(arr1));
Object.freeze(arr1);
testHoleyFrozenArray2(arr1);
// Verify change from sealed to frozen
var arr2 = [, 'a', 'b', 'c'];
assertTrue(%HasHoleyElements(arr2));
Object.seal(arr2);
Object.freeze(arr2);
testHoleyFrozenArray2(arr2);
// Verify change from non-extensible to frozen
var arr2 = [, 'a', 'b', 'c'];
assertTrue(%HasHoleyElements(arr2));
Object.preventExtensions(arr2);
Object.freeze(arr2);
testHoleyFrozenArray2(arr2);
// Test regression with Object.defineProperty
var obj = ['a', , 'b'];
obj.propertyA = 42;
obj[0] = true;
Object.freeze(obj);
assertThrows(function() {
Object.defineProperty(obj, 'propertyA', {
value: obj,
});
}, TypeError);
assertEquals(42, obj.propertyA);
assertThrows(function() {
Object.defineProperty(obj, 'propertyA', {
value: obj,
writable: false,
});
}, TypeError);
assertDoesNotThrow(function() {obj.propertyA = 2;});
assertEquals(obj.propertyA, 42);
assertThrows(function() {
Object.defineProperty(obj, 'abc', {
value: obj,
});
}, TypeError);
// Regression test with simple holey array
var arr = [, 'a'];
Object.freeze(arr);
arr[1] = 'b';
assertEquals(arr[1], 'a');
arr[0] = 1;
assertEquals(arr[0], undefined);
// Test regression Array.concat with double
var arr = ['a', , 'b'];
Object.freeze(arr);
arr = arr.concat(0.5);
assertEquals(arr, ['a', ,'b', 0.5]);
Object.freeze(arr);
arr = arr.concat([1.5, 'c']);
assertEquals(arr, ['a', ,'b', 0.5, 1.5, 'c']);
// Regression test with change length
var arr = ['a', ,'b'];
Object.freeze(arr);
assertEquals(arr.length, 3);
arr.length = 4;
assertEquals(arr.length, 3);
arr[3] = 'c';
assertEquals(arr[2], 'b');
assertEquals(arr[3], undefined);
arr.length = 2;
assertEquals(arr.length, 3);

View File

@ -225,7 +225,7 @@ for (var i = 0; i < length-1; i++) {
assertEquals(obj[i], 'new');
}
// Verify flat, map, flatMap, join, reduce, reduceRight for sealed packed array
// Verify flat, map, flatMap, join, reduce, reduceRight for non-extensible packed array
var arr = ['a', 'b', 'c'];
assertTrue(%HasPackedElements(arr));
Object.preventExtensions(arr);
@ -242,7 +242,7 @@ assertEquals(arr.reduce(reducer), "abc");
assertEquals(arr.reduceRight(reducer), "cba");
assertEquals(arr.slice(0, 1), ['a']);
// Verify change content of sealed packed array
// Verify change content of non-extensible packed array
arr.sort();
assertEquals(arr.join(''), "abc");
arr.reverse();
@ -280,3 +280,132 @@ assertEquals(arr[2], undefined);
arr.length = 1;
assertEquals(arr.length, 1);
assertEquals(arr[1], undefined);
// Test for holey array
// Test holey element array built-in functions with preventExtensions.
obj = [undefined, null, 1, , -1, 'a', Symbol("test")];
assertTrue(%HasHoleyElements(obj));
Object.preventExtensions(obj);
assertFalse(Object.isSealed(obj));
assertFalse(Object.isFrozen(obj));
assertFalse(Object.isExtensible(obj));
assertTrue(Array.isArray(obj));
// Verify that the length can't be written by builtins.
assertThrows(function() { obj.push(1); }, TypeError);
assertThrows(function() { obj.shift(); }, TypeError);
assertThrows(function() { obj.unshift(1); }, TypeError);
assertThrows(function() { obj.splice(0, 0, 1); }, TypeError);
assertDoesNotThrow(function() {obj.splice(0, 0)});
// Verify search, filter, iterator
obj = [undefined, null, 1, ,-1, 'a', Symbol("test")];
assertTrue(%HasHoleyElements(obj));
Object.preventExtensions(obj);
assertFalse(Object.isSealed(obj));
assertFalse(Object.isFrozen(obj));
assertFalse(Object.isExtensible(obj));
assertTrue(Array.isArray(obj));
assertEquals(obj.lastIndexOf(1), 2);
assertEquals(obj.indexOf('a'), 5);
assertEquals(obj.indexOf(undefined), 0);
assertFalse(obj.includes(Symbol("test")));
assertTrue(obj.includes(undefined));
assertFalse(obj.includes(NaN));
assertTrue(obj.includes());
assertEquals(obj.find(x => x==0), undefined);
assertEquals(obj.findIndex(x => x=='a'), 5);
assertTrue(obj.some(x => typeof x == 'symbol'));
assertFalse(obj.every(x => x == -1));
var filteredArray = obj.filter(e => typeof e == "symbol");
assertEquals(filteredArray.length, 1);
assertEquals(obj.map(x => x), obj);
var countPositiveNumber = 0;
obj.forEach(function(item, index) {
if (item === 1) {
countPositiveNumber++;
assertEquals(index, 2);
}
});
assertEquals(countPositiveNumber, 1);
assertEquals(obj.length, obj.concat([]).length);
var iterator = obj.values();
assertEquals(iterator.next().value, undefined);
assertEquals(iterator.next().value, null);
var iterator = obj.keys();
assertEquals(iterator.next().value, 0);
assertEquals(iterator.next().value, 1);
var iterator = obj.entries();
assertEquals(iterator.next().value, [0, undefined]);
assertEquals(iterator.next().value, [1, null]);
// Verify that the value can be written
var length = obj.length;
for (var i = 0; i < length-1; i++) {
if (i==3) continue;
obj[i] = 'new';
assertEquals(obj[i], 'new');
}
// Verify flat, map, flatMap, join, reduce, reduceRight for non-extensible holey array
var arr = [, 'a', 'b', 'c'];
assertTrue(%HasHoleyElements(arr));
Object.preventExtensions(arr);
assertFalse(Object.isSealed(obj));
assertFalse(Object.isFrozen(obj));
assertFalse(Object.isExtensible(obj));
assertTrue(Array.isArray(obj));
assertEquals(arr.map(x => [x]), [, ['a'], ['b'], ['c']]);
assertEquals(arr.flatMap(x => [x]), ["a", "b", "c"]);
assertEquals(arr.flat(), ["a", "b", "c"]);
assertEquals(arr.join('-'), "-a-b-c");
const reducer1 = (accumulator, currentValue) => accumulator + currentValue;
assertEquals(arr.reduce(reducer1), "abc");
assertEquals(arr.reduceRight(reducer1), "cba");
assertEquals(arr.slice(0, 1), [,]);
assertEquals(arr.slice(1, 2), ["a"]);
// Verify change content of non-extensible holey array
assertThrows(function(){arr.sort();}, TypeError);
assertEquals(arr.join(''), "abc");
assertThrows(function(){arr.reverse();}, TypeError);
assertEquals(arr.join(''), "abc");
assertThrows(function(){arr.copyWithin(0, 1, 2);}, TypeError);
arr.copyWithin(1, 2, 3);
assertEquals(arr.join(''),"bbc");
assertThrows(function(){arr.fill('d');}, TypeError);
assertEquals(arr.join(''), "bbc");
arr.pop();
assertEquals(arr.join(''), "bb");
// Regression test with simple holey array
var arr = [, 'a'];
Object.preventExtensions(arr);
arr[1] = 'b';
assertEquals(arr[1], 'b');
arr[0] = 1;
assertEquals(arr[0], undefined);
// Test regression Array.concat with double
var arr = ['a', , 'b'];
Object.preventExtensions(arr);
arr = arr.concat(0.5);
assertEquals(arr, ['a', ,'b', 0.5]);
Object.preventExtensions(arr);
arr = arr.concat([1.5, 'c']);
assertEquals(arr, ['a', ,'b', 0.5, 1.5, 'c']);
// Regression test with change length
var arr = ['a', , 'b'];
Object.preventExtensions(arr);
assertEquals(arr.length, 3);
arr.length = 4;
assertEquals(arr.length, 4);
arr[3] = 'c';
assertEquals(arr[3], undefined);
arr.length = 2;
assertEquals(arr.length, 2);
assertEquals(arr[2], undefined);
assertEquals(arr.pop(), undefined);
assertEquals(arr.length, 1);
assertEquals(arr[1], undefined);

View File

@ -550,3 +550,168 @@ arr[2] = 'c';
assertEquals(arr[2], undefined);
arr.length = 1;
assertEquals(arr.length, 2);
// Start testing for holey element array
// Test holey element array built-in functions with seal.
function testHoleySealedArray1(obj) {
assertTrue(Object.isSealed(obj));
assertFalse(Object.isFrozen(obj));
assertTrue(Array.isArray(obj));
// Verify that the length can't be written by builtins.
assertThrows(function() { obj.pop(); }, TypeError);
assertThrows(function() { obj.push(1); }, TypeError);
assertThrows(function() { obj.shift(); }, TypeError);
assertThrows(function() { obj.unshift(1); }, TypeError);
assertThrows(function() { obj.splice(0); }, TypeError);
assertDoesNotThrow(function() { obj.splice(0, 0); });
// Verify search, filter, iterator
obj = [undefined, null, 1, , -1, 'a', Symbol("test")];
assertTrue(%HasHoleyElements(obj));
Object.seal(obj);
assertTrue(Object.isSealed(obj));
assertFalse(Object.isFrozen(obj));
assertTrue(Array.isArray(obj));
assertEquals(obj.lastIndexOf(1), 2);
assertEquals(obj.indexOf('a'), 5);
assertEquals(obj.indexOf(undefined), 0);
assertFalse(obj.includes(Symbol("test")));
assertTrue(obj.includes(undefined));
assertFalse(obj.includes(NaN));
assertTrue(obj.includes());
assertEquals(obj.find(x => x==0), undefined);
assertEquals(obj.findIndex(x => x=='a'), 5);
assertTrue(obj.some(x => typeof x == 'symbol'));
assertFalse(obj.every(x => x == -1));
var filteredArray = obj.filter(e => typeof e == "symbol");
assertEquals(filteredArray.length, 1);
assertEquals(obj.map(x => x), obj);
var countPositiveNumber = 0;
obj.forEach(function(item, index) {
if (item === 1) {
countPositiveNumber++;
assertEquals(index, 2);
}
});
assertEquals(countPositiveNumber, 1);
assertEquals(obj.length, obj.concat([]).length);
var iterator = obj.values();
assertEquals(iterator.next().value, undefined);
assertEquals(iterator.next().value, null);
var iterator = obj.keys();
assertEquals(iterator.next().value, 0);
assertEquals(iterator.next().value, 1);
var iterator = obj.entries();
assertEquals(iterator.next().value, [0, undefined]);
assertEquals(iterator.next().value, [1, null]);
// Verify that the value can be written
var length = obj.length;
for (var i = 0; i < length; i++) {
if (i==3) continue;
obj[i] = 'new';
assertEquals(obj[i], 'new');
}
};
obj = [undefined, null, 1, , -1, 'a', Symbol("test")];
assertTrue(%HasHoleyElements(obj));
Object.seal(obj);
testHoleySealedArray1(obj);
// Verify after transition from preventExtensions
obj = [undefined, null, 1, , -1, 'a', Symbol("test")];
assertTrue(%HasHoleyElements(obj));
Object.preventExtensions(obj);
Object.seal(obj);
testHoleySealedArray1(obj);
// Verify flat, map, slice, flatMap, join, reduce, reduceRight for sealed holey array
function testHoleySealedArray2(arr) {
assertTrue(Object.isSealed(arr));
assertFalse(Object.isFrozen(arr));
assertEquals(arr.map(x => [x]), [, ['a'], ['b'], ['c']]);
assertEquals(arr.flatMap(x => [x]), ["a", "b", "c"]);
assertEquals(arr.flat(), ["a", "b", "c"]);
assertEquals(arr.join('-'), "-a-b-c");
const reducer = (accumulator, currentValue) => accumulator + currentValue;
assertEquals(arr.reduce(reducer), "abc");
assertEquals(arr.reduceRight(reducer), "cba");
assertEquals(arr.slice(0, 1), [,]);
assertEquals(arr.slice(1, 2), ["a"]);
// Verify change content of sealed holey array
assertThrows(function(){arr.sort();}, TypeError);
assertEquals(arr.join(''), "abc");
assertThrows(function(){arr.reverse();}, TypeError);
assertEquals(arr.join(''), "abc");
assertThrows(function(){arr.copyWithin(0, 1, 2);}, TypeError);
assertEquals(arr.join(''),"abc");
arr.copyWithin(1, 2, 3);
assertEquals(arr.join(''),"bbc");
assertThrows(function(){arr.fill('d');}, TypeError);
assertEquals(arr.join(''), "bbc");
}
var arr1 = [, 'a', 'b', 'c'];
assertTrue(%HasHoleyElements(arr1));
Object.seal(arr1);
testHoleySealedArray2(arr1);
var arr2 = [, 'a', 'b', 'c'];
assertTrue(%HasHoleyElements(arr2));
Object.preventExtensions(arr2);
Object.seal(arr2);
testHoleySealedArray2(arr2);
// Test regression with Object.defineProperty
var obj = ['a', , 'b'];
obj.propertyA = 42;
obj[0] = true;
Object.seal(obj);
assertDoesNotThrow(function() {
Object.defineProperty(obj, 'propertyA', {
value: obj,
});
});
assertEquals(obj, obj.propertyA);
assertDoesNotThrow(function() {
Object.defineProperty(obj, 'propertyA', {
value: obj,
writable: false,
});
});
obj.propertyA = 42;
assertEquals(obj.propertyA, 42);
assertThrows(function() {
Object.defineProperty(obj, 'abc', {
value: obj,
});
}, TypeError);
// Regression test with simple holey array
var arr = [, 'a'];
Object.seal(arr);
arr[1] = 'b';
assertEquals(arr[1], 'b');
arr[0] = 1;
assertEquals(arr[0], undefined);
// Test regression Array.concat with double
var arr = ['a', , 'b'];
Object.seal(arr);
arr = arr.concat(0.5);
assertEquals(arr, ['a', ,'b', 0.5]);
Object.seal(arr);
arr = arr.concat([1.5, 'c']);
assertEquals(arr, ['a', ,'b', 0.5, 1.5, 'c']);
// Regression test with change length
var arr = ['a', ,'b'];
Object.seal(arr);
assertEquals(arr.length, 3);
arr.length = 4;
assertEquals(arr.length, 4);
arr[3] = 'c';
assertEquals(arr[3], undefined);
arr.length = 2;
assertEquals(arr.length, 3);