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 part of dart2js.js_emitter.startup_emitter.model_emitter; | 5 part of dart2js.js_emitter.startup_emitter.model_emitter; |
6 | 6 |
7 /// The name of the property that stores the tear-off getter on a static | 7 /// The name of the property that stores the tear-off getter on a static |
8 /// function. | 8 /// function. |
9 /// | 9 /// |
10 /// This property is only used when isolates are used. | 10 /// This property is only used when isolates are used. |
(...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 /// | 646 /// |
647 /// The constructor is statically built. | 647 /// The constructor is statically built. |
648 js.Expression emitConstructor(Class cls) { | 648 js.Expression emitConstructor(Class cls) { |
649 js.Name name = cls.name; | 649 js.Name name = cls.name; |
650 // If the class is not directly instantiated we only need it for inheritance | 650 // If the class is not directly instantiated we only need it for inheritance |
651 // or RTI. In either case we don't need its fields. | 651 // or RTI. In either case we don't need its fields. |
652 if (cls.isNative || !cls.isDirectlyInstantiated) { | 652 if (cls.isNative || !cls.isDirectlyInstantiated) { |
653 return js.js('function #() { }', name); | 653 return js.js('function #() { }', name); |
654 } | 654 } |
655 | 655 |
656 List<js.Name> fieldNames = | 656 var statements = <js.Statement>[]; |
657 cls.fields.map((Field field) => field.name).toList(); | 657 var parameters = <js.Name>[]; |
658 if (cls.hasRtiField) { | 658 var thisRef; |
659 fieldNames.add(namer.rtiFieldJsName); | 659 |
| 660 // If there are many references to `this`, cache it in a local. |
| 661 if (cls.fields.length + (cls.hasRtiField ? 1 : 0) >= 4) { |
| 662 // TODO(29455): Fix js_ast printer and minifier to avoid conflicts between |
| 663 // js.Name and string-named variables, then use '_' in the js template |
| 664 // text. |
| 665 |
| 666 // We pick '_' in minified mode because no field minifies to '_'. This |
| 667 // avoids a conflict with one of the parameters which are named the same |
| 668 // as the fields. Unminified, a field might have the name '_', so we pick |
| 669 // '$_', which is an impossible member name since we escape '$'s in names. |
| 670 js.Name underscore = compiler.options.enableMinification |
| 671 ? new StringBackedName('_') |
| 672 : new StringBackedName(r'$_'); |
| 673 statements.add(js.js.statement('var # = this;', underscore)); |
| 674 thisRef = underscore; |
| 675 } else { |
| 676 thisRef = js.js('this'); |
660 } | 677 } |
661 | 678 |
662 Iterable<js.Name> assignments = fieldNames.map((js.Name field) { | 679 for (Field field in cls.fields) { |
663 return js.js("this.#field = #field", {"field": field}); | 680 js.Name paramName = field.name; |
664 }); | 681 parameters.add(paramName); |
| 682 statements |
| 683 .add(js.js.statement('#.# = #', [thisRef, field.name, paramName])); |
| 684 } |
665 | 685 |
666 // TODO(sra): Cache 'this' in a one-character local for 4 or more uses of | 686 if (cls.hasRtiField) { |
667 // 'this'. i.e. "var _=this;_.a=a;_.b=b;..." | 687 js.Name paramName = namer.rtiFieldJsName; |
| 688 parameters.add(paramName); |
| 689 statements.add(js.js |
| 690 .statement('#.# = #', [thisRef, namer.rtiFieldJsName, paramName])); |
| 691 } |
668 | 692 |
669 // TODO(sra): Separate field and field initializer parameter names so the | 693 return js.js('function #(#) { # }', [name, parameters, statements]); |
670 // latter may be fully minified. | |
671 | |
672 return js.js('function #(#) { # }', [name, fieldNames, assignments]); | |
673 } | 694 } |
674 | 695 |
675 /// Emits the prototype-section of the fragment. | 696 /// Emits the prototype-section of the fragment. |
676 /// | 697 /// |
677 /// This section updates the prototype-property of all constructors in the | 698 /// This section updates the prototype-property of all constructors in the |
678 /// global holders. | 699 /// global holders. |
679 js.Statement emitPrototypes(Fragment fragment) { | 700 js.Statement emitPrototypes(Fragment fragment) { |
680 List<js.Statement> assignments = fragment.libraries | 701 List<js.Statement> assignments = fragment.libraries |
681 .expand((Library library) => library.classes) | 702 .expand((Library library) => library.classes) |
682 .map((Class cls) { | 703 .map((Class cls) { |
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1445 } | 1466 } |
1446 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);", | 1467 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);", |
1447 js.objectLiteral(interceptorsByTag))); | 1468 js.objectLiteral(interceptorsByTag))); |
1448 statements.add( | 1469 statements.add( |
1449 js.js.statement("setOrUpdateLeafTags(#);", js.objectLiteral(leafTags))); | 1470 js.js.statement("setOrUpdateLeafTags(#);", js.objectLiteral(leafTags))); |
1450 statements.addAll(subclassAssignments); | 1471 statements.addAll(subclassAssignments); |
1451 | 1472 |
1452 return wrapPhase('nativeSupport', new js.Block(statements)); | 1473 return wrapPhase('nativeSupport', new js.Block(statements)); |
1453 } | 1474 } |
1454 } | 1475 } |
OLD | NEW |