| 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/names.dart' show Identifiers; | 8 import '../common/names.dart' show Identifiers; |
| 9 import '../compiler.dart' show Compiler; | 9 import '../compiler.dart' show Compiler; |
| 10 import '../diagnostics/messages.dart' show MessageKind; | 10 import '../diagnostics/messages.dart' show MessageKind; |
| 11 import '../constants/values.dart' | 11 import '../constants/values.dart' |
| 12 show | 12 show |
| 13 ConstantValue, | 13 ConstantValue, |
| 14 ConstructedConstantValue, | 14 ConstructedConstantValue, |
| 15 ListConstantValue, | 15 ListConstantValue, |
| 16 NullConstantValue, | 16 NullConstantValue, |
| 17 StringConstantValue, | 17 StringConstantValue, |
| 18 TypeConstantValue; | 18 TypeConstantValue; |
| 19 import '../elements/elements.dart' | 19 import '../elements/elements.dart' |
| 20 show | 20 show |
| 21 ClassElement, | 21 ClassElement, |
| 22 Element, | 22 Element, |
| 23 FieldElement, | 23 FieldElement, |
| 24 FunctionElement, | 24 FunctionElement, |
| 25 LibraryElement, | 25 LibraryElement, |
| 26 ParameterElement, |
| 26 MetadataAnnotation; | 27 MetadataAnnotation; |
| 27 | 28 |
| 28 import '../js/js.dart' as jsAst; | 29 import '../js/js.dart' as jsAst; |
| 29 import '../js/js.dart' show js; | 30 import '../js/js.dart' show js; |
| 30 import '../universe/selector.dart' show Selector; | 31 import '../universe/selector.dart' show Selector; |
| 31 import '../universe/universe.dart' show SelectorConstraints; | 32 import '../universe/universe.dart' show SelectorConstraints; |
| 32 | 33 |
| 33 import 'backend_helpers.dart' show BackendHelpers; | 34 import 'backend_helpers.dart' show BackendHelpers; |
| 34 import 'js_backend.dart' show JavaScriptBackend; | 35 import 'js_backend.dart' show JavaScriptBackend; |
| 35 | 36 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 } else { | 77 } else { |
| 77 // TODO(jacobr): report a warning if the value is not a String. | 78 // TODO(jacobr): report a warning if the value is not a String. |
| 78 backend.setJsInteropName(e, ''); | 79 backend.setJsInteropName(e, ''); |
| 79 } | 80 } |
| 80 enabledJsInterop = true; | 81 enabledJsInterop = true; |
| 81 return; | 82 return; |
| 82 } | 83 } |
| 83 } | 84 } |
| 84 } | 85 } |
| 85 | 86 |
| 87 bool hasAnonymousAnnotation(Element element) { |
| 88 if (backend.helpers.jsAnonymousClass == null) return false; |
| 89 return element.metadata.any((MetadataAnnotation annotation) { |
| 90 ConstantValue constant = backend.compiler.constants.getConstantValue( |
| 91 annotation.constant); |
| 92 if (constant == null || |
| 93 constant is! ConstructedConstantValue) return false; |
| 94 ConstructedConstantValue constructedConstant = constant; |
| 95 return constructedConstant.type.element == |
| 96 backend.helpers.jsAnonymousClass; |
| 97 }); |
| 98 } |
| 99 |
| 100 void _checkFunctionParameters(FunctionElement fn) { |
| 101 if (fn.hasFunctionSignature && |
| 102 fn.functionSignature.optionalParametersAreNamed) { |
| 103 backend.reporter.reportErrorMessage(fn, |
| 104 MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS, { |
| 105 'method': fn.name |
| 106 }); |
| 107 } |
| 108 } |
| 109 |
| 86 void processJsInteropAnnotationsInLibrary(LibraryElement library) { | 110 void processJsInteropAnnotationsInLibrary(LibraryElement library) { |
| 87 processJsInteropAnnotation(library); | 111 processJsInteropAnnotation(library); |
| 88 library.implementation.forEachLocalMember((Element element) { | 112 library.implementation.forEachLocalMember((Element element) { |
| 89 processJsInteropAnnotation(element); | 113 processJsInteropAnnotation(element); |
| 90 if (!element.isClass || !backend.isJsInterop(element)) return; | 114 if (!backend.isJsInterop(element)) return; |
| 115 if (element is FunctionElement) { |
| 116 _checkFunctionParameters(element); |
| 117 } |
| 118 |
| 119 if (!element.isClass) return; |
| 91 | 120 |
| 92 ClassElement classElement = element; | 121 ClassElement classElement = element; |
| 93 | 122 |
| 94 if (!classElement | 123 if (!classElement |
| 95 .implementsInterface(helpers.jsJavaScriptObjectClass)) { | 124 .implementsInterface(helpers.jsJavaScriptObjectClass)) { |
| 96 backend.reporter.reportErrorMessage(classElement, | 125 backend.reporter.reportErrorMessage(classElement, |
| 97 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { | 126 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { |
| 98 'cls': classElement.name, | 127 'cls': classElement.name, |
| 99 'superclass': classElement.superclass.name | 128 'superclass': classElement.superclass.name |
| 100 }); | 129 }); |
| 101 } | 130 } |
| 102 | 131 |
| 103 classElement.forEachMember( | 132 classElement.forEachMember( |
| 104 (ClassElement classElement, Element member) { | 133 (ClassElement classElement, Element member) { |
| 105 processJsInteropAnnotation(member); | 134 processJsInteropAnnotation(member); |
| 106 | 135 |
| 107 if (!member.isSynthesized && | 136 if (!member.isSynthesized && |
| 108 backend.isJsInterop(classElement) && | 137 backend.isJsInterop(classElement) && |
| 109 member is FunctionElement) { | 138 member is FunctionElement) { |
| 110 FunctionElement fn = member; | 139 FunctionElement fn = member; |
| 111 if (!fn.isExternal && !fn.isAbstract) { | 140 if (!fn.isExternal && !fn.isAbstract && !fn.isConstructor && |
| 141 !fn.isStatic) { |
| 112 backend.reporter.reportErrorMessage( | 142 backend.reporter.reportErrorMessage( |
| 113 fn, | 143 fn, |
| 114 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER, | 144 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER, |
| 115 {'cls': classElement.name, 'member': member.name}); | 145 {'cls': classElement.name, 'member': member.name}); |
| 116 } | 146 } |
| 147 |
| 148 if (fn.isFactoryConstructor && hasAnonymousAnnotation(classElement)) { |
| 149 fn.functionSignature.orderedForEachParameter( |
| 150 (ParameterElement parameter) { |
| 151 if (!parameter.isNamed) { |
| 152 backend.reporter.reportErrorMessage(parameter, |
| 153 MessageKind |
| 154 .JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMENTS
, |
| 155 { |
| 156 'parameter': parameter.name, |
| 157 'cls': classElement.name |
| 158 }); |
| 159 } |
| 160 }); |
| 161 } else { |
| 162 _checkFunctionParameters(fn); |
| 163 } |
| 117 } | 164 } |
| 118 }); | 165 }); |
| 119 }); | 166 }); |
| 120 } | 167 } |
| 121 | 168 |
| 122 jsAst.Statement buildJsInteropBootstrap() { | 169 jsAst.Statement buildJsInteropBootstrap() { |
| 123 if (!enabledJsInterop) return null; | 170 if (!enabledJsInterop) return null; |
| 124 List<jsAst.Statement> statements = <jsAst.Statement>[]; | 171 List<jsAst.Statement> statements = <jsAst.Statement>[]; |
| 125 backend.compiler.codegenWorld.forEachInvokedName( | 172 backend.compiler.codegenWorld.forEachInvokedName( |
| 126 (String name, Map<Selector, SelectorConstraints> selectors) { | 173 (String name, Map<Selector, SelectorConstraints> selectors) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 137 var name = backend.namer.invocationName(selector); | 184 var name = backend.namer.invocationName(selector); |
| 138 statements.add(js.statement( | 185 statements.add(js.statement( |
| 139 'Function.prototype.# = function(#) { return this(#) }', | 186 'Function.prototype.# = function(#) { return this(#) }', |
| 140 [name, parameters, parameters])); | 187 [name, parameters, parameters])); |
| 141 } | 188 } |
| 142 }); | 189 }); |
| 143 }); | 190 }); |
| 144 return new jsAst.Block(statements); | 191 return new jsAst.Block(statements); |
| 145 } | 192 } |
| 146 } | 193 } |
| OLD | NEW |