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 /// This library defines the operations that define and manipulate Dart | 5 /// This library defines the operations that define and manipulate Dart |
6 /// classes. Included in this are: | 6 /// classes. Included in this are: |
7 /// - Generics | 7 /// - Generics |
8 /// - Class metadata | 8 /// - Class metadata |
9 /// - Extension methods | 9 /// - Extension methods |
10 /// | 10 /// |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 if ($getGenericClass(T) == futureClass) { | 122 if ($getGenericClass(T) == futureClass) { |
123 let args = $getGenericArgs(T); | 123 let args = $getGenericArgs(T); |
124 if (args) return $builder(args[0]); | 124 if (args) return $builder(args[0]); |
125 } | 125 } |
126 return $builder(T); | 126 return $builder(T); |
127 } | 127 } |
128 return flatten; | 128 return flatten; |
129 })()'''); | 129 })()'''); |
130 | 130 |
131 /// Memoize a generic type constructor function. | 131 /// Memoize a generic type constructor function. |
132 generic(typeConstructor, [setBaseClass]) => JS('', '''(() => { | 132 generic(typeConstructor, setBaseClass) => JS('', '''(() => { |
133 let length = $typeConstructor.length; | 133 let length = $typeConstructor.length; |
134 if (length < 1) { | 134 if (length < 1) { |
135 $throwInternalError('must have at least one generic type argument'); | 135 $throwInternalError('must have at least one generic type argument'); |
136 } | 136 } |
137 let resultMap = new Map(); | 137 let resultMap = new Map(); |
138 function makeGenericType(...args) { | 138 function makeGenericType(...args) { |
139 if (args.length != length && args.length != 0) { | 139 if (args.length != length && args.length != 0) { |
140 $throwInternalError('requires ' + length + ' or 0 type arguments'); | 140 $throwInternalError('requires ' + length + ' or 0 type arguments'); |
141 } | 141 } |
142 while (args.length < length) args.push($dynamic); | 142 while (args.length < length) args.push($dynamic); |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 | 554 |
555 defineEnumValues(enumClass, names) { | 555 defineEnumValues(enumClass, names) { |
556 var values = []; | 556 var values = []; |
557 for (var i = 0; i < JS('int', '#.length', names); i++) { | 557 for (var i = 0; i < JS('int', '#.length', names); i++) { |
558 var value = const_(JS('', 'new #.new(#)', enumClass, i)); | 558 var value = const_(JS('', 'new #.new(#)', enumClass, i)); |
559 JS('', '#.push(#)', values, value); | 559 JS('', '#.push(#)', values, value); |
560 defineValue(enumClass, JS('', '#[#]', names, i), value); | 560 defineValue(enumClass, JS('', '#[#]', names, i), value); |
561 } | 561 } |
562 JS('', '#.values = #', enumClass, constList(values, enumClass)); | 562 JS('', '#.values = #', enumClass, constList(values, enumClass)); |
563 } | 563 } |
| 564 |
| 565 /// Adds type test predicates to a class/interface type [ctor], using the |
| 566 /// provided [isClass] JS Symbol. |
| 567 /// |
| 568 /// This will operate quickly for non-generic types, native extension types, |
| 569 /// as well as matching exact generic type arguments: |
| 570 /// |
| 571 /// class C<T> {} |
| 572 /// class D extends C<int> {} |
| 573 /// main() { dynamic d = new D(); d as C<int>; } |
| 574 /// |
| 575 addTypeTests(ctor, isClass) { |
| 576 if (isClass == null) isClass = JS('', 'Symbol("_is_" + ctor.name)'); |
| 577 // TODO(jmesserly): since we know we're dealing with class/interface types, |
| 578 // we can optimize this rather than go through the generic `dart.is` helpers. |
| 579 JS('', '#.prototype[#] = true', ctor, isClass); |
| 580 JS( |
| 581 '', |
| 582 '''#.is = function is_C(obj) { |
| 583 if (obj != null && obj[#]) return true; |
| 584 return #(obj, this); |
| 585 }''', |
| 586 ctor, |
| 587 isClass, |
| 588 instanceOf); |
| 589 JS( |
| 590 '', |
| 591 '''#.as = function as_C(obj) { |
| 592 if (obj == null || obj[#]) return obj; |
| 593 return #(obj, this, false); |
| 594 }''', |
| 595 ctor, |
| 596 isClass, |
| 597 cast); |
| 598 JS( |
| 599 '', |
| 600 '''#._check = function check_C(obj) { |
| 601 if (obj == null || obj[#]) return obj; |
| 602 return #(obj, this, true); |
| 603 }''', |
| 604 ctor, |
| 605 isClass, |
| 606 cast); |
| 607 } |
| 608 |
| 609 // TODO(jmesserly): should we do this for all interfaces? |
| 610 |
| 611 /// The well known symbol for testing `is Future` |
| 612 final isFuture = JS('', 'Symbol("_is_Future")'); |
| 613 |
| 614 /// The well known symbol for testing `is Iterable` |
| 615 final isIterable = JS('', 'Symbol("_is_Iterable")'); |
| 616 |
| 617 /// The well known symbol for testing `is List` |
| 618 final isList = JS('', 'Symbol("_is_List")'); |
| 619 |
| 620 /// The well known symbol for testing `is Map` |
| 621 final isMap = JS('', 'Symbol("_is_Map")'); |
| 622 |
| 623 /// The well known symbol for testing `is Stream` |
| 624 final isStream = JS('', 'Symbol("_is_Stream")'); |
| 625 |
| 626 /// The well known symbol for testing `is StreamSubscription` |
| 627 final isStreamSubscription = JS('', 'Symbol("_is_StreamSubscription")'); |
OLD | NEW |