| // Copyright 2015 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 |
| |
| // NOTE: |
| // Tests in this file are meant to run in the presence of an invalidated |
| // NoElementsProtector, as effected by the following line. |
| Array.prototype[0] = 42; |
| delete Array.prototype[0]; |
| |
| |
| (function TestBasics() { |
| var a = [1, 2]; |
| var b = [...a]; |
| assertArrayEquals([1, 2], b) |
| |
| assertArrayEquals(['a', 'b', 'c', 'd', 'e', 'f'], |
| ['a', ...'bc', 'd', ...'ef']) |
| })(); |
| |
| |
| var log = []; |
| |
| function* gen(n) { |
| log.push(n, 1); |
| yield 1; |
| log.push(n, 2); |
| yield 2; |
| log.push(n, 3); |
| yield 3; |
| log.push(n, 'done'); |
| } |
| |
| function id(v) { |
| log.push(v); |
| return v; |
| } |
| |
| |
| (function TestGenerator() { |
| assertArrayEquals([1, 2, 3], [...gen('a')]); |
| assertArrayEquals(['x', 1, 2, 3, 'y', 1, 2, 3, 'z'], |
| ['x', ...gen('a'), 'y', ...gen('b'), 'z']); |
| })(); |
| |
| |
| (function TestOrderOfExecution() { |
| log = []; |
| assertArrayEquals(['x', 1, 2, 3, 'y', 1, 2, 3, 'z'], |
| [id('x'), ...gen('a'), id('y'), ...gen('b'), id('z')]); |
| assertArrayEquals([ |
| 'x', 'a', 1, 'a', 2, 'a', 3, 'a', 'done', |
| 'y', 'b', 1, 'b', 2, 'b', 3, 'b', 'done', |
| 'z' |
| ], log); |
| })(); |
| |
| |
| (function TestNotIterable() { |
| var a; |
| assertThrows(function() { |
| a = [...42]; |
| }, TypeError); |
| assertSame(undefined, a); |
| |
| |
| })(); |
| |
| |
| (function TestInvalidIterator() { |
| var iter = { |
| [Symbol.iterator]: 42 |
| }; |
| var a; |
| assertThrows(function() { |
| a = [...iter]; |
| }, TypeError); |
| assertSame(undefined, a); |
| })(); |
| |
| |
| (function TestIteratorNotAnObject() { |
| var iter = { |
| [Symbol.iterator]() { |
| return 42; |
| } |
| }; |
| var a; |
| assertThrows(function() { |
| a = [...iter]; |
| }, TypeError); |
| assertSame(undefined, a); |
| })(); |
| |
| |
| (function TestIteratorNoNext() { |
| var iter = { |
| [Symbol.iterator]() { |
| return {}; |
| } |
| }; |
| var a; |
| assertThrows(function() { |
| a = [...iter]; |
| }, TypeError); |
| assertSame(undefined, a); |
| })(); |
| |
| |
| (function TestIteratorResultDoneThrows() { |
| function MyError() {} |
| var iter = { |
| [Symbol.iterator]() { |
| return { |
| next() { |
| return { |
| get done() { |
| throw new MyError(); |
| } |
| } |
| } |
| }; |
| } |
| }; |
| var a; |
| assertThrows(function() { |
| a = [...iter]; |
| }, MyError); |
| assertSame(undefined, a); |
| })(); |
| |
| |
| (function TestIteratorResultValueThrows() { |
| function MyError() {} |
| var iter = { |
| [Symbol.iterator]() { |
| return { |
| next() { |
| return { |
| done: false, |
| get value() { |
| throw new MyError(); |
| } |
| } |
| } |
| }; |
| } |
| }; |
| var a; |
| assertThrows(function() { |
| a = [...iter]; |
| }, MyError); |
| assertSame(undefined, a); |
| })(); |
| |
| |
| (function TestOptimize() { |
| function f() { |
| return [...'abc']; |
| } |
| %PrepareFunctionForOptimization(f); |
| assertArrayEquals(['a', 'b', 'c'], f()); |
| %OptimizeFunctionOnNextCall(f); |
| assertArrayEquals(['a', 'b', 'c'], f()); |
| })(); |
| |
| |
| (function TestDeoptimize() { |
| var iter = { |
| [Symbol.iterator]() { |
| var i = 0; |
| return { |
| next() { |
| %DeoptimizeFunction(f); |
| return {value: ++i, done: i === 3}; |
| } |
| }; |
| } |
| }; |
| function f() { |
| return [0, ...iter]; |
| } |
| |
| assertArrayEquals([0, 1, 2], f()); |
| })(); |
| |
| |
| (function TestPrototypeSetter1() { |
| Object.defineProperty(Array.prototype, 3, {set() {throw 666}}) |
| Object.defineProperty(Array.prototype, 4, {set() {throw 666}}) |
| |
| function f() { |
| return ['a', ...['b', 'c', 'd'], 'e'] |
| } |
| |
| %PrepareFunctionForOptimization(f); |
| assertArrayEquals(['a', 'b', 'c', 'd', 'e'], f()); |
| %OptimizeFunctionOnNextCall(f); |
| assertArrayEquals(['a', 'b', 'c', 'd', 'e'], f()); |
| |
| delete Array.prototype[3]; |
| delete Array.prototype[4]; |
| })(); |
| |
| |
| (function TestPrototypeSetter2() { |
| Object.defineProperty(Array.prototype.__proto__, 3, {set() {throw 666}}) |
| Object.defineProperty(Array.prototype.__proto__, 4, {set() {throw 666}}) |
| |
| function f() { |
| return ['a', ...['b', 'c', 'd'], 'e'] |
| } |
| |
| %PrepareFunctionForOptimization(f); |
| assertArrayEquals(['a', 'b', 'c', 'd', 'e'], f()); |
| %OptimizeFunctionOnNextCall(f); |
| assertArrayEquals(['a', 'b', 'c', 'd', 'e'], f()); |
| |
| delete Array.prototype.__proto__[3]; |
| delete Array.prototype.__proto__[4]; |
| })(); |
| |
| |
| (function TestPrototypeProxy() { |
| const backup = Array.prototype.__proto__; |
| Array.prototype.__proto__ = new Proxy({}, {set() {throw 666}}); |
| |
| function f() { |
| return ['a', ...['b', 'c', 'd'], 'e'] |
| } |
| |
| %PrepareFunctionForOptimization(f); |
| assertArrayEquals(['a', 'b', 'c', 'd', 'e'], f()); |
| %OptimizeFunctionOnNextCall(f); |
| assertArrayEquals(['a', 'b', 'c', 'd', 'e'], f()); |
| |
| Object.setPrototypeOf(Array.prototype, backup); |
| })(); |