952c097679
This also includes ports of Array.p.toString and Array.p.toLocaleString. Many parts of the old JS implementation are preserved, because TypedArray.p.join still relies on it. These will be removed once TypedArray.p.join is ported to Torque. To simplify implementation, special handling of extremely sparse arrays has been removed. Performance improvements vary by array size, elements, and sparse-ness. Some quick numbers and graphs are here: https://docs.google.com/spreadsheets/d/125VLmRMudk8XaomLCsZQ1ewc94WCqht-8GQwU3s9BW8/edit#gid=2087673710 Cq-Include-Trybots: luci.chromium.try:linux_chromium_headless_rel;luci.v8.try:v8_linux_noi18n_rel_ng;master.tryserver.blink:linux_trusty_blink_rel Change-Id: Ia4069a068403ce36676c37401d349aefc976b045 Reviewed-on: https://chromium-review.googlesource.com/c/1196693 Commit-Queue: Peter Wong <peter.wm.wong@gmail.com> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#56699}
198 lines
4.0 KiB
JavaScript
198 lines
4.0 KiB
JavaScript
// 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());
|
|
})();
|