OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library js_backend.native_data; | 5 library js_backend.native_data; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../elements/elements.dart' show | 8 import '../elements/elements.dart' |
9 ClassElement, | 9 show ClassElement, Element, FunctionElement, MemberElement; |
10 Element, | |
11 FunctionElement, | |
12 MemberElement; | |
13 | 10 |
14 /// Additional element information for native classes and methods and js-interop | 11 /// Additional element information for native classes and methods and js-interop |
15 /// methods. | 12 /// methods. |
16 class NativeData { | 13 class NativeData { |
17 /// The JavaScript names for elements implemented via typed JavaScript | 14 /// The JavaScript names for elements implemented via typed JavaScript |
18 /// interop. | 15 /// interop. |
19 Map<Element, String> jsInteropNames = <Element, String>{}; | 16 Map<Element, String> jsInteropNames = <Element, String>{}; |
20 | 17 |
21 /// The JavaScript names for native JavaScript elements implemented. | 18 /// The JavaScript names for native JavaScript elements implemented. |
22 Map<Element, String> nativeMemberName = <Element, String>{}; | 19 Map<Element, String> nativeMemberName = <Element, String>{}; |
23 | 20 |
24 /// Tag info for native JavaScript classes names. See | 21 /// Tag info for native JavaScript classes names. See |
25 /// [setNativeClassTagInfo]. | 22 /// [setNativeClassTagInfo]. |
26 Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{}; | 23 Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{}; |
27 | 24 |
28 /// Returns `true` if [element] is explicitly marked as part of JsInterop. | 25 /// Returns `true` if [element] is explicitly marked as part of JsInterop. |
29 bool _isJsInterop(Element element) { | 26 bool _isJsInterop(Element element) { |
30 return jsInteropNames.containsKey(element.declaration); | 27 return jsInteropNames.containsKey(element.declaration); |
31 } | 28 } |
32 | 29 |
33 /// Returns [element] as an explicit part of JsInterop. The js interop name is | 30 /// Returns [element] as an explicit part of JsInterop. The js interop name is |
34 /// expected to be computed later. | 31 /// expected to be computed later. |
35 void markAsJsInterop(Element element) { | 32 void markAsJsInterop(Element element) { |
36 jsInteropNames[element.declaration] = null; | 33 jsInteropNames[element.declaration] = null; |
37 } | 34 } |
38 | 35 |
39 /// Sets the explicit js interop [name] for [element]. | 36 /// Sets the explicit js interop [name] for [element]. |
40 void setJsInteropName(Element element, String name) { | 37 void setJsInteropName(Element element, String name) { |
41 assert(invariant(element, | 38 assert(invariant(element, isJsInterop(element), |
42 isJsInterop(element), | |
43 message: | 39 message: |
44 'Element $element is not js interop but given a js interop name.')); | 40 'Element $element is not js interop but given a js interop name.')); |
45 jsInteropNames[element.declaration] = name; | 41 jsInteropNames[element.declaration] = name; |
46 } | 42 } |
47 | 43 |
48 /// Returns the explicit js interop name for [element]. | 44 /// Returns the explicit js interop name for [element]. |
49 String getJsInteropName(Element element) { | 45 String getJsInteropName(Element element) { |
50 return jsInteropNames[element.declaration]; | 46 return jsInteropNames[element.declaration]; |
51 } | 47 } |
52 | 48 |
53 /// Returns `true` if [element] is part of JsInterop. | 49 /// Returns `true` if [element] is part of JsInterop. |
54 bool isJsInterop(Element element) { | 50 bool isJsInterop(Element element) { |
(...skipping 15 matching lines...) Expand all Loading... |
70 | 66 |
71 /// Returns `true` if the name of [element] is fixed for the generated | 67 /// Returns `true` if the name of [element] is fixed for the generated |
72 /// JavaScript. | 68 /// JavaScript. |
73 bool hasFixedBackendName(Element element) { | 69 bool hasFixedBackendName(Element element) { |
74 return isJsInterop(element) || | 70 return isJsInterop(element) || |
75 nativeMemberName.containsKey(element.declaration); | 71 nativeMemberName.containsKey(element.declaration); |
76 } | 72 } |
77 | 73 |
78 String _jsNameHelper(Element element) { | 74 String _jsNameHelper(Element element) { |
79 String jsInteropName = jsInteropNames[element.declaration]; | 75 String jsInteropName = jsInteropNames[element.declaration]; |
80 assert(invariant(element, | 76 assert(invariant(element, !(_isJsInterop(element) && jsInteropName == null), |
81 !(_isJsInterop(element) && jsInteropName == null), | |
82 message: | 77 message: |
83 'Element $element is js interop but js interop name has not yet ' | 78 'Element $element is js interop but js interop name has not yet ' |
84 'been computed.')); | 79 'been computed.')); |
85 if (jsInteropName != null && jsInteropName.isNotEmpty) { | 80 if (jsInteropName != null && jsInteropName.isNotEmpty) { |
86 return jsInteropName; | 81 return jsInteropName; |
87 } | 82 } |
88 return element.isLibrary ? 'self' : element.name; | 83 return element.isLibrary ? 'self' : element.name; |
89 } | 84 } |
90 | 85 |
91 /// Computes the name for [element] to use in the generated JavaScript. This | 86 /// Computes the name for [element] to use in the generated JavaScript. This |
(...skipping 22 matching lines...) Expand all Loading... |
114 return nativeMemberName.containsKey(element.declaration); | 109 return nativeMemberName.containsKey(element.declaration); |
115 } | 110 } |
116 } | 111 } |
117 | 112 |
118 /// Sets the native [name] for the member [element]. This name is used for | 113 /// Sets the native [name] for the member [element]. This name is used for |
119 /// [element] in the generated JavaScript. | 114 /// [element] in the generated JavaScript. |
120 void setNativeMemberName(MemberElement element, String name) { | 115 void setNativeMemberName(MemberElement element, String name) { |
121 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer | 116 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer |
122 // might enqueue [element] several times (before processing it) and computes | 117 // might enqueue [element] several times (before processing it) and computes |
123 // name on each call to `internalAddToWorkList`. | 118 // name on each call to `internalAddToWorkList`. |
124 assert(invariant(element, | 119 assert(invariant( |
| 120 element, |
125 nativeMemberName[element.declaration] == null || | 121 nativeMemberName[element.declaration] == null || |
126 nativeMemberName[element.declaration] == name, | 122 nativeMemberName[element.declaration] == name, |
127 message: | 123 message: "Native member name set inconsistently on $element: " |
128 "Native member name set inconsistently on $element: " | 124 "Existing name '${nativeMemberName[element.declaration]}', " |
129 "Existing name '${nativeMemberName[element.declaration]}', " | 125 "new name '$name'.")); |
130 "new name '$name'.")); | |
131 nativeMemberName[element.declaration] = name; | 126 nativeMemberName[element.declaration] = name; |
132 } | 127 } |
133 | 128 |
134 /// Sets the native tag info for [cls]. | 129 /// Sets the native tag info for [cls]. |
135 /// | 130 /// |
136 /// The tag info string contains comma-separated 'words' which are either | 131 /// The tag info string contains comma-separated 'words' which are either |
137 /// dispatch tags (having JavaScript identifier syntax) and directives that | 132 /// dispatch tags (having JavaScript identifier syntax) and directives that |
138 /// begin with `!`. | 133 /// begin with `!`. |
139 void setNativeClassTagInfo(ClassElement cls, String tagInfo) { | 134 void setNativeClassTagInfo(ClassElement cls, String tagInfo) { |
140 // TODO(johnniwinther): Assert that this is only called once. The memory | 135 // TODO(johnniwinther): Assert that this is only called once. The memory |
141 // compiler copies pre-processed elements into a new compiler through | 136 // compiler copies pre-processed elements into a new compiler through |
142 // [Compiler.onLibraryScanned] and thereby causes multiple calls to this | 137 // [Compiler.onLibraryScanned] and thereby causes multiple calls to this |
143 // method. | 138 // method. |
144 assert(invariant(cls, | 139 assert(invariant( |
| 140 cls, |
145 nativeClassTagInfo[cls.declaration] == null || | 141 nativeClassTagInfo[cls.declaration] == null || |
146 nativeClassTagInfo[cls.declaration] == tagInfo, | 142 nativeClassTagInfo[cls.declaration] == tagInfo, |
147 message: | 143 message: "Native tag info set inconsistently on $cls: " |
148 "Native tag info set inconsistently on $cls: " | 144 "Existing tag info '${nativeClassTagInfo[cls.declaration]}', " |
149 "Existing tag info '${nativeClassTagInfo[cls.declaration]}', " | 145 "new tag info '$tagInfo'.")); |
150 "new tag info '$tagInfo'.")); | |
151 nativeClassTagInfo[cls.declaration] = tagInfo; | 146 nativeClassTagInfo[cls.declaration] = tagInfo; |
152 } | 147 } |
153 | 148 |
154 /// Returns the list of native tag words for [cls]. | 149 /// Returns the list of native tag words for [cls]. |
155 List<String> getNativeTagsOfClassRaw(ClassElement cls) { | 150 List<String> getNativeTagsOfClassRaw(ClassElement cls) { |
156 String quotedName = nativeClassTagInfo[cls.declaration]; | 151 String quotedName = nativeClassTagInfo[cls.declaration]; |
157 return quotedName.substring(1, quotedName.length - 1).split(','); | 152 return quotedName.substring(1, quotedName.length - 1).split(','); |
158 } | 153 } |
159 | 154 |
160 /// Returns the list of non-directive native tag words for [cls]. | 155 /// Returns the list of non-directive native tag words for [cls]. |
161 List<String> getNativeTagsOfClass(ClassElement cls) { | 156 List<String> getNativeTagsOfClass(ClassElement cls) { |
162 return getNativeTagsOfClassRaw(cls).where( | 157 return getNativeTagsOfClassRaw(cls) |
163 (s) => !s.startsWith('!')).toList(); | 158 .where((s) => !s.startsWith('!')) |
| 159 .toList(); |
164 } | 160 } |
165 | 161 |
166 /// Returns `true` if [cls] has a `!nonleaf` tag word. | 162 /// Returns `true` if [cls] has a `!nonleaf` tag word. |
167 bool hasNativeTagsForcedNonLeaf(ClassElement cls) { | 163 bool hasNativeTagsForcedNonLeaf(ClassElement cls) { |
168 return getNativeTagsOfClassRaw(cls).contains('!nonleaf'); | 164 return getNativeTagsOfClassRaw(cls).contains('!nonleaf'); |
169 } | 165 } |
170 } | 166 } |
OLD | NEW |