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

198 lines
4.0 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 ToStringThrows() {
function TestError() {}
let callCount = 0;
const a = [1, 2];
assertThrows(() => a.join({
toString() {
callCount++;
throw new TestError;
}
}), TestError);
assertSame(1, callCount);
// Verifies cycle detection still works properly after thrown error.
assertSame('1,2', a.join());
})();
(function RecursiveJoinCall() {
const a = [1,2,3];
let callCount = 0;
const sep = {
toString() {
callCount++;
return a.join('-');
}
};
assertSame('11-2-321-2-33', a.join(sep));
assertSame(1, callCount);
// Verify cycle detection works properly after nested call
assertSame('1,2,3', a.join());
})();
(function ArrayLengthIncreased() {
const a = [1,2,3];
let callCount = 0;
assertSame('1,2,3', a.join({
toString() {
callCount++;
a.push(4);
return ',';
}
}));
assertSame(1, callCount);
assertSame('1,2,3,4', a.join());
})();
(function ArrayLengthDecreased() {
const a = [1,2,3];
let callCount = 0;
assertSame('1,2,', a.join({
toString() {
callCount++;
a.pop();
return ',';
}
}));
assertSame(1, callCount);
assertSame('1,2', a.join());
})();
(function ArrayEmptied() {
const a = [1,2,3];
let callCount = 0;
assertSame(',,', a.join({
toString() {
callCount++;
a.length = 0;
return ',';
}
}));
assertSame(1, callCount);
})();
(function NumberDictionaryEmptied() {
const a = [];
a[0] = 1;
a[MIN_DICTIONARY_INDEX] = 2;
assertTrue(%HasDictionaryElements(a));
let callCount = 0;
assertSame('-'.repeat(MIN_DICTIONARY_INDEX), a.join({
toString() {
callCount++;
a.length = 0;
return '-';
}
}));
assertSame(1, callCount);
})();
(function NumberDictionaryEmptiedEmptySeparator() {
const a = [];
a[0] = 1;
a[MIN_DICTIONARY_INDEX] = 2;
assertTrue(%HasDictionaryElements(a));
let callCount = 0;
assertSame(''.repeat(MIN_DICTIONARY_INDEX), a.join({
toString() {
callCount++;
a.length = 0;
return '';
}
}));
assertSame(1, callCount);
})();
(function ElementsKindSmiToDoubles() {
const a = [1,2,3];
let callCount = 0;
assertTrue(%HasSmiElements(a));
assertSame('1.5,2,3', a.join({
toString() {
callCount++;
a[0] = 1.5;
assertTrue(%HasDoubleElements(a));
return ',';
}
}));
assertSame(1, callCount);
assertSame('1.5,2,3', a.join());
})();
(function ElementsKindDoublesToObjects() {
const a = [1.5, 2.5, 3.5];
let callCount = 0;
assertTrue(%HasDoubleElements(a));
assertSame('one,2.5,3.5', a.join({
toString() {
callCount++;
a[0] = 'one';
assertTrue(%HasObjectElements(a));
return ',';
}
}));
assertSame(1, callCount);
assertSame('one,2.5,3.5', a.join());
})();
(function ArrayIsNoLongerFast() {
const a = [1,2,3];
let callCount = 0;
assertSame('666,2,3', a.join({
toString() {
callCount++;
Object.defineProperty(a, '0', {
get(){ return 666; }
});
return ',';
}
}));
assertSame(1, callCount);
assertSame('666,2,3', a.join());
})();
(function ArrayPrototypeUnset() {
const a = [1,2];
a.length = 3;
let callCount = 0;
assertSame('1,2,4', a.join({
toString() {
callCount++;
a.__proto__ = { '2': 4 };
return ',';
}
}));
assertSame(1, callCount);
a.__proto__ = Array.prototype;
assertSame('1,2,', a.join());
})();
(function ArrayPrototypeIsNoLongerFast() {
const a = [1,2,3];
let callCount = 0;
assertSame('1,2,777', a.join({
toString() {
callCount++;
a.pop();
Object.defineProperty(Array.prototype, '2', {
get(){ return 777; }
});
return ',';
}
}));
assertSame(1, callCount);
assertSame('1,2', a.join());
})();