| 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; |
| 11 import '../elements/resolution_types.dart' | 11 import '../elements/resolution_types.dart' |
| 12 show ResolutionDartType, ResolutionDynamicType, ResolutionFunctionType; | 12 show ResolutionDartType, ResolutionDynamicType, ResolutionFunctionType; |
| 13 import '../diagnostics/messages.dart' show MessageKind; | 13 import '../diagnostics/messages.dart' show MessageKind; |
| 14 import '../elements/elements.dart' | 14 import '../elements/elements.dart' |
| 15 show | 15 show |
| 16 ClassElement, | 16 ClassElement, |
| 17 Element, | 17 Element, |
| 18 FieldElement, | 18 FieldElement, |
| 19 FunctionElement, | 19 FunctionElement, |
| 20 LibraryElement, | 20 LibraryElement, |
| 21 ParameterElement, | 21 ParameterElement, |
| 22 MethodElement, |
| 22 MetadataAnnotation; | 23 MetadataAnnotation; |
| 23 import '../js/js.dart' as jsAst; | 24 import '../js/js.dart' as jsAst; |
| 24 import '../js/js.dart' show js; | 25 import '../js/js.dart' show js; |
| 25 import '../universe/selector.dart' show Selector; | 26 import '../universe/selector.dart' show Selector; |
| 26 import '../universe/world_builder.dart' show SelectorConstraints; | 27 import '../universe/world_builder.dart' show SelectorConstraints; |
| 27 import 'backend_helpers.dart' show BackendHelpers; | 28 import 'backend_helpers.dart' show BackendHelpers; |
| 28 import 'js_backend.dart' show JavaScriptBackend; | 29 import 'js_backend.dart' show JavaScriptBackend; |
| 29 | 30 |
| 30 class JsInteropAnalysis { | 31 class JsInteropAnalysis { |
| 31 final JavaScriptBackend backend; | 32 final JavaScriptBackend backend; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 61 // TODO(johnniwinther): Avoid processing unresolved elements. | 62 // TODO(johnniwinther): Avoid processing unresolved elements. |
| 62 if (annotation.constant == null) continue; | 63 if (annotation.constant == null) continue; |
| 63 ConstantValue constant = | 64 ConstantValue constant = |
| 64 backend.compiler.constants.getConstantValue(annotation.constant); | 65 backend.compiler.constants.getConstantValue(annotation.constant); |
| 65 if (constant == null || constant is! ConstructedConstantValue) continue; | 66 if (constant == null || constant is! ConstructedConstantValue) continue; |
| 66 ConstructedConstantValue constructedConstant = constant; | 67 ConstructedConstantValue constructedConstant = constant; |
| 67 if (constructedConstant.type.element == helpers.jsAnnotationClass) { | 68 if (constructedConstant.type.element == helpers.jsAnnotationClass) { |
| 68 ConstantValue value = constructedConstant.fields[nameField]; | 69 ConstantValue value = constructedConstant.fields[nameField]; |
| 69 if (value.isString) { | 70 if (value.isString) { |
| 70 StringConstantValue stringValue = value; | 71 StringConstantValue stringValue = value; |
| 71 backend.nativeClassDataBuilder | 72 backend.nativeDataBuilder |
| 72 .setJsInteropName(e, stringValue.primitiveValue.slowToString()); | 73 .setJsInteropName(e, stringValue.primitiveValue.slowToString()); |
| 73 } else { | 74 } else { |
| 74 // TODO(jacobr): report a warning if the value is not a String. | 75 // TODO(jacobr): report a warning if the value is not a String. |
| 75 backend.nativeClassDataBuilder.setJsInteropName(e, ''); | 76 backend.nativeDataBuilder.setJsInteropName(e, ''); |
| 76 } | 77 } |
| 77 enabledJsInterop = true; | 78 enabledJsInterop = true; |
| 78 return; | 79 return; |
| 79 } | 80 } |
| 80 } | 81 } |
| 81 } | 82 } |
| 82 | 83 |
| 83 bool hasAnonymousAnnotation(Element element) { | 84 bool hasAnonymousAnnotation(Element element) { |
| 84 if (backend.helpers.jsAnonymousClass == null) return false; | 85 if (backend.helpers.jsAnonymousClass == null) return false; |
| 85 return element.metadata.any((MetadataAnnotation annotation) { | 86 return element.metadata.any((MetadataAnnotation annotation) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 100 fn, | 101 fn, |
| 101 MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS, | 102 MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS, |
| 102 {'method': fn.name}); | 103 {'method': fn.name}); |
| 103 } | 104 } |
| 104 } | 105 } |
| 105 | 106 |
| 106 void processJsInteropAnnotationsInLibrary(LibraryElement library) { | 107 void processJsInteropAnnotationsInLibrary(LibraryElement library) { |
| 107 processJsInteropAnnotation(library); | 108 processJsInteropAnnotation(library); |
| 108 library.implementation.forEachLocalMember((Element element) { | 109 library.implementation.forEachLocalMember((Element element) { |
| 109 processJsInteropAnnotation(element); | 110 processJsInteropAnnotation(element); |
| 110 if (!backend.nativeData.isJsInterop(element)) return; | 111 if (element is MethodElement) { |
| 111 if (element is FunctionElement) { | 112 if (!backend.nativeData.isJsInteropMember(element)) return; |
| 112 _checkFunctionParameters(element); | 113 _checkFunctionParameters(element); |
| 113 } | 114 } |
| 114 | 115 |
| 115 if (!element.isClass) return; | 116 if (!element.isClass) return; |
| 116 | 117 |
| 117 ClassElement classElement = element; | 118 ClassElement classElement = element; |
| 119 if (!backend.nativeData.isJsInteropClass(classElement)) return; |
| 118 | 120 |
| 119 // Skip classes that are completely unreachable. This should only happen | 121 // Skip classes that are completely unreachable. This should only happen |
| 120 // when all of jsinterop types are unreachable from main. | 122 // when all of jsinterop types are unreachable from main. |
| 121 if (!backend.compiler.resolutionWorldBuilder | 123 if (!backend.compiler.resolutionWorldBuilder |
| 122 .isImplemented(classElement)) { | 124 .isImplemented(classElement)) { |
| 123 return; | 125 return; |
| 124 } | 126 } |
| 125 | 127 |
| 126 if (!classElement.implementsInterface(helpers.jsJavaScriptObjectClass)) { | 128 if (!classElement.implementsInterface(helpers.jsJavaScriptObjectClass)) { |
| 127 backend.reporter.reportErrorMessage(classElement, | 129 backend.reporter.reportErrorMessage(classElement, |
| 128 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { | 130 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { |
| 129 'cls': classElement.name, | 131 'cls': classElement.name, |
| 130 'superclass': classElement.superclass.name | 132 'superclass': classElement.superclass.name |
| 131 }); | 133 }); |
| 132 } | 134 } |
| 133 | 135 |
| 134 classElement.forEachMember((ClassElement classElement, Element member) { | 136 classElement.forEachMember((ClassElement classElement, Element member) { |
| 135 processJsInteropAnnotation(member); | 137 processJsInteropAnnotation(member); |
| 136 | 138 |
| 137 if (!member.isSynthesized && | 139 if (!member.isSynthesized && |
| 138 backend.nativeData.isJsInterop(classElement) && | 140 backend.nativeData.isJsInteropClass(classElement) && |
| 139 member is FunctionElement) { | 141 member is FunctionElement) { |
| 140 FunctionElement fn = member; | 142 FunctionElement fn = member; |
| 141 if (!fn.isExternal && | 143 if (!fn.isExternal && |
| 142 !fn.isAbstract && | 144 !fn.isAbstract && |
| 143 !fn.isConstructor && | 145 !fn.isConstructor && |
| 144 !fn.isStatic) { | 146 !fn.isStatic) { |
| 145 backend.reporter.reportErrorMessage( | 147 backend.reporter.reportErrorMessage( |
| 146 fn, | 148 fn, |
| 147 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER, | 149 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER, |
| 148 {'cls': classElement.name, 'member': member.name}); | 150 {'cls': classElement.name, 'member': member.name}); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 ResolutionFunctionType buildJsFunctionType() { | 197 ResolutionFunctionType buildJsFunctionType() { |
| 196 // TODO(jacobr): consider using codegenWorldBuilder.isChecks to determine th
e | 198 // TODO(jacobr): consider using codegenWorldBuilder.isChecks to determine th
e |
| 197 // range of positional arguments that need to be supported by JavaScript | 199 // range of positional arguments that need to be supported by JavaScript |
| 198 // function types. | 200 // function types. |
| 199 return new ResolutionFunctionType.synthesized( | 201 return new ResolutionFunctionType.synthesized( |
| 200 const ResolutionDynamicType(), | 202 const ResolutionDynamicType(), |
| 201 [], | 203 [], |
| 202 new List<ResolutionDartType>.filled(16, const ResolutionDynamicType())); | 204 new List<ResolutionDartType>.filled(16, const ResolutionDynamicType())); |
| 203 } | 205 } |
| 204 } | 206 } |
| OLD | NEW |