| // Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | import 'dart:typed_data'; | 
 |  | 
 | import 'package:expect/expect.dart'; | 
 |  | 
 | // Check that NaN is detected as an invalid index for system Lists, Strings and | 
 | // typed lists. | 
 | // | 
 | // There are several methods called `dynamicCallN` for various N that are called | 
 | // with different indexable collection implementations to exercise various | 
 | // dart2js optimizations based on knowing (or not knowing) the concrete type of | 
 | // the List argument. | 
 |  | 
 | void main() { | 
 |   int nan = makeIntNaN(); | 
 |   Expect.isFalse(nan <= 0); | 
 |   Expect.isFalse(nan >= 0); | 
 |  | 
 |   List<int> ints = [1, 2, 3, 4]; | 
 |   final bytes = Uint8List(3) | 
 |     ..[0] = 100 | 
 |     ..[1] = 101 | 
 |     ..[2] = 102; | 
 |   final words = Int16List(3) | 
 |     ..[0] = 16000 | 
 |     ..[1] = 16001 | 
 |     ..[2] = 16002; | 
 |  | 
 |   Expect.throws(() => ints[nan], anyError, 'List[nan]'); | 
 |   Expect.throws(() => 'abc'[nan], anyError, 'String[nan]'); | 
 |   Expect.throws(() => bytes[nan], anyError, 'UInt8List[nan]'); | 
 |   Expect.throws(() => words[nan], anyError, 'Int16List[nan]'); | 
 |  | 
 |   // [dynamicCall1] Seeded with JSIndexable and Map, so is doing a complete | 
 |   // interceptor dispatch. | 
 |   Expect.equals(2, dynamicCall1(ints, 1)); | 
 |   Expect.equals('b', dynamicCall1('abc', 1)); | 
 |   Expect.equals(2, dynamicCall1({'a': 1, 'b': 2, 'c': 3}, 'b')); | 
 |  | 
 |   Expect.throws(() => dynamicCall1(ints, nan), anyError, 'dynamic List'); | 
 |   Expect.throws(() => dynamicCall1('AB', nan), anyError, 'dynamic String'); | 
 |   Expect.throws(() => dynamicCall1(bytes, nan), anyError, 'dynamic Uint8List'); | 
 |   Expect.throws(() => dynamicCall1(words, nan), anyError, 'dynamic Int16list'); | 
 |  | 
 |   var a = <int>[]; | 
 |   Expect.throws(() => a.removeLast(), contains('-1')); | 
 |  | 
 |   // [dynamicCall2] seeded with JSIndexable only, so can be optimized to a | 
 |   // JavaScript indexing operation. | 
 |   Expect.equals(2, dynamicCall2(ints, 1)); | 
 |   Expect.equals('b', dynamicCall2('abc', 1)); | 
 |  | 
 |   Expect.throws(() => dynamicCall2(ints, nan), anyError, 'JSIndexable List'); | 
 |   Expect.throws(() => dynamicCall2('AB', nan), anyError, 'JSIndexable String'); | 
 |  | 
 |   // [dynamicCall3] Seeded with List of known length only, various indexes. The | 
 |   // upper bound is fixed. | 
 |   Expect.throws(() => dynamicCall3(ints, nan), anyError, 'known length nan'); | 
 |   Expect.throws(() => dynamicCall3(ints, null), anyError, 'known length null'); | 
 |  | 
 |   // [dynamicCall4] Seeded with List of known length only. | 
 |   Expect.throws(() => dynamicCall4(ints, nan), anyError, 'dynamic[] List'); | 
 |  | 
 |   // [dynamicCall5] Seeded with List of unknown length only. | 
 |   Expect.throws(() => dynamicCall5(ints, nan), anyError, 'dynamic[] List'); | 
 |   Expect.throws(() => dynamicCall5(a, nan), anyError, 'dynamic[] List'); | 
 |  | 
 |   // [dynamicCall6] Seeded with Uint8List only. | 
 |   Expect.throws(() => dynamicCall6(bytes, nan), anyError, 'dynamic Uint8List'); | 
 | } | 
 |  | 
 | bool anyError(error) => true; | 
 |  | 
 | bool Function(dynamic) contains(Pattern pattern) => | 
 |     (error) => '$error'.contains(pattern); | 
 |  | 
 | @pragma('dart2js:noInline') | 
 | dynamic dynamicCall1(dynamic indexable, dynamic index) { | 
 |   return indexable[index]; | 
 | } | 
 |  | 
 | @pragma('dart2js:noInline') | 
 | dynamic dynamicCall2(dynamic indexable, dynamic index) { | 
 |   return indexable[index]; | 
 | } | 
 |  | 
 | @pragma('dart2js:noInline') | 
 | dynamic dynamicCall3(dynamic indexable, dynamic index) { | 
 |   return indexable[index]; | 
 | } | 
 |  | 
 | @pragma('dart2js:noInline') | 
 | dynamic dynamicCall4(dynamic indexable, dynamic index) { | 
 |   return indexable[index]; | 
 | } | 
 |  | 
 | @pragma('dart2js:noInline') | 
 | dynamic dynamicCall5(dynamic indexable, dynamic index) { | 
 |   return indexable[index]; | 
 | } | 
 |  | 
 | @pragma('dart2js:noInline') | 
 | dynamic dynamicCall6(dynamic indexable, dynamic index) { | 
 |   return indexable[index]; | 
 | } | 
 |  | 
 | int makeIntNaN() { | 
 |   int n = 2; | 
 |   // Overflow to Infinity. | 
 |   for (int i = 0; i < 10; i++, n *= n) {} | 
 |   // Infinity - Infinity = NaN. | 
 |   return n - n; | 
 | } |