| // 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()); |
| })(); |