| 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 /// Analysis to determine how to generate code for typed JavaScript interop. | 5 /// Analysis to determine how to generate code for typed JavaScript interop. |
| 6 library compiler.src.js_backend.js_interop_analysis; | 6 library compiler.src.js_backend.js_interop_analysis; |
| 7 | 7 |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../constants/values.dart' | 9 import '../constants/values.dart' |
| 10 show ConstantValue, ConstructedConstantValue, StringConstantValue; | 10 show ConstantValue, ConstructedConstantValue, StringConstantValue; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 // TODO(johnniwinther): Avoid processing unresolved elements. | 61 // TODO(johnniwinther): Avoid processing unresolved elements. |
| 62 if (annotation.constant == null) continue; | 62 if (annotation.constant == null) continue; |
| 63 ConstantValue constant = | 63 ConstantValue constant = |
| 64 backend.compiler.constants.getConstantValue(annotation.constant); | 64 backend.compiler.constants.getConstantValue(annotation.constant); |
| 65 if (constant == null || constant is! ConstructedConstantValue) continue; | 65 if (constant == null || constant is! ConstructedConstantValue) continue; |
| 66 ConstructedConstantValue constructedConstant = constant; | 66 ConstructedConstantValue constructedConstant = constant; |
| 67 if (constructedConstant.type.element == helpers.jsAnnotationClass) { | 67 if (constructedConstant.type.element == helpers.jsAnnotationClass) { |
| 68 ConstantValue value = constructedConstant.fields[nameField]; | 68 ConstantValue value = constructedConstant.fields[nameField]; |
| 69 if (value.isString) { | 69 if (value.isString) { |
| 70 StringConstantValue stringValue = value; | 70 StringConstantValue stringValue = value; |
| 71 backend.nativeData | 71 backend.nativeDataBuilder |
| 72 .setJsInteropName(e, stringValue.primitiveValue.slowToString()); | 72 .setJsInteropName(e, stringValue.primitiveValue.slowToString()); |
| 73 } else { | 73 } else { |
| 74 // TODO(jacobr): report a warning if the value is not a String. | 74 // TODO(jacobr): report a warning if the value is not a String. |
| 75 backend.nativeData.setJsInteropName(e, ''); | 75 backend.nativeDataBuilder.setJsInteropName(e, ''); |
| 76 } | 76 } |
| 77 enabledJsInterop = true; | 77 enabledJsInterop = true; |
| 78 return; | 78 return; |
| 79 } | 79 } |
| 80 } | 80 } |
| 81 } | 81 } |
| 82 | 82 |
| 83 bool hasAnonymousAnnotation(Element element) { | 83 bool hasAnonymousAnnotation(Element element) { |
| 84 if (backend.helpers.jsAnonymousClass == null) return false; | 84 if (backend.helpers.jsAnonymousClass == null) return false; |
| 85 return element.metadata.any((MetadataAnnotation annotation) { | 85 return element.metadata.any((MetadataAnnotation annotation) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 100 fn, | 100 fn, |
| 101 MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS, | 101 MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS, |
| 102 {'method': fn.name}); | 102 {'method': fn.name}); |
| 103 } | 103 } |
| 104 } | 104 } |
| 105 | 105 |
| 106 void processJsInteropAnnotationsInLibrary(LibraryElement library) { | 106 void processJsInteropAnnotationsInLibrary(LibraryElement library) { |
| 107 processJsInteropAnnotation(library); | 107 processJsInteropAnnotation(library); |
| 108 library.implementation.forEachLocalMember((Element element) { | 108 library.implementation.forEachLocalMember((Element element) { |
| 109 processJsInteropAnnotation(element); | 109 processJsInteropAnnotation(element); |
| 110 if (!backend.isJsInterop(element)) return; | 110 if (!backend.nativeData.isJsInterop(element)) return; |
| 111 if (element is FunctionElement) { | 111 if (element is FunctionElement) { |
| 112 _checkFunctionParameters(element); | 112 _checkFunctionParameters(element); |
| 113 } | 113 } |
| 114 | 114 |
| 115 if (!element.isClass) return; | 115 if (!element.isClass) return; |
| 116 | 116 |
| 117 ClassElement classElement = element; | 117 ClassElement classElement = element; |
| 118 | 118 |
| 119 // Skip classes that are completely unreachable. This should only happen | 119 // Skip classes that are completely unreachable. This should only happen |
| 120 // when all of jsinterop types are unreachable from main. | 120 // when all of jsinterop types are unreachable from main. |
| 121 if (!backend.compiler.resolutionWorldBuilder | 121 if (!backend.compiler.resolutionWorldBuilder |
| 122 .isImplemented(classElement)) { | 122 .isImplemented(classElement)) { |
| 123 return; | 123 return; |
| 124 } | 124 } |
| 125 | 125 |
| 126 if (!classElement.implementsInterface(helpers.jsJavaScriptObjectClass)) { | 126 if (!classElement.implementsInterface(helpers.jsJavaScriptObjectClass)) { |
| 127 backend.reporter.reportErrorMessage(classElement, | 127 backend.reporter.reportErrorMessage(classElement, |
| 128 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { | 128 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { |
| 129 'cls': classElement.name, | 129 'cls': classElement.name, |
| 130 'superclass': classElement.superclass.name | 130 'superclass': classElement.superclass.name |
| 131 }); | 131 }); |
| 132 } | 132 } |
| 133 | 133 |
| 134 classElement.forEachMember((ClassElement classElement, Element member) { | 134 classElement.forEachMember((ClassElement classElement, Element member) { |
| 135 processJsInteropAnnotation(member); | 135 processJsInteropAnnotation(member); |
| 136 | 136 |
| 137 if (!member.isSynthesized && | 137 if (!member.isSynthesized && |
| 138 backend.isJsInterop(classElement) && | 138 backend.nativeData.isJsInterop(classElement) && |
| 139 member is FunctionElement) { | 139 member is FunctionElement) { |
| 140 FunctionElement fn = member; | 140 FunctionElement fn = member; |
| 141 if (!fn.isExternal && | 141 if (!fn.isExternal && |
| 142 !fn.isAbstract && | 142 !fn.isAbstract && |
| 143 !fn.isConstructor && | 143 !fn.isConstructor && |
| 144 !fn.isStatic) { | 144 !fn.isStatic) { |
| 145 backend.reporter.reportErrorMessage( | 145 backend.reporter.reportErrorMessage( |
| 146 fn, | 146 fn, |
| 147 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER, | 147 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER, |
| 148 {'cls': classElement.name, 'member': member.name}); | 148 {'cls': classElement.name, 'member': member.name}); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 ResolutionFunctionType buildJsFunctionType() { | 195 ResolutionFunctionType buildJsFunctionType() { |
| 196 // TODO(jacobr): consider using codegenWorldBuilder.isChecks to determine th
e | 196 // TODO(jacobr): consider using codegenWorldBuilder.isChecks to determine th
e |
| 197 // range of positional arguments that need to be supported by JavaScript | 197 // range of positional arguments that need to be supported by JavaScript |
| 198 // function types. | 198 // function types. |
| 199 return new ResolutionFunctionType.synthesized( | 199 return new ResolutionFunctionType.synthesized( |
| 200 const ResolutionDynamicType(), | 200 const ResolutionDynamicType(), |
| 201 [], | 201 [], |
| 202 new List<ResolutionDartType>.filled(16, const ResolutionDynamicType())); | 202 new List<ResolutionDartType>.filled(16, const ResolutionDynamicType())); |
| 203 } | 203 } |
| 204 } | 204 } |
| OLD | NEW |