| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 var assert = chai.assert; | 5 var assert = chai.assert; |
| 6 | 6 |
| 7 suite('dart_runtime generic', function() { | 7 suite('generic', () => { |
| 8 "use strict"; | 8 "use strict"; |
| 9 | 9 |
| 10 var generic = dart.generic; | 10 let generic = dart.generic; |
| 11 | 11 |
| 12 test('zero arguments is not allowed', function() { | 12 test('zero arguments is not allowed', () => { |
| 13 assert.throws(function() { generic(function(){}); }); | 13 assert.throws(() => { generic(function(){}); }); |
| 14 }); | 14 }); |
| 15 | 15 |
| 16 test('argument count cannot change', function() { | 16 test('argument count cannot change', () => { |
| 17 var SomeType = generic(function(x) {}); | 17 let SomeType = generic(function(x) { return {x: x}; }); |
| 18 assert.throws(function() { SomeType(1,2) }); | 18 assert.throws(() => { SomeType(1,2) }); |
| 19 SomeType(1); | 19 let obj = {}; |
| 20 SomeType(1); | 20 assert.equal(SomeType(obj).x, obj); |
| 21 assert.throws(function() { SomeType() }); | 21 assert.equal(SomeType(obj).x, obj); |
| 22 SomeType(1); | 22 assert.equal(SomeType().x, dart.dynamic); |
| 23 }); | 23 }); |
| 24 | 24 |
| 25 test('undefined is not allowed as an argument', function() { | 25 test('undefined/null are not allowed', () => { |
| 26 var SomeType = generic(function(x) {}); | 26 let SomeType = generic(function(x) {}); |
| 27 assert.throws(function() { SomeType(void 0) }); | 27 assert.throws(() => { SomeType(void 0) }); |
| 28 SomeType(1); | 28 SomeType(1); |
| 29 assert.throws(function() { SomeType(void 0) }); | 29 assert.throws(() => { SomeType(void 0) }); |
| 30 SomeType(1); | 30 SomeType(1); |
| 31 SomeType(null); | 31 assert.throws(() => { SomeType(null) }); |
| 32 }); | 32 }); |
| 33 | 33 |
| 34 test('result is memoized', function() { | 34 test('result is memoized', () => { |
| 35 var t1 = Object.create(null); | 35 let t1 = Object.create(null); |
| 36 var t2 = Object.create(null); | 36 let t2 = Object.create(null); |
| 37 | 37 |
| 38 var count = 0; | 38 let count = 0; |
| 39 var SomeType = generic(function(x, y) { | 39 let SomeType = generic(function(x, y) { |
| 40 count++; | 40 count++; |
| 41 return Object.create(null); | 41 return Object.create(null); |
| 42 }); | 42 }); |
| 43 | 43 |
| 44 var x12 = SomeType(1, 2); | 44 let x12 = SomeType(1, 2); |
| 45 assert.strictEqual(SomeType(1, 2), x12); | 45 assert.strictEqual(SomeType(1, 2), x12); |
| 46 assert.strictEqual(SomeType(1, 2), x12); | 46 assert.strictEqual(SomeType(1, 2), x12); |
| 47 assert.strictEqual(count, 1); | 47 assert.strictEqual(count, 1); |
| 48 var x11 = SomeType(1, 1); | 48 let x11 = SomeType(1, 1); |
| 49 assert.strictEqual(count, 2); | 49 assert.strictEqual(count, 2); |
| 50 assert.strictEqual(SomeType(1, 1), x11); | 50 assert.strictEqual(SomeType(1, 1), x11); |
| 51 assert.strictEqual(count, 2); | 51 assert.strictEqual(count, 2); |
| 52 count = 0; | 52 count = 0; |
| 53 | 53 |
| 54 var t1t2 = SomeType(t1, t2); | 54 let t1t2 = SomeType(t1, t2); |
| 55 assert.strictEqual(count, 1); | 55 assert.strictEqual(count, 1); |
| 56 var t2t1 = SomeType(t2, t1); | 56 let t2t1 = SomeType(t2, t1); |
| 57 assert.strictEqual(count, 2); | 57 assert.strictEqual(count, 2); |
| 58 assert.notStrictEqual(t1t2, t2t1); | 58 assert.notStrictEqual(t1t2, t2t1); |
| 59 assert.strictEqual(SomeType(t1, t2), t1t2); | 59 assert.strictEqual(SomeType(t1, t2), t1t2); |
| 60 assert.strictEqual(SomeType(t2, t1), t2t1); | 60 assert.strictEqual(SomeType(t2, t1), t2t1); |
| 61 assert.strictEqual(SomeType(t1, t2), t1t2); | 61 assert.strictEqual(SomeType(t1, t2), t1t2); |
| 62 count = 0; | 62 count = 0; |
| 63 | 63 |
| 64 var nullKeys = SomeType(null, null); | |
| 65 assert.strictEqual(SomeType(null, null), nullKeys); | |
| 66 assert.strictEqual(count, 1); | |
| 67 count = 0; | |
| 68 | |
| 69 // Nothing has been stored on the object | 64 // Nothing has been stored on the object |
| 70 assert.strictEqual(Object.keys(t1).length, 0); | 65 assert.strictEqual(Object.keys(t1).length, 0); |
| 71 assert.strictEqual(Object.keys(t2).length, 0); | 66 assert.strictEqual(Object.keys(t2).length, 0); |
| 72 }); | 67 }); |
| 73 | 68 |
| 74 test('type constructor is reflectable', function() { | 69 test('type constructor is reflectable', () => { |
| 75 var SomeType = generic(function(x, y) { return Object.create(null); }); | 70 let SomeType = generic(function(x, y) { return Object.create(null); }); |
| 76 var someValue = SomeType('hi', 123); | 71 let someValue = SomeType('hi', 123); |
| 77 assert.deepEqual(someValue[dart.typeSignature], [SomeType, 'hi', 123]); | 72 assert.equal(someValue[dart.originalDeclaration], SomeType); |
| 73 assert.deepEqual(someValue[dart.typeArguments], ['hi', 123]); |
| 78 }); | 74 }); |
| 79 }); | 75 }); |
| 76 |
| 77 |
| 78 suite('instanceOf', () => { |
| 79 "use strict"; |
| 80 |
| 81 let expect = assert.equal; |
| 82 let isGroundType = dart.isGroundType; |
| 83 let generic = dart.generic; |
| 84 let intIsNonNullable = false; |
| 85 let cast = dart.as; |
| 86 let instanceOf = dart.is; |
| 87 let getRuntimeType = dart.getRuntimeType; |
| 88 |
| 89 let Object = core.Object; |
| 90 let String = core.String; |
| 91 let dynamic = dart.dynamic; |
| 92 let List = core.List; |
| 93 let Map = core.Map; |
| 94 let Map$ = core.Map$; |
| 95 let int = core.int; |
| 96 let num = core.num; |
| 97 let bool = core.bool; |
| 98 |
| 99 class A {} |
| 100 class B extends A {} |
| 101 class C extends B {} |
| 102 |
| 103 let AA$ = generic((T, U) => class AA extends core.Object {}); |
| 104 let AA = AA$(); |
| 105 let BB$ = generic((T, U) => class BB extends AA$(U, T) {}); |
| 106 let BB = BB$(); |
| 107 class CC extends BB$(String, List) {} |
| 108 |
| 109 function checkType(x, type, expectedTrue) { |
| 110 if (expectedTrue === undefined) expectedTrue = true; |
| 111 expect(instanceOf(x, type), expectedTrue); |
| 112 } |
| 113 |
| 114 test('int', () => { |
| 115 expect(isGroundType(int), true); |
| 116 expect(isGroundType(getRuntimeType(5)), true); |
| 117 |
| 118 checkType(5, int); |
| 119 checkType(5, dynamic); |
| 120 checkType(5, Object); |
| 121 checkType(5, num); |
| 122 |
| 123 checkType(5, bool, false); |
| 124 checkType(5, String, false); |
| 125 |
| 126 expect(cast(5, int), 5); |
| 127 if (intIsNonNullable) { |
| 128 expect(() => cast(null, int), throws); |
| 129 } else { |
| 130 expect(cast(null, int), null); |
| 131 } |
| 132 }); |
| 133 |
| 134 test('dynamic', () => { |
| 135 expect(isGroundType(dynamic), true); |
| 136 checkType(new Object(), dynamic); |
| 137 checkType(null, dynamic); |
| 138 |
| 139 expect(cast(null, dynamic), null); |
| 140 }); |
| 141 |
| 142 test('Object', () => { |
| 143 expect(isGroundType(Object), true); |
| 144 checkType(new Object(), dynamic); |
| 145 checkType(null, Object); |
| 146 |
| 147 expect(cast(null, Object), null); |
| 148 }); |
| 149 |
| 150 test('null', () => { |
| 151 // Object, dynamic cases are already handled above. |
| 152 checkType(null, core.Null); |
| 153 checkType(void 0, core.Null); |
| 154 checkType(void 0, core.Object); |
| 155 checkType(void 0, dart.dynamic); |
| 156 }); |
| 157 |
| 158 test('String', () => { |
| 159 expect(isGroundType(String), true); |
| 160 expect(isGroundType(getRuntimeType("foo")), true); |
| 161 checkType("foo", String); |
| 162 checkType("foo", Object); |
| 163 checkType("foo", dynamic); |
| 164 |
| 165 expect(cast(null, String), null); |
| 166 }); |
| 167 |
| 168 test('Map', () => { |
| 169 let m1 = new (Map$(String, String))(); |
| 170 let m2 = new (Map$(Object, Object))(); |
| 171 let m3 = new Map(); |
| 172 let m4 = new (collection.HashMap$(dart.dynamic, dart.dynamic))(); |
| 173 let m5 = new collection.LinkedHashMap(); |
| 174 |
| 175 expect(isGroundType(Map), true); |
| 176 expect(isGroundType(getRuntimeType(m1)), false); |
| 177 expect(isGroundType(Map$(String, String)), false); |
| 178 expect(isGroundType(getRuntimeType(m2)), true); |
| 179 expect(isGroundType(Map$(Object, Object)), true); |
| 180 expect(isGroundType(getRuntimeType(m3)), true); |
| 181 expect(isGroundType(Map), true); |
| 182 expect(isGroundType(getRuntimeType(m4)), true); |
| 183 expect(isGroundType(collection.HashMap$(dynamic, dynamic)), true); |
| 184 expect(isGroundType(getRuntimeType(m5)), true); |
| 185 expect(isGroundType(collection.LinkedHashMap), true); |
| 186 expect(isGroundType(collection.LinkedHashMap), true); |
| 187 |
| 188 // Map<T1,T2> <: Map |
| 189 checkType(m1, Map); |
| 190 checkType(m1, Object); |
| 191 |
| 192 // Instance of self |
| 193 checkType(m1, getRuntimeType(m1)); |
| 194 checkType(m1, Map$(String, String)); |
| 195 |
| 196 // Covariance on generics |
| 197 checkType(m1, getRuntimeType(m2)); |
| 198 checkType(m1, Map$(Object, Object)); |
| 199 |
| 200 // No contravariance on generics. |
| 201 checkType(m2, getRuntimeType(m1), false); |
| 202 checkType(m2, Map$(String, String), false); |
| 203 |
| 204 // null is! Map |
| 205 checkType(null, Map, false); |
| 206 |
| 207 // Raw generic types |
| 208 checkType(m5, Map); |
| 209 checkType(m4, Map); |
| 210 }); |
| 211 |
| 212 test('generic and inheritance', () => { |
| 213 let aaraw = new AA(); |
| 214 let aarawtype = getRuntimeType(aaraw); |
| 215 let aadynamic = new (AA$(dynamic, dynamic))(); |
| 216 let aadynamictype = getRuntimeType(aadynamic); |
| 217 let aa = new (AA$(String, List))(); |
| 218 let aatype = getRuntimeType(aa); |
| 219 let bb = new (BB$(String, List))(); |
| 220 let bbtype = getRuntimeType(bb); |
| 221 let cc = new CC(); |
| 222 let cctype = getRuntimeType(cc); |
| 223 // We don't allow constructing bad types. |
| 224 // This was AA<String> in Dart (wrong number of type args). |
| 225 let aabad = new (AA$(dart.dynamic, dart.dynamic))(); |
| 226 let aabadtype = getRuntimeType(aabad); |
| 227 |
| 228 expect(isGroundType(aatype), false); |
| 229 expect(isGroundType(AA$(String, List)), false); |
| 230 expect(isGroundType(bbtype), false); |
| 231 expect(isGroundType(BB$(String, List)), false); |
| 232 expect(isGroundType(cctype), true); |
| 233 expect(isGroundType(CC), true); |
| 234 checkType(cc, aatype, false); |
| 235 checkType(cc, AA$(String, List), false); |
| 236 checkType(cc, bbtype); |
| 237 checkType(cc, BB$(String, List)); |
| 238 checkType(aa, cctype, false); |
| 239 checkType(aa, CC, false); |
| 240 checkType(aa, bbtype, false); |
| 241 checkType(aa, BB$(String, List), false); |
| 242 checkType(bb, cctype, false); |
| 243 checkType(bb, CC, false); |
| 244 checkType(aa, aabadtype); |
| 245 checkType(aa, dynamic); |
| 246 checkType(aabad, aatype, false); |
| 247 checkType(aabad, AA$(String, List), false); |
| 248 checkType(aabad, aarawtype); |
| 249 checkType(aabad, AA); |
| 250 checkType(aaraw, aabadtype); |
| 251 checkType(aaraw, AA$(dart.dynamic, dart.dynamic)); |
| 252 checkType(aaraw, aadynamictype); |
| 253 checkType(aaraw, AA$(dynamic, dynamic)); |
| 254 checkType(aadynamic, aarawtype); |
| 255 checkType(aadynamic, AA); |
| 256 }); |
| 257 |
| 258 test('void', () => { |
| 259 //checkType((x) => x, type((void _(x)) {})); |
| 260 }); |
| 261 |
| 262 }); |
| OLD | NEW |