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 |