v8/test/mjsunit/array-join-element-tostring-side-effects.js

153 lines
3.1 KiB
JavaScript
Raw Normal View History

// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
const MIN_DICTIONARY_INDEX = 8192;
function ArrayTests() {
(function ToStringThrows() {
function TestError() {}
let callCount = 0;
const toStringThrows = {
toString() {
callCount++;
throw new TestError;
}
};
const a = [toStringThrows];
assertThrows(() => a.join(), TestError);
assertSame(1, callCount);
// Verifies cycle detection still works properly after thrown error.
a[0] = 1;
a[1] = 2;
assertSame('1,2', a.join());
})();
(function ArrayLengthIncreased() {
let callCount = 0;
const a = [
{
toString() {
callCount++;
a.push(2);
return '1';
}
}
];
assertSame('1', a.join());
assertSame(1, callCount);
assertSame('1,2', a.join());
})();
(function ArrayLengthDecreased() {
let callCount = 0;
const a = [
{
toString() {
callCount++;
a.pop();
return '1';
}
},
'2'
];
assertSame('1,', a.join());
assertSame(1, callCount);
assertSame('1', a.join());
})();
(function ElementsKindChangedToHoley() {
let callCount = 0;
const a = [
{
toString() {
callCount++;
a.length = 4;
a[1] = 777;
a[2] = 7.7;
return '1';
}
},
2,
3
];
assertSame('1,777,7.7', a.join());
assertSame(1, callCount);
assertSame('1,777,7.7,', a.join());
})();
(function ElementsKindChangedToHoleyThroughDeletion() {
let callCount = 0;
const a = [
{
toString() {
callCount++;
delete a[1];
a[2] = 7.7;
return '1';
}
},
2,
3
];
assertSame('1,,7.7', a.join());
assertSame(1, callCount);
assertSame('1,,7.7', a.join());
})();
(function NumberDictionaryChanged() {
let callCount = 0;
const a = [];
a[MIN_DICTIONARY_INDEX - 1] = {
toString() {
callCount++;
a[MIN_DICTIONARY_INDEX] = '2';
return '1';
}
};
a[MIN_DICTIONARY_INDEX] = 'NOPE';
assertTrue(%HasDictionaryElements(a));
assertSame('12', a.join(''));
assertSame(1, callCount);
assertSame('12', a.join(''));
})();
(function NumberDictionaryLengthChange() {
let callCount = 0;
const a = [];
a[MIN_DICTIONARY_INDEX - 1] = {
toString() {
callCount++;
a.length = MIN_DICTIONARY_INDEX;
return '1';
}
};
a[MIN_DICTIONARY_INDEX] = '2';
assertTrue(%HasDictionaryElements(a));
assertSame('1', a.join(''));
assertSame(1, callCount);
assertSame('1', a.join(''));
})();
}
(function NonArrayCycleDetection() {
const a = {
length: 3,
toString() { return Array.prototype.join.call(this); }
};
a[0] = '1';
a[1] = a;
a[2] = '3';
assertSame("1,,3", Array.prototype.join.call(a));
});
ArrayTests();
%SetForceSlowPath(true);
ArrayTests();