| 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; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 FieldElement, | 23 FieldElement, |
| 24 FunctionElement, | 24 FunctionElement, |
| 25 LibraryElement, | 25 LibraryElement, |
| 26 MetadataAnnotation; | 26 MetadataAnnotation; |
| 27 | 27 |
| 28 import '../js/js.dart' as jsAst; | 28 import '../js/js.dart' as jsAst; |
| 29 import '../js/js.dart' show js; | 29 import '../js/js.dart' show js; |
| 30 import '../universe/selector.dart' show Selector; | 30 import '../universe/selector.dart' show Selector; |
| 31 import '../universe/universe.dart' show SelectorConstraints; | 31 import '../universe/universe.dart' show SelectorConstraints; |
| 32 | 32 |
| 33 import 'backend_helpers.dart' show BackendHelpers; |
| 33 import 'js_backend.dart' show JavaScriptBackend; | 34 import 'js_backend.dart' show JavaScriptBackend; |
| 34 | 35 |
| 35 class JsInteropAnalysis { | 36 class JsInteropAnalysis { |
| 36 final JavaScriptBackend backend; | 37 final JavaScriptBackend backend; |
| 37 | 38 |
| 38 /// The resolved [FieldElement] for `Js.name`. | 39 /// The resolved [FieldElement] for `Js.name`. |
| 39 FieldElement nameField; | 40 FieldElement nameField; |
| 40 bool enabledJsInterop = false; | 41 bool enabledJsInterop = false; |
| 41 | 42 |
| 42 /// Whether the backend is currently processing the codegen queue. | 43 /// Whether the backend is currently processing the codegen queue. |
| 43 bool _inCodegen = false; | 44 bool _inCodegen = false; |
| 44 | 45 |
| 45 JsInteropAnalysis(this.backend); | 46 JsInteropAnalysis(this.backend); |
| 46 | 47 |
| 48 BackendHelpers get helpers => backend.helpers; |
| 49 |
| 47 void onQueueClosed() { | 50 void onQueueClosed() { |
| 48 if (_inCodegen) return; | 51 if (_inCodegen) return; |
| 49 | 52 |
| 50 if (backend.jsAnnotationClass != null) { | 53 if (helpers.jsAnnotationClass != null) { |
| 51 nameField = backend.jsAnnotationClass.lookupMember('name'); | 54 nameField = helpers.jsAnnotationClass.lookupMember('name'); |
| 52 backend.compiler.libraryLoader.libraries | 55 backend.compiler.libraryLoader.libraries |
| 53 .forEach(processJsInteropAnnotationsInLibrary); | 56 .forEach(processJsInteropAnnotationsInLibrary); |
| 54 } | 57 } |
| 55 } | 58 } |
| 56 | 59 |
| 57 void onCodegenStart() { | 60 void onCodegenStart() { |
| 58 _inCodegen = true; | 61 _inCodegen = true; |
| 59 } | 62 } |
| 60 | 63 |
| 61 void processJsInteropAnnotation(Element e) { | 64 void processJsInteropAnnotation(Element e) { |
| 62 for (MetadataAnnotation annotation in e.implementation.metadata) { | 65 for (MetadataAnnotation annotation in e.implementation.metadata) { |
| 63 ConstantValue constant = backend.compiler.constants.getConstantValue( | 66 ConstantValue constant = backend.compiler.constants.getConstantValue( |
| 64 annotation.constant); | 67 annotation.constant); |
| 65 if (constant == null || constant is! ConstructedConstantValue) continue; | 68 if (constant == null || constant is! ConstructedConstantValue) continue; |
| 66 ConstructedConstantValue constructedConstant = constant; | 69 ConstructedConstantValue constructedConstant = constant; |
| 67 if (constructedConstant.type.element == backend.jsAnnotationClass) { | 70 if (constructedConstant.type.element == helpers.jsAnnotationClass) { |
| 68 ConstantValue value = constructedConstant.fields[nameField]; | 71 ConstantValue value = constructedConstant.fields[nameField]; |
| 69 if (value.isString) { | 72 if (value.isString) { |
| 70 StringConstantValue stringValue = value; | 73 StringConstantValue stringValue = value; |
| 71 backend.setJsInteropName( | 74 backend.setJsInteropName( |
| 72 e, stringValue.primitiveValue.slowToString()); | 75 e, stringValue.primitiveValue.slowToString()); |
| 73 } else { | 76 } else { |
| 74 // TODO(jacobr): report a warning if the value is not a String. | 77 // TODO(jacobr): report a warning if the value is not a String. |
| 75 backend.setJsInteropName(e, ''); | 78 backend.setJsInteropName(e, ''); |
| 76 } | 79 } |
| 77 enabledJsInterop = true; | 80 enabledJsInterop = true; |
| 78 return; | 81 return; |
| 79 } | 82 } |
| 80 } | 83 } |
| 81 } | 84 } |
| 82 | 85 |
| 83 void processJsInteropAnnotationsInLibrary(LibraryElement library) { | 86 void processJsInteropAnnotationsInLibrary(LibraryElement library) { |
| 84 processJsInteropAnnotation(library); | 87 processJsInteropAnnotation(library); |
| 85 library.implementation.forEachLocalMember((Element element) { | 88 library.implementation.forEachLocalMember((Element element) { |
| 86 processJsInteropAnnotation(element); | 89 processJsInteropAnnotation(element); |
| 87 if (!element.isClass || !backend.isJsInterop(element)) return; | 90 if (!element.isClass || !backend.isJsInterop(element)) return; |
| 88 | 91 |
| 89 ClassElement classElement = element; | 92 ClassElement classElement = element; |
| 90 | 93 |
| 91 if (!classElement | 94 if (!classElement |
| 92 .implementsInterface(backend.jsJavaScriptObjectClass)) { | 95 .implementsInterface(helpers.jsJavaScriptObjectClass)) { |
| 93 backend.reporter.reportErrorMessage(classElement, | 96 backend.reporter.reportErrorMessage(classElement, |
| 94 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { | 97 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { |
| 95 'cls': classElement.name, | 98 'cls': classElement.name, |
| 96 'superclass': classElement.superclass.name | 99 'superclass': classElement.superclass.name |
| 97 }); | 100 }); |
| 98 } | 101 } |
| 99 | 102 |
| 100 classElement.forEachMember( | 103 classElement.forEachMember( |
| 101 (ClassElement classElement, Element member) { | 104 (ClassElement classElement, Element member) { |
| 102 processJsInteropAnnotation(member); | 105 processJsInteropAnnotation(member); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 var name = backend.namer.invocationName(selector); | 137 var name = backend.namer.invocationName(selector); |
| 135 statements.add(js.statement( | 138 statements.add(js.statement( |
| 136 'Function.prototype.# = function(#) { return this(#) }', | 139 'Function.prototype.# = function(#) { return this(#) }', |
| 137 [name, parameters, parameters])); | 140 [name, parameters, parameters])); |
| 138 } | 141 } |
| 139 }); | 142 }); |
| 140 }); | 143 }); |
| 141 return new jsAst.Block(statements); | 144 return new jsAst.Block(statements); |
| 142 } | 145 } |
| 143 } | 146 } |
| OLD | NEW |