| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * A function element that represents a closure call. The signature is copied | 6 * A function element that represents a closure call. The signature is copied |
| 7 * from the given element. | 7 * from the given element. |
| 8 */ | 8 */ |
| 9 class ClosureInvocationElement extends FunctionElement { | 9 class ClosureInvocationElement extends FunctionElement { |
| 10 ClosureInvocationElement(SourceString name, | 10 ClosureInvocationElement(SourceString name, |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 | 485 |
| 486 String compiledFieldName(Element member) { | 486 String compiledFieldName(Element member) { |
| 487 assert(member.isField()); | 487 assert(member.isField()); |
| 488 return member.isNative() | 488 return member.isNative() |
| 489 ? member.name.slowToString() | 489 ? member.name.slowToString() |
| 490 : namer.getName(member); | 490 : namer.getName(member); |
| 491 } | 491 } |
| 492 | 492 |
| 493 void addInstanceMember(Element member, | 493 void addInstanceMember(Element member, |
| 494 DefineMemberFunction defineInstanceMember) { | 494 DefineMemberFunction defineInstanceMember) { |
| 495 assert(member.isDeclaration); |
| 495 // TODO(floitsch): we don't need to deal with members of | 496 // TODO(floitsch): we don't need to deal with members of |
| 496 // uninstantiated classes, that have been overwritten by subclasses. | 497 // uninstantiated classes, that have been overwritten by subclasses. |
| 497 | 498 |
| 498 if (member.isFunction() | 499 if (member.isFunction() |
| 499 || member.isGenerativeConstructorBody() | 500 || member.isGenerativeConstructorBody() |
| 500 || member.isGetter() | 501 || member.isGetter() |
| 501 || member.isSetter()) { | 502 || member.isSetter()) { |
| 502 if (member.modifiers !== null && member.modifiers.isAbstract()) return; | 503 if (member.modifiers !== null && member.modifiers.isAbstract()) return; |
| 503 CodeBuffer codeBuffer = compiler.codegenWorld.generatedCode[member]; | 504 CodeBuffer codeBuffer = compiler.codegenWorld.generatedCode[member]; |
| 504 if (codeBuffer == null) return; | 505 if (codeBuffer == null) return; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 530 SourceString helper = compiler.backend.getCheckedModeHelper(type); | 531 SourceString helper = compiler.backend.getCheckedModeHelper(type); |
| 531 Element helperElement = compiler.findHelper(helper); | 532 Element helperElement = compiler.findHelper(helper); |
| 532 String helperName = namer.isolateAccess(helperElement); | 533 String helperName = namer.isolateAccess(helperElement); |
| 533 String additionalArgument = namer.operatorIs(type.element); | 534 String additionalArgument = namer.operatorIs(type.element); |
| 534 return " set\$$fieldName: function(v) { " | 535 return " set\$$fieldName: function(v) { " |
| 535 "this.$fieldName = $helperName(v, '$additionalArgument'); }"; | 536 "this.$fieldName = $helperName(v, '$additionalArgument'); }"; |
| 536 } | 537 } |
| 537 } | 538 } |
| 538 | 539 |
| 539 List<String> emitClassFields(ClassElement classElement, CodeBuffer buffer) { | 540 List<String> emitClassFields(ClassElement classElement, CodeBuffer buffer) { |
| 541 assert(classElement.isDeclaration); |
| 540 // If the class is never instantiated we still need to set it up for | 542 // If the class is never instantiated we still need to set it up for |
| 541 // inheritance purposes, but we can simplify its JavaScript constructor. | 543 // inheritance purposes, but we can simplify its JavaScript constructor. |
| 542 bool isInstantiated = | 544 bool isInstantiated = |
| 543 compiler.codegenWorld.instantiatedClasses.contains(classElement); | 545 compiler.codegenWorld.instantiatedClasses.contains(classElement); |
| 544 List<String> checkedSetters = <String>[]; | 546 List<String> checkedSetters = <String>[]; |
| 545 | 547 |
| 546 bool isFirstField = true; | 548 bool isFirstField = true; |
| 547 void addField(ClassElement enclosingClass, Element member) { | 549 void addField(ClassElement enclosingClass, Element member) { |
| 548 assert(!member.isNative()); | 550 assert(!member.isNative()); |
| 551 assert(member.isDeclaration); |
| 549 | 552 |
| 550 LibraryElement library = member.getLibrary(); | 553 LibraryElement library = member.getLibrary(); |
| 551 SourceString name = member.name; | 554 SourceString name = member.name; |
| 552 bool isPrivate = name.isPrivate(); | 555 bool isPrivate = name.isPrivate(); |
| 553 // See if we can dynamically create getters and setters. | 556 // See if we can dynamically create getters and setters. |
| 554 // We can only generate getters and setters for [classElement] since | 557 // We can only generate getters and setters for [classElement] since |
| 555 // the fields of super classes could be overwritten with getters or | 558 // the fields of super classes could be overwritten with getters or |
| 556 // setters. | 559 // setters. |
| 557 bool needsDynamicGetter = false; | 560 bool needsDynamicGetter = false; |
| 558 bool needsDynamicSetter = false; | 561 bool needsDynamicSetter = false; |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 }); | 830 }); |
| 828 // If a static function is used as a closure we need to add its name | 831 // If a static function is used as a closure we need to add its name |
| 829 // in case it is used in spawnFunction. | 832 // in case it is used in spawnFunction. |
| 830 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 833 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; |
| 831 buffer.add('$fieldAccess.$fieldName = "$staticName";\n'); | 834 buffer.add('$fieldAccess.$fieldName = "$staticName";\n'); |
| 832 } | 835 } |
| 833 } | 836 } |
| 834 | 837 |
| 835 void emitDynamicFunctionGetter(FunctionElement member, | 838 void emitDynamicFunctionGetter(FunctionElement member, |
| 836 DefineMemberFunction defineInstanceMember) { | 839 DefineMemberFunction defineInstanceMember) { |
| 840 assert(member.isDeclaration); |
| 837 // For every method that has the same name as a property-get we create a | 841 // For every method that has the same name as a property-get we create a |
| 838 // getter that returns a bound closure. Say we have a class 'A' with method | 842 // getter that returns a bound closure. Say we have a class 'A' with method |
| 839 // 'foo' and somewhere in the code there is a dynamic property get of | 843 // 'foo' and somewhere in the code there is a dynamic property get of |
| 840 // 'foo'. Then we generate the following code (in pseudo Dart/JavaScript): | 844 // 'foo'. Then we generate the following code (in pseudo Dart/JavaScript): |
| 841 // | 845 // |
| 842 // class A { | 846 // class A { |
| 843 // foo(x, y, z) { ... } // Original function. | 847 // foo(x, y, z) { ... } // Original function. |
| 844 // get foo { return new BoundClosure499(this, "foo"); } | 848 // get foo { return new BoundClosure499(this, "foo"); } |
| 845 // } | 849 // } |
| 846 // class BoundClosure499 extends Closure { | 850 // class BoundClosure499 extends Closure { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 912 String targetName = namer.instanceMethodName(member); | 916 String targetName = namer.instanceMethodName(member); |
| 913 CodeBuffer getterBuffer = new CodeBuffer(); | 917 CodeBuffer getterBuffer = new CodeBuffer(); |
| 914 getterBuffer.add( | 918 getterBuffer.add( |
| 915 "function() { return new $closureClass(this, '$targetName'); }"); | 919 "function() { return new $closureClass(this, '$targetName'); }"); |
| 916 defineInstanceMember(getterName, getterBuffer); | 920 defineInstanceMember(getterName, getterBuffer); |
| 917 } | 921 } |
| 918 | 922 |
| 919 void emitCallStubForGetter(Element member, | 923 void emitCallStubForGetter(Element member, |
| 920 Set<Selector> selectors, | 924 Set<Selector> selectors, |
| 921 DefineMemberFunction defineInstanceMember) { | 925 DefineMemberFunction defineInstanceMember) { |
| 926 assert(member.isDeclaration); |
| 927 LibraryElement memberLibrary = member.getLibrary(); |
| 922 String getter; | 928 String getter; |
| 923 if (member.isGetter()) { | 929 if (member.isGetter()) { |
| 924 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; | 930 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; |
| 925 } else { | 931 } else { |
| 926 String name = namer.instanceFieldName(member.getLibrary(), member.name); | 932 String name = namer.instanceFieldName(memberLibrary, member.name); |
| 927 getter = "this.$name"; | 933 getter = "this.$name"; |
| 928 } | 934 } |
| 929 for (Selector selector in selectors) { | 935 for (Selector selector in selectors) { |
| 930 if (selector.applies(member, compiler)) { | 936 if (selector.applies(member, compiler)) { |
| 931 String invocationName = | 937 String invocationName = |
| 932 namer.instanceMethodInvocationName(member.getLibrary(), member.name, | 938 namer.instanceMethodInvocationName(memberLibrary, member.name, |
| 933 selector); | 939 selector); |
| 934 SourceString callName = Namer.CLOSURE_INVOCATION_NAME; | 940 SourceString callName = Namer.CLOSURE_INVOCATION_NAME; |
| 935 String closureCallName = | 941 String closureCallName = |
| 936 namer.instanceMethodInvocationName(member.getLibrary(), callName, | 942 namer.instanceMethodInvocationName(memberLibrary, callName, |
| 937 selector); | 943 selector); |
| 938 List<String> arguments = <String>[]; | 944 List<String> arguments = <String>[]; |
| 939 for (int i = 0; i < selector.argumentCount; i++) { | 945 for (int i = 0; i < selector.argumentCount; i++) { |
| 940 arguments.add("arg$i"); | 946 arguments.add("arg$i"); |
| 941 } | 947 } |
| 942 String joined = Strings.join(arguments, ", "); | 948 String joined = Strings.join(arguments, ", "); |
| 943 CodeBuffer getterBuffer = new CodeBuffer(); | 949 CodeBuffer getterBuffer = new CodeBuffer(); |
| 944 getterBuffer.add( | 950 getterBuffer.add( |
| 945 "function($joined) { return $getter.$closureCallName($joined); }"); | 951 "function($joined) { return $getter.$closureCallName($joined); }"); |
| 946 defineInstanceMember(invocationName, getterBuffer); | 952 defineInstanceMember(invocationName, getterBuffer); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 buffer.add(@'''.makeConstantList = function(list) { | 1026 buffer.add(@'''.makeConstantList = function(list) { |
| 1021 list.immutable$list = true; | 1027 list.immutable$list = true; |
| 1022 list.fixed$length = true; | 1028 list.fixed$length = true; |
| 1023 return list; | 1029 return list; |
| 1024 }; | 1030 }; |
| 1025 '''); | 1031 '''); |
| 1026 } | 1032 } |
| 1027 | 1033 |
| 1028 void emitExtraAccessors(Element member, | 1034 void emitExtraAccessors(Element member, |
| 1029 DefineMemberFunction defineInstanceMember) { | 1035 DefineMemberFunction defineInstanceMember) { |
| 1036 assert(member.isDeclaration); |
| 1030 if (member.isGetter() || member.isField()) { | 1037 if (member.isGetter() || member.isField()) { |
| 1031 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | 1038 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| 1032 if (selectors !== null && !selectors.isEmpty()) { | 1039 if (selectors !== null && !selectors.isEmpty()) { |
| 1033 emitCallStubForGetter(member, selectors, defineInstanceMember); | 1040 emitCallStubForGetter(member, selectors, defineInstanceMember); |
| 1034 } | 1041 } |
| 1035 } else if (member.isFunction()) { | 1042 } else if (member.isFunction()) { |
| 1036 if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { | 1043 if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { |
| 1037 emitDynamicFunctionGetter(member, defineInstanceMember); | 1044 emitDynamicFunctionGetter(member, defineInstanceMember); |
| 1038 } | 1045 } |
| 1039 } | 1046 } |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1350 const String HOOKS_API_USAGE = """ | 1357 const String HOOKS_API_USAGE = """ |
| 1351 // Generated by dart2js, the Dart to JavaScript compiler. | 1358 // Generated by dart2js, the Dart to JavaScript compiler. |
| 1352 // The code supports the following hooks: | 1359 // The code supports the following hooks: |
| 1353 // dartPrint(message) - if this function is defined it is called | 1360 // dartPrint(message) - if this function is defined it is called |
| 1354 // instead of the Dart [print] method. | 1361 // instead of the Dart [print] method. |
| 1355 // dartMainRunner(main) - if this function is defined, the Dart [main] | 1362 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 1356 // method will not be invoked directly. | 1363 // method will not be invoked directly. |
| 1357 // Instead, a closure that will invoke [main] is | 1364 // Instead, a closure that will invoke [main] is |
| 1358 // passed to [dartMainRunner]. | 1365 // passed to [dartMainRunner]. |
| 1359 """; | 1366 """; |
| OLD | NEW |