| 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 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
| 9 * from the given element. | 9 * from the given element. |
| 10 */ | 10 */ |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 /** Shorter access to [isolatePropertiesName]. Both here in the code, as | 68 /** Shorter access to [isolatePropertiesName]. Both here in the code, as |
| 69 well as in the generated code. */ | 69 well as in the generated code. */ |
| 70 String isolateProperties; | 70 String isolateProperties; |
| 71 String classesCollector; | 71 String classesCollector; |
| 72 final Set<ClassElement> neededClasses = new Set<ClassElement>(); | 72 final Set<ClassElement> neededClasses = new Set<ClassElement>(); |
| 73 final List<ClassElement> regularClasses = <ClassElement>[]; | 73 final List<ClassElement> regularClasses = <ClassElement>[]; |
| 74 final List<ClassElement> deferredClasses = <ClassElement>[]; | 74 final List<ClassElement> deferredClasses = <ClassElement>[]; |
| 75 final List<ClassElement> nativeClasses = <ClassElement>[]; | 75 final List<ClassElement> nativeClasses = <ClassElement>[]; |
| 76 final List<Selector> trivialNsmHandlers = <Selector>[]; | 76 final List<Selector> trivialNsmHandlers = <Selector>[]; |
| 77 final Map<String, String> mangledFieldNames = <String, String>{}; | 77 final Map<String, String> mangledFieldNames = <String, String>{}; |
| 78 final Set<String> recordedMangledNames = new Set<String>(); |
| 78 final Set<String> interceptorInvocationNames = new Set<String>(); | 79 final Set<String> interceptorInvocationNames = new Set<String>(); |
| 79 final Set<String> recordedUnmangledNames = new Set<String>(); | |
| 80 | 80 |
| 81 // TODO(ngeoffray): remove this field. | 81 // TODO(ngeoffray): remove this field. |
| 82 Set<ClassElement> instantiatedClasses; | 82 Set<ClassElement> instantiatedClasses; |
| 83 | 83 |
| 84 final List<jsAst.Expression> boundClosures = <jsAst.Expression>[]; | 84 final List<jsAst.Expression> boundClosures = <jsAst.Expression>[]; |
| 85 | 85 |
| 86 JavaScriptBackend get backend => compiler.backend; | 86 JavaScriptBackend get backend => compiler.backend; |
| 87 | 87 |
| 88 String get _ => compiler.enableMinification ? "" : " "; | 88 String get _ => compiler.enableMinification ? "" : " "; |
| 89 String get n => compiler.enableMinification ? "" : "\n"; | 89 String get n => compiler.enableMinification ? "" : "\n"; |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 * string encoding fields, constructor and superclass. Get | 610 * string encoding fields, constructor and superclass. Get |
| 611 * the superclass and the fields in the format | 611 * the superclass and the fields in the format |
| 612 * '[name/]Super;field1,field2' | 612 * '[name/]Super;field1,field2' |
| 613 * from the null-string property on the descriptor. | 613 * from the null-string property on the descriptor. |
| 614 * The 'name/' is optional and contains the name that should be used | 614 * The 'name/' is optional and contains the name that should be used |
| 615 * when printing the runtime type string. It is used, for example, to | 615 * when printing the runtime type string. It is used, for example, to |
| 616 * print the runtime type JSInt as 'int'. | 616 * print the runtime type JSInt as 'int'. |
| 617 */ | 617 */ |
| 618 js('var classData = desc[""], supr, name = cls, fields = classData'), | 618 js('var classData = desc[""], supr, name = cls, fields = classData'), |
| 619 optional( | 619 optional( |
| 620 compiler.mirrorsEnabled, | 620 backend.hasRetainedMetadata, |
| 621 js.if_('typeof classData == "object" && ' | 621 js.if_('typeof classData == "object" && ' |
| 622 'classData instanceof Array', | 622 'classData instanceof Array', |
| 623 [js('classData = fields = classData[0]')])), | 623 [js('classData = fields = classData[0]')])), |
| 624 | 624 |
| 625 js.if_('typeof classData == "string"', [ | 625 js.if_('typeof classData == "string"', [ |
| 626 js('var split = classData.split("/")'), | 626 js('var split = classData.split("/")'), |
| 627 js.if_('split.length == 2', [ | 627 js.if_('split.length == 2', [ |
| 628 js('name = split[0]'), | 628 js('name = split[0]'), |
| 629 js('fields = split[1]') | 629 js('fields = split[1]') |
| 630 ]) | 630 ]) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 644 js('supr = s[0]'), | 644 js('supr = s[0]'), |
| 645 js('var mixin = collectedClasses[s[1]]'), | 645 js('var mixin = collectedClasses[s[1]]'), |
| 646 js.forIn('d', 'mixin', [ | 646 js.forIn('d', 'mixin', [ |
| 647 js.if_('hasOwnProperty.call(mixin, d)' | 647 js.if_('hasOwnProperty.call(mixin, d)' |
| 648 '&& !hasOwnProperty.call(desc, d)', | 648 '&& !hasOwnProperty.call(desc, d)', |
| 649 js('desc[d] = mixin[d]')) | 649 js('desc[d] = mixin[d]')) |
| 650 ]), | 650 ]), |
| 651 ])), | 651 ])), |
| 652 | 652 |
| 653 js('var constructor = defineClass(name, cls, fields, desc)'), | 653 js('var constructor = defineClass(name, cls, fields, desc)'), |
| 654 optional(compiler.mirrorsEnabled, | 654 optional(backend.hasRetainedMetadata, |
| 655 js('constructor["${namer.metadataField}"] = desc')), | 655 js('constructor["${namer.metadataField}"] = desc')), |
| 656 js('isolateProperties[cls] = constructor'), | 656 js('isolateProperties[cls] = constructor'), |
| 657 js.if_('supr', js('pendingClasses[cls] = supr')) | 657 js.if_('supr', js('pendingClasses[cls] = supr')) |
| 658 ]) | 658 ]) |
| 659 ]), | 659 ]), |
| 660 | 660 |
| 661 js('var finishedClasses = {}'), | 661 js('var finishedClasses = {}'), |
| 662 | 662 |
| 663 buildFinishClass(), | 663 buildFinishClass(), |
| 664 ]; | 664 ]; |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 parametersBuffer, argumentsBuffer, | 1012 parametersBuffer, argumentsBuffer, |
| 1013 indexOfLastOptionalArgumentInParameters); | 1013 indexOfLastOptionalArgumentInParameters); |
| 1014 } else { | 1014 } else { |
| 1015 body = [js.return_(js('this')[namer.getName(member)](argumentsBuffer))]; | 1015 body = [js.return_(js('this')[namer.getName(member)](argumentsBuffer))]; |
| 1016 } | 1016 } |
| 1017 | 1017 |
| 1018 jsAst.Fun function = js.fun(parametersBuffer, body); | 1018 jsAst.Fun function = js.fun(parametersBuffer, body); |
| 1019 | 1019 |
| 1020 defineStub(invocationName, function); | 1020 defineStub(invocationName, function); |
| 1021 | 1021 |
| 1022 String reflectionName = getReflectionName(selector); | 1022 String reflectionName = getReflectionName(selector, invocationName); |
| 1023 if (reflectionName != null) { | 1023 if (reflectionName != null) { |
| 1024 defineStub('+$reflectionName', js('0')); | 1024 defineStub('+$reflectionName', js('0')); |
| 1025 } | 1025 } |
| 1026 } | 1026 } |
| 1027 | 1027 |
| 1028 void addParameterStubs(FunctionElement member, | 1028 void addParameterStubs(FunctionElement member, |
| 1029 DefineStubFunction defineStub) { | 1029 DefineStubFunction defineStub) { |
| 1030 // We fill the lists depending on the selector. For example, | 1030 // We fill the lists depending on the selector. For example, |
| 1031 // take method foo: | 1031 // take method foo: |
| 1032 // foo(a, b, {c, d}); | 1032 // foo(a, b, {c, d}); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 element.getLibrary(), | 1133 element.getLibrary(), |
| 1134 signature.requiredParameterCount + i, | 1134 signature.requiredParameterCount + i, |
| 1135 <SourceString>[])); | 1135 <SourceString>[])); |
| 1136 } | 1136 } |
| 1137 return selectors; | 1137 return selectors; |
| 1138 } | 1138 } |
| 1139 | 1139 |
| 1140 bool instanceFieldNeedsGetter(Element member) { | 1140 bool instanceFieldNeedsGetter(Element member) { |
| 1141 assert(member.isField()); | 1141 assert(member.isField()); |
| 1142 if (fieldAccessNeverThrows(member)) return false; | 1142 if (fieldAccessNeverThrows(member)) return false; |
| 1143 return compiler.mirrorsEnabled | 1143 return backend.retainGetter(member) |
| 1144 || compiler.codegenWorld.hasInvokedGetter(member, compiler); | 1144 || compiler.codegenWorld.hasInvokedGetter(member, compiler); |
| 1145 } | 1145 } |
| 1146 | 1146 |
| 1147 bool instanceFieldNeedsSetter(Element member) { | 1147 bool instanceFieldNeedsSetter(Element member) { |
| 1148 assert(member.isField()); | 1148 assert(member.isField()); |
| 1149 if (fieldAccessNeverThrows(member)) return false; | 1149 if (fieldAccessNeverThrows(member)) return false; |
| 1150 return (!member.modifiers.isFinalOrConst()) | 1150 return (!member.modifiers.isFinalOrConst()) |
| 1151 && (compiler.mirrorsEnabled | 1151 && (backend.retainSetter(member) |
| 1152 || compiler.codegenWorld.hasInvokedSetter(member, compiler)); | 1152 || compiler.codegenWorld.hasInvokedSetter(member, compiler)); |
| 1153 } | 1153 } |
| 1154 | 1154 |
| 1155 // We never access a field in a closure (a captured variable) without knowing | 1155 // We never access a field in a closure (a captured variable) without knowing |
| 1156 // that it is there. Therefore we don't need to use a getter (that will throw | 1156 // that it is there. Therefore we don't need to use a getter (that will throw |
| 1157 // if the getter method is missing), but can always access the field directly. | 1157 // if the getter method is missing), but can always access the field directly. |
| 1158 static bool fieldAccessNeverThrows(Element element) { | 1158 static bool fieldAccessNeverThrows(Element element) { |
| 1159 return element is ClosureFieldElement; | 1159 return element is ClosureFieldElement; |
| 1160 } | 1160 } |
| 1161 | 1161 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1184 if (code == null) return; | 1184 if (code == null) return; |
| 1185 String name = namer.getName(member); | 1185 String name = namer.getName(member); |
| 1186 if (backend.isInterceptedMethod(member)) { | 1186 if (backend.isInterceptedMethod(member)) { |
| 1187 interceptorInvocationNames.add(name); | 1187 interceptorInvocationNames.add(name); |
| 1188 } | 1188 } |
| 1189 builder.addProperty(name, code); | 1189 builder.addProperty(name, code); |
| 1190 var metadata = buildMetadataFunction(member); | 1190 var metadata = buildMetadataFunction(member); |
| 1191 if (metadata != null) { | 1191 if (metadata != null) { |
| 1192 builder.addProperty('@$name', metadata); | 1192 builder.addProperty('@$name', metadata); |
| 1193 } | 1193 } |
| 1194 String reflectionName = getReflectionName(member); | 1194 String reflectionName = getReflectionName(member, name); |
| 1195 if (reflectionName != null) { | 1195 if (reflectionName != null) { |
| 1196 builder.addProperty('+$reflectionName', js('0')); | 1196 builder.addProperty('+$reflectionName', js('0')); |
| 1197 } | 1197 } |
| 1198 code = backend.generatedBailoutCode[member]; | 1198 code = backend.generatedBailoutCode[member]; |
| 1199 if (code != null) { | 1199 if (code != null) { |
| 1200 builder.addProperty(namer.getBailoutName(member), code); | 1200 builder.addProperty(namer.getBailoutName(member), code); |
| 1201 } | 1201 } |
| 1202 FunctionElement function = member; | 1202 FunctionElement function = member; |
| 1203 FunctionSignature parameters = function.computeSignature(compiler); | 1203 FunctionSignature parameters = function.computeSignature(compiler); |
| 1204 if (!parameters.optionalParameters.isEmpty) { | 1204 if (!parameters.optionalParameters.isEmpty) { |
| 1205 addParameterStubs(member, builder.addProperty); | 1205 addParameterStubs(member, builder.addProperty); |
| 1206 } | 1206 } |
| 1207 } else if (!member.isField()) { | 1207 } else if (!member.isField()) { |
| 1208 compiler.internalError('unexpected kind: "${member.kind}"', | 1208 compiler.internalError('unexpected kind: "${member.kind}"', |
| 1209 element: member); | 1209 element: member); |
| 1210 } | 1210 } |
| 1211 emitExtraAccessors(member, builder); | 1211 emitExtraAccessors(member, builder); |
| 1212 } | 1212 } |
| 1213 | 1213 |
| 1214 String getReflectionName(elementOrSelector) { | 1214 String getReflectionName(elementOrSelector, String mangledName) { |
| 1215 if (!compiler.mirrorsEnabled) return null; | 1215 if (!backend.retainName(elementOrSelector.name)) return null; |
| 1216 String result = getReflectionNameInternal(elementOrSelector); | 1216 // TODO(ahe): Enable the next line when I can tell the difference between |
| 1217 if (recordedUnmangledNames.contains(result)) return null; | 1217 // an instance method and a global. They may have the same mangled name. |
| 1218 recordedUnmangledNames.add(result); | 1218 // if (recordedMangledNames.contains(mangledName)) return null; |
| 1219 return result; | 1219 recordedMangledNames.add(mangledName); |
| 1220 return getReflectionNameInternal(elementOrSelector, mangledName); |
| 1220 } | 1221 } |
| 1221 | 1222 |
| 1222 String getReflectionNameInternal(elementOrSelector) { | 1223 String getReflectionNameInternal(elementOrSelector, String mangledName) { |
| 1223 String name = elementOrSelector.name.slowToString(); | 1224 String name = elementOrSelector.name.slowToString(); |
| 1224 if (elementOrSelector.isGetter()) return name; | 1225 if (elementOrSelector.isGetter()) return name; |
| 1225 if (elementOrSelector.isSetter()) return '$name='; | 1226 if (elementOrSelector.isSetter()) { |
| 1227 if (!mangledName.startsWith(namer.setterPrefix)) return '$name='; |
| 1228 String base = mangledName.substring(namer.setterPrefix.length); |
| 1229 String getter = '${namer.getterPrefix}$base'; |
| 1230 mangledFieldNames[getter] = name; |
| 1231 recordedMangledNames.add(getter); |
| 1232 return null; |
| 1233 } |
| 1226 if (elementOrSelector is Selector | 1234 if (elementOrSelector is Selector |
| 1227 || elementOrSelector.isFunction() | 1235 || elementOrSelector.isFunction() |
| 1228 || elementOrSelector.isConstructor()) { | 1236 || elementOrSelector.isConstructor()) { |
| 1229 int requiredParameterCount; | 1237 int requiredParameterCount; |
| 1230 int optionalParameterCount; | 1238 int optionalParameterCount; |
| 1231 bool isConstructor; | 1239 bool isConstructor; |
| 1232 if (elementOrSelector is Selector) { | 1240 if (elementOrSelector is Selector) { |
| 1233 requiredParameterCount = elementOrSelector.argumentCount; | 1241 requiredParameterCount = elementOrSelector.argumentCount; |
| 1234 optionalParameterCount = 0; | 1242 optionalParameterCount = 0; |
| 1235 isConstructor = false; | 1243 isConstructor = false; |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1491 /* Do nothing. */ | 1499 /* Do nothing. */ |
| 1492 } | 1500 } |
| 1493 | 1501 |
| 1494 void emitRuntimeName(String runtimeName, ClassBuilder builder) { | 1502 void emitRuntimeName(String runtimeName, ClassBuilder builder) { |
| 1495 /* Do nothing. */ | 1503 /* Do nothing. */ |
| 1496 } | 1504 } |
| 1497 | 1505 |
| 1498 void recordMangledField(Element member, | 1506 void recordMangledField(Element member, |
| 1499 String accessorName, | 1507 String accessorName, |
| 1500 String memberName) { | 1508 String memberName) { |
| 1509 if (!backend.retainGetter(member)) return; |
| 1501 String previousName = mangledFieldNames.putIfAbsent( | 1510 String previousName = mangledFieldNames.putIfAbsent( |
| 1502 '${namer.getterPrefix}$accessorName', | 1511 '${namer.getterPrefix}$accessorName', |
| 1503 () => memberName); | 1512 () => memberName); |
| 1504 assert(invariant(member, previousName == memberName, | 1513 assert(invariant(member, previousName == memberName, |
| 1505 message: '$previousName != ${memberName}')); | 1514 message: '$previousName != ${memberName}')); |
| 1506 previousName = mangledFieldNames.putIfAbsent( | |
| 1507 '${namer.setterPrefix}$accessorName', | |
| 1508 () => '${memberName}='); | |
| 1509 assert(invariant(member, previousName == '${memberName}=', | |
| 1510 message: '$previousName != ${memberName}=')); | |
| 1511 } | 1515 } |
| 1512 | 1516 |
| 1513 /// Returns `true` if fields added. | 1517 /// Returns `true` if fields added. |
| 1514 bool emitClassFields(ClassElement classElement, | 1518 bool emitClassFields(ClassElement classElement, |
| 1515 ClassBuilder builder, | 1519 ClassBuilder builder, |
| 1516 String superName, | 1520 String superName, |
| 1517 { bool classIsNative: false }) { | 1521 { bool classIsNative: false }) { |
| 1518 assert(superName != null); | 1522 assert(superName != null); |
| 1519 String separator = ''; | 1523 String separator = ''; |
| 1520 String nativeName = namer.getPrimitiveInterceptorRuntimeName(classElement); | 1524 String nativeName = namer.getPrimitiveInterceptorRuntimeName(classElement); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1536 bool needsCheckedSetter) { | 1540 bool needsCheckedSetter) { |
| 1537 // Ignore needsCheckedSetter - that is handled below. | 1541 // Ignore needsCheckedSetter - that is handled below. |
| 1538 bool needsAccessor = (needsGetter || needsSetter); | 1542 bool needsAccessor = (needsGetter || needsSetter); |
| 1539 // We need to output the fields for non-native classes so we can auto- | 1543 // We need to output the fields for non-native classes so we can auto- |
| 1540 // generate the constructor. For native classes there are no | 1544 // generate the constructor. For native classes there are no |
| 1541 // constructors, so we don't need the fields unless we are generating | 1545 // constructors, so we don't need the fields unless we are generating |
| 1542 // accessors at runtime. | 1546 // accessors at runtime. |
| 1543 if (!classIsNative || needsAccessor) { | 1547 if (!classIsNative || needsAccessor) { |
| 1544 buffer.write(separator); | 1548 buffer.write(separator); |
| 1545 separator = ','; | 1549 separator = ','; |
| 1546 if (compiler.mirrorsEnabled) { | 1550 var metadata = buildMetadataFunction(member); |
| 1547 var metadata = buildMetadataFunction(member); | 1551 if (metadata != null) { |
| 1548 if (metadata != null) { | 1552 hasMetadata = true; |
| 1549 hasMetadata = true; | 1553 } else { |
| 1550 } else { | 1554 metadata = new jsAst.LiteralNull(); |
| 1551 metadata = new jsAst.LiteralNull(); | |
| 1552 } | |
| 1553 fieldMetadata.add(metadata); | |
| 1554 } | 1555 } |
| 1555 if (compiler.mirrorsEnabled) { | 1556 fieldMetadata.add(metadata); |
| 1556 recordMangledField(member, accessorName, member.name.slowToString()); | 1557 recordMangledField(member, accessorName, member.name.slowToString()); |
| 1557 } | |
| 1558 if (!needsAccessor) { | 1558 if (!needsAccessor) { |
| 1559 // Emit field for constructor generation. | 1559 // Emit field for constructor generation. |
| 1560 assert(!classIsNative); | 1560 assert(!classIsNative); |
| 1561 buffer.write(name); | 1561 buffer.write(name); |
| 1562 } else { | 1562 } else { |
| 1563 // Emit (possibly renaming) field name so we can add accessors at | 1563 // Emit (possibly renaming) field name so we can add accessors at |
| 1564 // runtime. | 1564 // runtime. |
| 1565 buffer.write(accessorName); | 1565 buffer.write(accessorName); |
| 1566 if (name != accessorName) { | 1566 if (name != accessorName) { |
| 1567 buffer.write(':$name'); | 1567 buffer.write(':$name'); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1678 emitInstanceMembers(classElement, builder); | 1678 emitInstanceMembers(classElement, builder); |
| 1679 } | 1679 } |
| 1680 emitIsTests(classElement, builder); | 1680 emitIsTests(classElement, builder); |
| 1681 | 1681 |
| 1682 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. | 1682 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. |
| 1683 if (!buffer.isEmpty) { | 1683 if (!buffer.isEmpty) { |
| 1684 buffer.write(',$n$n'); | 1684 buffer.write(',$n$n'); |
| 1685 } | 1685 } |
| 1686 buffer.write('$className:$_'); | 1686 buffer.write('$className:$_'); |
| 1687 buffer.write(jsAst.prettyPrint(builder.toObjectInitializer(), compiler)); | 1687 buffer.write(jsAst.prettyPrint(builder.toObjectInitializer(), compiler)); |
| 1688 if (compiler.mirrorsEnabled) { | 1688 if (backend.retainName(classElement.name)) { |
| 1689 buffer.write(',$n$n"+${classElement.name.slowToString()}": 0'); | 1689 buffer.write(',$n$n"+${classElement.name.slowToString()}": 0'); |
| 1690 } | 1690 } |
| 1691 } | 1691 } |
| 1692 | 1692 |
| 1693 bool get getterAndSetterCanBeImplementedByFieldSpec => true; | 1693 bool get getterAndSetterCanBeImplementedByFieldSpec => true; |
| 1694 | 1694 |
| 1695 /// If this is true then we can generate the noSuchMethod handlers at startup | 1695 /// If this is true then we can generate the noSuchMethod handlers at startup |
| 1696 /// time, instead of them being emitted as part of the Object class. | 1696 /// time, instead of them being emitted as part of the Object class. |
| 1697 bool get generateTrivialNsmHandlers => true; | 1697 bool get generateTrivialNsmHandlers => true; |
| 1698 | 1698 |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1911 for (Element element in Elements.sortedByPosition(elements)) { | 1911 for (Element element in Elements.sortedByPosition(elements)) { |
| 1912 CodeBuffer buffer = bufferForElement(element, eagerBuffer); | 1912 CodeBuffer buffer = bufferForElement(element, eagerBuffer); |
| 1913 jsAst.Expression code = backend.generatedCode[element]; | 1913 jsAst.Expression code = backend.generatedCode[element]; |
| 1914 String name = namer.getName(element); | 1914 String name = namer.getName(element); |
| 1915 emitStaticFunction(buffer, name, code); | 1915 emitStaticFunction(buffer, name, code); |
| 1916 var metadata = buildMetadataFunction(element); | 1916 var metadata = buildMetadataFunction(element); |
| 1917 if (metadata != null) { | 1917 if (metadata != null) { |
| 1918 buffer.write(',$n$n"@$name":$_'); | 1918 buffer.write(',$n$n"@$name":$_'); |
| 1919 buffer.write(jsAst.prettyPrint(metadata, compiler)); | 1919 buffer.write(jsAst.prettyPrint(metadata, compiler)); |
| 1920 } | 1920 } |
| 1921 String reflectionName = getReflectionName(element); | 1921 String reflectionName = getReflectionName(element, name); |
| 1922 if (reflectionName != null) { | 1922 if (reflectionName != null) { |
| 1923 buffer.write(',$n$n"+$reflectionName":${_}0'); | 1923 buffer.write(',$n$n"+$reflectionName":${_}0'); |
| 1924 } | 1924 } |
| 1925 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; | 1925 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; |
| 1926 if (bailoutCode != null) { | 1926 if (bailoutCode != null) { |
| 1927 pendingElementsWithBailouts.remove(element); | 1927 pendingElementsWithBailouts.remove(element); |
| 1928 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); | 1928 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); |
| 1929 } | 1929 } |
| 1930 } | 1930 } |
| 1931 | 1931 |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2440 // If we're calling bar on an object of type D, we don't need | 2440 // If we're calling bar on an object of type D, we don't need |
| 2441 // the handler either because all objects of type D implement | 2441 // the handler either because all objects of type D implement |
| 2442 // bar through inheritance. | 2442 // bar through inheritance. |
| 2443 // | 2443 // |
| 2444 // If we're calling bar on an object of type A we do need the | 2444 // If we're calling bar on an object of type A we do need the |
| 2445 // handler because we may have to call B.noSuchMethod since B | 2445 // handler because we may have to call B.noSuchMethod since B |
| 2446 // does not implement bar. | 2446 // does not implement bar. |
| 2447 if (mask.willHit(selector, compiler)) continue; | 2447 if (mask.willHit(selector, compiler)) continue; |
| 2448 String jsName = namer.invocationMirrorInternalName(selector); | 2448 String jsName = namer.invocationMirrorInternalName(selector); |
| 2449 addedJsNames[jsName] = selector; | 2449 addedJsNames[jsName] = selector; |
| 2450 String reflectionName = getReflectionName(selector); | 2450 String reflectionName = getReflectionName(selector, jsName); |
| 2451 if (reflectionName != null) { | 2451 if (reflectionName != null) { |
| 2452 mangledFieldNames[jsName] = reflectionName; | 2452 mangledFieldNames[jsName] = reflectionName; |
| 2453 } | 2453 } |
| 2454 } | 2454 } |
| 2455 } | 2455 } |
| 2456 | 2456 |
| 2457 compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers); | 2457 compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers); |
| 2458 compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers); | 2458 compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers); |
| 2459 compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers); | 2459 compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers); |
| 2460 | 2460 |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3060 if (compiler.enableMinification) buffer.write('\n'); | 3060 if (compiler.enableMinification) buffer.write('\n'); |
| 3061 } | 3061 } |
| 3062 | 3062 |
| 3063 /// The metadata function returns the metadata associated with | 3063 /// The metadata function returns the metadata associated with |
| 3064 /// [element] in generated code. The metadata needs to be wrapped | 3064 /// [element] in generated code. The metadata needs to be wrapped |
| 3065 /// in a function as it refers to constants that may not have been | 3065 /// in a function as it refers to constants that may not have been |
| 3066 /// constructed yet. For example, a class is allowed to be | 3066 /// constructed yet. For example, a class is allowed to be |
| 3067 /// annotated with itself. The metadata function is used by | 3067 /// annotated with itself. The metadata function is used by |
| 3068 /// mirrors_patch to implement DeclarationMirror.metadata. | 3068 /// mirrors_patch to implement DeclarationMirror.metadata. |
| 3069 jsAst.Fun buildMetadataFunction(Element element) { | 3069 jsAst.Fun buildMetadataFunction(Element element) { |
| 3070 if (!compiler.mirrorsEnabled) return null; | 3070 if (!backend.retainMetadataOf(element)) return null; |
| 3071 return compiler.withCurrentElement(element, () { | 3071 return compiler.withCurrentElement(element, () { |
| 3072 var metadata = []; | 3072 var metadata = []; |
| 3073 Link link = element.metadata; | 3073 Link link = element.metadata; |
| 3074 // TODO(ahe): Why is metadata sometimes null? | 3074 // TODO(ahe): Why is metadata sometimes null? |
| 3075 if (link != null) { | 3075 if (link != null) { |
| 3076 for (; !link.isEmpty; link = link.tail) { | 3076 for (; !link.isEmpty; link = link.tail) { |
| 3077 MetadataAnnotation annotation = link.head; | 3077 MetadataAnnotation annotation = link.head; |
| 3078 Constant value = annotation.value; | 3078 Constant value = annotation.value; |
| 3079 if (value == null) { | 3079 if (value == null) { |
| 3080 compiler.reportInternalError( | 3080 compiler.reportInternalError( |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3387 api.Diagnostic.WARNING); | 3387 api.Diagnostic.WARNING); |
| 3388 } | 3388 } |
| 3389 | 3389 |
| 3390 // TODO(ahe): This code should be integrated in finishClasses. | 3390 // TODO(ahe): This code should be integrated in finishClasses. |
| 3391 String getReflectionDataParser() { | 3391 String getReflectionDataParser() { |
| 3392 return ''' | 3392 return ''' |
| 3393 (function (reflectionData) { | 3393 (function (reflectionData) { |
| 3394 if (!init.libraries) init.libraries = []; | 3394 if (!init.libraries) init.libraries = []; |
| 3395 if (!init.mangledNames) init.mangledNames = {}; | 3395 if (!init.mangledNames) init.mangledNames = {}; |
| 3396 if (!init.mangledGlobalNames) init.mangledGlobalNames = {}; | 3396 if (!init.mangledGlobalNames) init.mangledGlobalNames = {}; |
| 3397 init.getterPrefix = "${namer.getterPrefix}"; |
| 3398 init.setterPrefix = "${namer.setterPrefix}"; |
| 3397 var libraries = init.libraries; | 3399 var libraries = init.libraries; |
| 3398 var mangledNames = init.mangledNames; | 3400 var mangledNames = init.mangledNames; |
| 3399 var mangledGlobalNames = init.mangledGlobalNames; | 3401 var mangledGlobalNames = init.mangledGlobalNames; |
| 3400 var hasOwnProperty = Object.prototype.hasOwnProperty; | 3402 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 3401 var length = reflectionData.length; | 3403 var length = reflectionData.length; |
| 3402 for (var i = 0; i < length; i++) { | 3404 for (var i = 0; i < length; i++) { |
| 3403 var data = reflectionData[i]; | 3405 var data = reflectionData[i]; |
| 3404 var name = data[0]; | 3406 var name = data[0]; |
| 3405 var uri = data[1]; | 3407 var uri = data[1]; |
| 3406 var metadata = data[2]; | 3408 var metadata = data[2]; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3452 | 3454 |
| 3453 const String HOOKS_API_USAGE = """ | 3455 const String HOOKS_API_USAGE = """ |
| 3454 // The code supports the following hooks: | 3456 // The code supports the following hooks: |
| 3455 // dartPrint(message) - if this function is defined it is called | 3457 // dartPrint(message) - if this function is defined it is called |
| 3456 // instead of the Dart [print] method. | 3458 // instead of the Dart [print] method. |
| 3457 // dartMainRunner(main) - if this function is defined, the Dart [main] | 3459 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 3458 // method will not be invoked directly. | 3460 // method will not be invoked directly. |
| 3459 // Instead, a closure that will invoke [main] is | 3461 // Instead, a closure that will invoke [main] is |
| 3460 // passed to [dartMainRunner]. | 3462 // passed to [dartMainRunner]. |
| 3461 """; | 3463 """; |
| OLD | NEW |