 Chromium Code Reviews
 Chromium Code Reviews Issue 1156993015:
  fixes #193, factory constructors as static methods  (Closed) 
  Base URL: git@github.com:dart-lang/dev_compiler.git@master
    
  
    Issue 1156993015:
  fixes #193, factory constructors as static methods  (Closed) 
  Base URL: git@github.com:dart-lang/dev_compiler.git@master| 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 library dev_compiler.src.codegen.js_codegen; | 5 library dev_compiler.src.codegen.js_codegen; | 
| 6 | 6 | 
| 7 import 'dart:collection' show HashSet, HashMap; | 7 import 'dart:collection' show HashSet, HashMap; | 
| 8 | 8 | 
| 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 
| 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 | 460 | 
| 461 _loader.finishTopLevel(element); | 461 _loader.finishTopLevel(element); | 
| 462 return heritage; | 462 return heritage; | 
| 463 } | 463 } | 
| 464 | 464 | 
| 465 List<JS.Method> _emitClassMethods(ClassDeclaration node, | 465 List<JS.Method> _emitClassMethods(ClassDeclaration node, | 
| 466 List<ConstructorDeclaration> ctors, List<FieldDeclaration> fields) { | 466 List<ConstructorDeclaration> ctors, List<FieldDeclaration> fields) { | 
| 467 var element = node.element; | 467 var element = node.element; | 
| 468 var type = element.type; | 468 var type = element.type; | 
| 469 var isObject = type.isObject; | 469 var isObject = type.isObject; | 
| 470 var name = node.name.name; | |
| 471 | 470 | 
| 472 // Iff no constructor is specified for a class C, it implicitly has a | 471 // Iff no constructor is specified for a class C, it implicitly has a | 
| 473 // default constructor `C() : super() {}`, unless C is class Object. | 472 // default constructor `C() : super() {}`, unless C is class Object. | 
| 474 var jsMethods = <JS.Method>[]; | 473 var jsMethods = <JS.Method>[]; | 
| 475 if (ctors.isEmpty && !isObject) { | 474 if (ctors.isEmpty && !isObject) { | 
| 476 jsMethods.add(_emitImplicitConstructor(node, name, fields)); | 475 jsMethods.add(_emitImplicitConstructor(node, fields)); | 
| 477 } | 476 } | 
| 478 | 477 | 
| 479 bool hasJsPeer = getAnnotationValue(node, _isJsPeerInterface) != null; | 478 bool hasJsPeer = getAnnotationValue(node, _isJsPeerInterface) != null; | 
| 480 | 479 | 
| 481 bool hasIterator = false; | 480 bool hasIterator = false; | 
| 482 for (var m in node.members) { | 481 for (var m in node.members) { | 
| 483 if (m is ConstructorDeclaration) { | 482 if (m is ConstructorDeclaration) { | 
| 484 jsMethods.add(_emitConstructor(m, name, fields, isObject)); | 483 jsMethods.add(_emitConstructor(m, type, fields, isObject)); | 
| 485 } else if (m is MethodDeclaration) { | 484 } else if (m is MethodDeclaration) { | 
| 486 jsMethods.add(_emitMethodDeclaration(type, m)); | 485 jsMethods.add(_emitMethodDeclaration(type, m)); | 
| 487 | 486 | 
| 488 if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') { | 487 if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') { | 
| 489 hasIterator = true; | 488 hasIterator = true; | 
| 490 jsMethods.add(_emitIterable(type)); | 489 jsMethods.add(_emitIterable(type)); | 
| 491 } | 490 } | 
| 492 } | 491 } | 
| 493 } | 492 } | 
| 494 | 493 | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 557 if (classElem.interfaces.isNotEmpty) { | 556 if (classElem.interfaces.isNotEmpty) { | 
| 558 body.add(js.statement('#[dart.implements] = () => #;', [ | 557 body.add(js.statement('#[dart.implements] = () => #;', [ | 
| 559 name, | 558 name, | 
| 560 new JS.ArrayInitializer( | 559 new JS.ArrayInitializer( | 
| 561 classElem.interfaces.map(_emitTypeName).toList()) | 560 classElem.interfaces.map(_emitTypeName).toList()) | 
| 562 ])); | 561 ])); | 
| 563 } | 562 } | 
| 564 | 563 | 
| 565 // Named constructors | 564 // Named constructors | 
| 566 for (ConstructorDeclaration member in ctors) { | 565 for (ConstructorDeclaration member in ctors) { | 
| 567 if (member.name != null) { | 566 if (member.name != null && member.factoryKeyword == null) { | 
| 568 body.add(js.statement('dart.defineNamedConstructor(#, #);', [ | 567 body.add(js.statement('dart.defineNamedConstructor(#, #);', [ | 
| 569 name, | 568 name, | 
| 570 _emitMemberName(member.name.name, isStatic: true) | 569 _emitMemberName(member.name.name, isStatic: true) | 
| 571 ])); | 570 ])); | 
| 572 } | 571 } | 
| 573 } | 572 } | 
| 574 | 573 | 
| 575 // Instance fields, if they override getter/setter pairs | 574 // Instance fields, if they override getter/setter pairs | 
| 576 for (FieldDeclaration member in fields) { | 575 for (FieldDeclaration member in fields) { | 
| 577 for (VariableDeclaration fieldDecl in member.fields.variables) { | 576 for (VariableDeclaration fieldDecl in member.fields.variables) { | 
| (...skipping 26 matching lines...) Expand all Loading... | |
| 604 var property = | 603 var property = | 
| 605 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 604 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 
| 606 if (node.isStatic) { | 605 if (node.isStatic) { | 
| 607 tStatics.add(property); | 606 tStatics.add(property); | 
| 608 sNames.add(memberName); | 607 sNames.add(memberName); | 
| 609 } else tMethods.add(property); | 608 } else tMethods.add(property); | 
| 610 } | 609 } | 
| 611 } | 610 } | 
| 612 var tCtors = []; | 611 var tCtors = []; | 
| 613 for (ConstructorDeclaration node in ctors) { | 612 for (ConstructorDeclaration node in ctors) { | 
| 614 var memberName = _constructorName(classElem.name, node.name); | 613 var memberName = _constructorName(node.element); | 
| 615 var element = node.element; | 614 var element = node.element; | 
| 616 var parts = | 615 var parts = | 
| 617 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); | 616 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); | 
| 618 var property = | 617 var property = | 
| 619 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 618 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 
| 620 tCtors.add(property); | 619 tCtors.add(property); | 
| 621 } | 620 } | 
| 622 build(name, elements) { | 621 build(name, elements) { | 
| 623 var o = | 622 var o = | 
| 624 new JS.ObjectInitializer(elements, vertical: elements.length > 1); | 623 new JS.ObjectInitializer(elements, vertical: elements.length > 1); | 
| (...skipping 25 matching lines...) Expand all Loading... | |
| 650 var cls = e.enclosingElement; | 649 var cls = e.enclosingElement; | 
| 651 return js.statement('dart.virtualField(#, #)', [ | 650 return js.statement('dart.virtualField(#, #)', [ | 
| 652 cls.name, | 651 cls.name, | 
| 653 _emitMemberName(e.name, type: cls.type) | 652 _emitMemberName(e.name, type: cls.type) | 
| 654 ]); | 653 ]); | 
| 655 } | 654 } | 
| 656 | 655 | 
| 657 /// Generates the implicit default constructor for class C of the form | 656 /// Generates the implicit default constructor for class C of the form | 
| 658 /// `C() : super() {}`. | 657 /// `C() : super() {}`. | 
| 659 JS.Method _emitImplicitConstructor( | 658 JS.Method _emitImplicitConstructor( | 
| 660 ClassDeclaration node, String name, List<FieldDeclaration> fields) { | 659 ClassDeclaration node, List<FieldDeclaration> fields) { | 
| 661 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty); | 660 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty); | 
| 662 | 661 | 
| 663 // If we don't have a method body, skip this. | 662 // If we don't have a method body, skip this. | 
| 664 var superCall = _superConstructorCall(node); | 663 var superCall = _superConstructorCall(node.element); | 
| 665 if (fields.isEmpty && superCall == null) return null; | 664 if (fields.isEmpty && superCall == null) return null; | 
| 666 | 665 | 
| 667 dynamic body = _initializeFields(node, fields); | 666 dynamic body = _initializeFields(node, fields); | 
| 668 if (superCall != null) body = [[body, superCall]]; | 667 if (superCall != null) body = [[body, superCall]]; | 
| 669 return new JS.Method( | 668 var name = _constructorName(node.element.unnamedConstructor); | 
| 670 _propertyName(name), js.call('function() { #; }', body)); | 669 return new JS.Method(name, js.call('function() { #; }', body)); | 
| 671 } | 670 } | 
| 672 | 671 | 
| 673 JS.Method _emitConstructor(ConstructorDeclaration node, String className, | 672 JS.Method _emitConstructor(ConstructorDeclaration node, InterfaceType type, | 
| 674 List<FieldDeclaration> fields, bool isObject) { | 673 List<FieldDeclaration> fields, bool isObject) { | 
| 675 if (_externalOrNative(node)) return null; | 674 if (_externalOrNative(node)) return null; | 
| 676 | 675 | 
| 677 var name = _constructorName(className, node.name); | 676 var name = _constructorName(node.element); | 
| 677 | |
| 678 // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz; | |
| 
Jennifer Messerly
2015/05/29 19:54:53
this code moved from _emitConstructorBody, which w
 | |
| 679 var redirect = node.redirectedConstructor; | |
| 680 if (redirect != null) { | |
| 681 var newKeyword = redirect.staticElement.isFactory ? '' : 'new'; | |
| 682 // Pass along all arguments verbatim, and let the callee handle them. | |
| 683 // TODO(jmesserly): we'll need something different once we have | |
| 684 // rest/spread support, but this should work for now. | |
| 685 var params = _visit(node.parameters); | |
| 686 var fun = js.call('function(#) { return $newKeyword #(#); }', [ | |
| 687 params, | |
| 688 _visit(redirect), | |
| 689 params, | |
| 690 ]); | |
| 691 return new JS.Method(name, fun, isStatic: true)..sourceInformation = node; | |
| 692 } | |
| 693 | |
| 694 // Factory constructors are essentially static methods. | |
| 695 if (node.factoryKeyword != null) { | |
| 696 var body = <JS.Statement>[]; | |
| 697 var init = _emitArgumentInitializers(node, constructor: true); | |
| 698 if (init != null) body.add(init); | |
| 699 body.add(_visit(node.body)); | |
| 700 var fun = new JS.Fun(_visit(node.parameters), new JS.Block(body)); | |
| 701 return new JS.Method(name, fun, isStatic: true)..sourceInformation = node; | |
| 702 } | |
| 678 | 703 | 
| 679 // Code generation for Object's constructor. | 704 // Code generation for Object's constructor. | 
| 680 JS.Block body; | 705 JS.Block body; | 
| 681 if (isObject && | 706 if (isObject && | 
| 682 node.body is EmptyFunctionBody && | 707 node.body is EmptyFunctionBody && | 
| 683 node.constKeyword != null && | 708 node.constKeyword != null && | 
| 684 node.name == null) { | 709 node.name == null) { | 
| 685 // Implements Dart constructor behavior. Because of V8 `super` | 710 // Implements Dart constructor behavior. Because of V8 `super` | 
| 686 // [constructor restrictions] | 711 // [constructor restrictions] | 
| 687 // (https://code.google.com/p/v8/issues/detail?id=3330#c65) | 712 // (https://code.google.com/p/v8/issues/detail?id=3330#c65) | 
| (...skipping 19 matching lines...) Expand all Loading... | |
| 707 body = _emitConstructorBody(node, fields); | 732 body = _emitConstructorBody(node, fields); | 
| 708 } | 733 } | 
| 709 | 734 | 
| 710 // We generate constructors as initializer methods in the class; | 735 // We generate constructors as initializer methods in the class; | 
| 711 // this allows use of `super` for instance methods/properties. | 736 // this allows use of `super` for instance methods/properties. | 
| 712 // It also avoids V8 restrictions on `super` in default constructors. | 737 // It also avoids V8 restrictions on `super` in default constructors. | 
| 713 return new JS.Method(name, new JS.Fun(_visit(node.parameters), body)) | 738 return new JS.Method(name, new JS.Fun(_visit(node.parameters), body)) | 
| 714 ..sourceInformation = node; | 739 ..sourceInformation = node; | 
| 715 } | 740 } | 
| 716 | 741 | 
| 717 JS.Expression _constructorName(String className, SimpleIdentifier name) { | 742 JS.Expression _constructorName(ConstructorElement ctor) { | 
| 718 if (name == null) return _propertyName(className); | 743 var name = ctor.name; | 
| 719 return _emitMemberName(name.name, isStatic: true); | 744 if (name != '') { | 
| 745 return _emitMemberName(name, isStatic: true); | |
| 746 } | |
| 747 | |
| 748 // Factory default constructors use `new` as their name, for readability | |
| 749 // Other default constructors use the class name, as they aren't called | |
| 750 // from call sites, but rather from Object's constructor. | |
| 751 // TODO(jmesserly): revisit in the context of Dart metaclasses, and cleaning | |
| 752 // up constructors to integrate more closely with ES6. | |
| 753 return _propertyName(ctor.isFactory ? 'new' : ctor.enclosingElement.name); | |
| 720 } | 754 } | 
| 721 | 755 | 
| 722 JS.Block _emitConstructorBody( | 756 JS.Block _emitConstructorBody( | 
| 723 ConstructorDeclaration node, List<FieldDeclaration> fields) { | 757 ConstructorDeclaration node, List<FieldDeclaration> fields) { | 
| 724 // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz; | |
| 725 if (node.redirectedConstructor != null) { | |
| 726 return js.statement('{ return new #(#); }', [ | |
| 727 _visit(node.redirectedConstructor), | |
| 728 _visit(node.parameters) | |
| 729 ]); | |
| 730 } | |
| 731 | |
| 732 var body = <JS.Statement>[]; | 758 var body = <JS.Statement>[]; | 
| 733 | 759 | 
| 734 // Generate optional/named argument value assignment. These can not have | 760 // Generate optional/named argument value assignment. These can not have | 
| 735 // side effects, and may be used by the constructor's initializers, so it's | 761 // side effects, and may be used by the constructor's initializers, so it's | 
| 736 // nice to do them first. | 762 // nice to do them first. | 
| 737 // Also for const constructors we need to ensure default values are | 763 // Also for const constructors we need to ensure default values are | 
| 738 // available for use by top-level constant initializers. | 764 // available for use by top-level constant initializers. | 
| 739 ClassDeclaration cls = node.parent; | 765 ClassDeclaration cls = node.parent; | 
| 740 if (node.constKeyword != null) _loader.startTopLevel(cls.element); | 766 if (node.constKeyword != null) _loader.startTopLevel(cls.element); | 
| 741 var init = _emitArgumentInitializers(node, constructor: true); | 767 var init = _emitArgumentInitializers(node, constructor: true); | 
| 742 if (node.constKeyword != null) _loader.finishTopLevel(cls.element); | 768 if (node.constKeyword != null) _loader.finishTopLevel(cls.element); | 
| 743 if (init != null) body.add(init); | 769 if (init != null) body.add(init); | 
| 744 | 770 | 
| 745 // Redirecting constructors: these are not allowed to have initializers, | 771 // Redirecting constructors: these are not allowed to have initializers, | 
| 746 // and the redirecting ctor invocation runs before field initializers. | 772 // and the redirecting ctor invocation runs before field initializers. | 
| 747 var redirectCall = node.initializers.firstWhere( | 773 var redirectCall = node.initializers.firstWhere( | 
| 748 (i) => i is RedirectingConstructorInvocation, orElse: () => null); | 774 (i) => i is RedirectingConstructorInvocation, orElse: () => null); | 
| 749 | 775 | 
| 750 if (redirectCall != null) { | 776 if (redirectCall != null) { | 
| 751 body.add(_visit(redirectCall)); | 777 body.add(_visit(redirectCall)); | 
| 752 return new JS.Block(body); | 778 return new JS.Block(body); | 
| 753 } | 779 } | 
| 754 | 780 | 
| 755 // Initializers only run for non-factory constructors. | 781 // Generate field initializers. | 
| 756 if (node.factoryKeyword == null) { | 782 // These are expanded into each non-redirecting constructor. | 
| 757 // Generate field initializers. | 783 // In the future we may want to create an initializer function if we have | 
| 758 // These are expanded into each non-redirecting constructor. | 784 // multiple constructors, but it needs to be balanced against readability. | 
| 759 // In the future we may want to create an initializer function if we have | 785 body.add(_initializeFields(node.parent, fields, node)); | 
| 760 // multiple constructors, but it needs to be balanced against readability. | |
| 761 body.add(_initializeFields(node.parent, fields, node)); | |
| 762 | 786 | 
| 763 var superCall = node.initializers.firstWhere( | 787 var superCall = node.initializers.firstWhere( | 
| 764 (i) => i is SuperConstructorInvocation, orElse: () => null); | 788 (i) => i is SuperConstructorInvocation, orElse: () => null); | 
| 765 | 789 | 
| 766 // If no superinitializer is provided, an implicit superinitializer of the | 790 // If no superinitializer is provided, an implicit superinitializer of the | 
| 767 // form `super()` is added at the end of the initializer list, unless the | 791 // form `super()` is added at the end of the initializer list, unless the | 
| 768 // enclosing class is class Object. | 792 // enclosing class is class Object. | 
| 769 var jsSuper = _superConstructorCall(node.parent, superCall); | 793 var jsSuper = _superConstructorCall(cls.element, superCall); | 
| 770 if (jsSuper != null) body.add(jsSuper); | 794 if (jsSuper != null) body.add(jsSuper); | 
| 771 } | |
| 772 | 795 | 
| 773 body.add(_visit(node.body)); | 796 body.add(_visit(node.body)); | 
| 774 return new JS.Block(body)..sourceInformation = node; | 797 return new JS.Block(body)..sourceInformation = node; | 
| 775 } | 798 } | 
| 776 | 799 | 
| 777 @override | 800 @override | 
| 778 JS.Statement visitRedirectingConstructorInvocation( | 801 JS.Statement visitRedirectingConstructorInvocation( | 
| 779 RedirectingConstructorInvocation node) { | 802 RedirectingConstructorInvocation node) { | 
| 780 ClassDeclaration classDecl = node.parent.parent; | 803 var name = _constructorName(node.staticElement); | 
| 781 var className = classDecl.name.name; | |
| 782 | |
| 783 var name = _constructorName(className, node.constructorName); | |
| 784 return js.statement('this.#(#);', [name, _visit(node.argumentList)]); | 804 return js.statement('this.#(#);', [name, _visit(node.argumentList)]); | 
| 785 } | 805 } | 
| 786 | 806 | 
| 787 JS.Statement _superConstructorCall(ClassDeclaration clazz, | 807 JS.Statement _superConstructorCall(ClassElement element, | 
| 788 [SuperConstructorInvocation node]) { | 808 [SuperConstructorInvocation node]) { | 
| 789 var superCtorName = node != null ? node.constructorName : null; | |
| 790 | 809 | 
| 791 var element = clazz.element; | 810 ConstructorElement superCtor; | 
| 792 if (superCtorName == null && !_shouldCallUnnamedSuperCtor(element)) { | 811 if (node != null) { | 
| 812 superCtor = node.staticElement; | |
| 813 } else { | |
| 814 // Get the supertype's unnamed constructor. | |
| 815 superCtor = element.supertype.element.unnamedConstructor; | |
| 816 if (superCtor == null) { | |
| 817 // This will only happen if the code has errors: | |
| 818 // we're trying to generate an implicit constructor for a type where | |
| 819 // we don't have a default constructor in the supertype. | |
| 820 assert(options.forceCompile); | |
| 821 return null; | |
| 822 } | |
| 823 } | |
| 824 | |
| 825 if (superCtor.name == '' && !_shouldCallUnnamedSuperCtor(element)) { | |
| 793 return null; | 826 return null; | 
| 794 } | 827 } | 
| 795 | 828 | 
| 796 var supertypeName = element.supertype.name; | 829 var name = _constructorName(superCtor); | 
| 797 var name = _constructorName(supertypeName, superCtorName); | |
| 798 | |
| 799 var args = node != null ? _visit(node.argumentList) : []; | 830 var args = node != null ? _visit(node.argumentList) : []; | 
| 800 return js.statement('super.#(#);', [name, args])..sourceInformation = node; | 831 return js.statement('super.#(#);', [name, args])..sourceInformation = node; | 
| 801 } | 832 } | 
| 802 | 833 | 
| 803 bool _shouldCallUnnamedSuperCtor(ClassElement e) { | 834 bool _shouldCallUnnamedSuperCtor(ClassElement e) { | 
| 804 var supertype = e.supertype; | 835 var supertype = e.supertype; | 
| 805 if (supertype == null) return false; | 836 if (supertype == null) return false; | 
| 806 if (_hasUnnamedConstructor(supertype.element)) return true; | 837 if (_hasUnnamedConstructor(supertype.element)) return true; | 
| 807 for (var mixin in e.mixins) { | 838 for (var mixin in e.mixins) { | 
| 808 if (_hasUnnamedConstructor(mixin.element)) return true; | 839 if (_hasUnnamedConstructor(mixin.element)) return true; | 
| (...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1629 body.add(js.statement('dart.copyProperties(#, { # });', [ | 1660 body.add(js.statement('dart.copyProperties(#, { # });', [ | 
| 1630 _exportsVar, | 1661 _exportsVar, | 
| 1631 _properties.map(_emitTopLevelProperty) | 1662 _properties.map(_emitTopLevelProperty) | 
| 1632 ])); | 1663 ])); | 
| 1633 _properties.clear(); | 1664 _properties.clear(); | 
| 1634 } | 1665 } | 
| 1635 | 1666 | 
| 1636 @override | 1667 @override | 
| 1637 visitConstructorName(ConstructorName node) { | 1668 visitConstructorName(ConstructorName node) { | 
| 1638 var typeName = _visit(node.type); | 1669 var typeName = _visit(node.type); | 
| 1639 if (node.name != null) { | 1670 if (node.name != null || node.staticElement.isFactory) { | 
| 1640 return js.call( | 1671 var namedCtor = _constructorName(node.staticElement); | 
| 1641 '#.#', [typeName, _emitMemberName(node.name.name, isStatic: true)]); | 1672 return new JS.PropertyAccess(typeName, namedCtor); | 
| 1642 } | 1673 } | 
| 1643 return typeName; | 1674 return typeName; | 
| 1644 } | 1675 } | 
| 1645 | 1676 | 
| 1646 @override | 1677 @override | 
| 1647 visitInstanceCreationExpression(InstanceCreationExpression node) { | 1678 visitInstanceCreationExpression(InstanceCreationExpression node) { | 
| 1648 emitNew() => js.call( | 1679 emitNew() { | 
| 1649 'new #(#)', [_visit(node.constructorName), _visit(node.argumentList)]); | 1680 var ctor = _visit(node.constructorName); | 
| 1681 var args = _visit(node.argumentList); | |
| 1682 var isFactory = node.staticElement.isFactory; | |
| 1683 return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args); | |
| 1684 } | |
| 1650 if (node.isConst) return _emitConst(node, emitNew); | 1685 if (node.isConst) return _emitConst(node, emitNew); | 
| 1651 return emitNew(); | 1686 return emitNew(); | 
| 1652 } | 1687 } | 
| 1653 | 1688 | 
| 1654 /// True if this type is built-in to JS, and we use the values unwrapped. | 1689 /// True if this type is built-in to JS, and we use the values unwrapped. | 
| 1655 /// For these types we generate a calling convention via static | 1690 /// For these types we generate a calling convention via static | 
| 1656 /// "extension methods". This allows types to be extended without adding | 1691 /// "extension methods". This allows types to be extended without adding | 
| 1657 /// extensions directly on the prototype. | 1692 /// extensions directly on the prototype. | 
| 1658 bool _isJSBuiltinType(DartType t) => | 1693 bool _isJSBuiltinType(DartType t) => | 
| 1659 typeIsPrimitiveInJS(t) || rules.isStringType(t); | 1694 typeIsPrimitiveInJS(t) || rules.isStringType(t); | 
| (...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2612 | 2647 | 
| 2613 /// A special kind of element created by the compiler, signifying a temporary | 2648 /// A special kind of element created by the compiler, signifying a temporary | 
| 2614 /// variable. These objects use instance equality, and should be shared | 2649 /// variable. These objects use instance equality, and should be shared | 
| 2615 /// everywhere in the tree where they are treated as the same variable. | 2650 /// everywhere in the tree where they are treated as the same variable. | 
| 2616 class TemporaryVariableElement extends LocalVariableElementImpl { | 2651 class TemporaryVariableElement extends LocalVariableElementImpl { | 
| 2617 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2652 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 
| 2618 | 2653 | 
| 2619 int get hashCode => identityHashCode(this); | 2654 int get hashCode => identityHashCode(this); | 
| 2620 bool operator ==(Object other) => identical(this, other); | 2655 bool operator ==(Object other) => identical(this, other); | 
| 2621 } | 2656 } | 
| OLD | NEW |