Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: pkg/compiler/lib/src/js_backend/native_data.dart

Issue 2721403006: Split NativeData (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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' 8 import '../elements/elements.dart'
9 show ClassElement, Element, FieldElement, FunctionElement, MemberElement; 9 show
10 ClassElement,
11 Element,
12 FieldElement,
13 FunctionElement,
14 MemberElement,
15 MethodElement;
10 import '../elements/entities.dart'; 16 import '../elements/entities.dart';
11 import '../native/behavior.dart' show NativeBehavior; 17 import '../native/behavior.dart' show NativeBehavior;
12 18
13 /// Additional element information for native classes and methods and js-interop 19 /// Additional element information for native classes and methods and js-interop
14 /// methods. 20 /// methods.
15 class NativeData { 21 abstract class NativeData {
22 /// Returns `true` if [cls] corresponds to a native JavaScript class.
23 ///
24 /// A class is marked as native either through the `@Native(...)` annotation
25 /// allowed for internal libraries or via the typed JavaScriptInterop
26 /// mechanism allowed for user libraries.
27 bool isNativeClass(ClassEntity element);
28
29 /// Returns `true` if [element] corresponds to a native JavaScript member.
30 ///
31 /// A member is marked as native either through the native mechanism
32 /// (`@Native(...)` or the `native` pseudo keyword) allowed for internal
Siggi Cherem (dart-lang) 2017/03/14 00:15:59 doesn't this require also `external`?
Johnni Winther 2017/03/14 15:48:04 We correctly don't use external in dart:html.
33 /// libraries or via the typed JavaScriptInterop mechanism allowed for user
34 /// libraries.
35 bool isNativeMember(MemberEntity element);
36
37 /// Returns `true` if [element] or any of its superclasses is native.
38 bool isNativeOrExtendsNative(ClassElement element);
39
40 /// Returns `true` if the name of [element] is fixed for the generated
41 /// JavaScript.
42 bool hasFixedBackendName(Element element);
43
44 /// Computes the name for [element] to use in the generated JavaScript. This
45 /// is either given through a native annotation or a js interop annotation.
46 String getFixedBackendName(Entity entity);
47
48 /// Returns the list of non-directive native tag words for [cls].
49 List<String> getNativeTagsOfClass(ClassElement cls);
50
51 /// Returns `true` if [cls] has a `!nonleaf` tag word.
52 bool hasNativeTagsForcedNonLeaf(ClassElement cls);
53
54 /// Returns the [NativeBehavior] for calling the native [method].
55 NativeBehavior getNativeMethodBehavior(MethodElement method);
56
57 /// Returns the [NativeBehavior] for reading from the native [field].
58 NativeBehavior getNativeFieldLoadBehavior(FieldElement field);
59
60 /// Returns the [NativeBehavior] for writing to the native [field].
61 NativeBehavior getNativeFieldStoreBehavior(FieldElement field);
62
63 /// Returns `true` if [element] is part of JsInterop.
64 bool isJsInterop(Element element);
65
66 /// Returns `true` if [element] is a JsInterop class.
67 bool isJsInteropClass(ClassElement element);
68
69 /// Returns `true` if [element] is a JsInterop method.
70 bool isJsInteropMethod(MethodElement element);
71
72 /// Returns the explicit js interop name for [element].
73 String getJsInteropName(Element element);
74
75 /// Apply JS$ escaping scheme to convert possible escaped Dart names into
76 /// JS names.
77 String getUnescapedJSInteropName(String name);
78 }
79
80 abstract class NativeDataBuilder {
81 /// Sets the native tag info for [cls].
82 ///
83 /// The tag info string contains comma-separated 'words' which are either
84 /// dispatch tags (having JavaScript identifier syntax) and directives that
85 /// begin with `!`.
Siggi Cherem (dart-lang) 2017/03/14 00:15:59 is there a more detailed description of the tags e
Johnni Winther 2017/03/14 15:48:04 Haven't seen any. Stephen might know more.
86 void setNativeClassTagInfo(ClassElement cls, String tagInfo);
87
88 /// Returns the list of native tag words for [cls].
89 List<String> getNativeTagsOfClassRaw(ClassElement cls);
90
91 /// Sets the native [name] for the member [element]. This name is used for
92 /// [element] in the generated JavaScript.
93 void setNativeMemberName(MemberElement element, String name);
94
95 /// Registers the [behavior] for calling the native [method].
96 void setNativeMethodBehavior(MethodElement method, NativeBehavior behavior);
97
98 /// Registers the [behavior] for reading from the native [field].
99 void setNativeFieldLoadBehavior(FieldElement field, NativeBehavior behavior);
100
101 /// Registers the [behavior] for writing to the native [field].
102 void setNativeFieldStoreBehavior(FieldElement field, NativeBehavior behavior);
103
104 /// Returns [element] as an explicit part of JsInterop. The js interop name is
Siggi Cherem (dart-lang) 2017/03/14 00:15:59 Returns => marks?
Johnni Winther 2017/03/14 15:48:04 Done.
105 /// expected to be computed later.
106 void markAsJsInterop(Element element);
107
108 /// Sets the explicit js interop [name] for [element].
109 void setJsInteropName(Element element, String name);
110 }
111
112 class NativeDataImpl implements NativeData, NativeDataBuilder {
16 /// The JavaScript names for elements implemented via typed JavaScript 113 /// The JavaScript names for elements implemented via typed JavaScript
17 /// interop. 114 /// interop.
18 Map<Element, String> jsInteropNames = <Element, String>{}; 115 Map<Element, String> jsInteropNames = <Element, String>{};
19 116
20 /// The JavaScript names for native JavaScript elements implemented. 117 /// The JavaScript names for native JavaScript elements implemented.
21 Map<Element, String> nativeMemberName = <Element, String>{}; 118 Map<Element, String> nativeMemberName = <Element, String>{};
22 119
23 /// Tag info for native JavaScript classes names. See 120 /// Tag info for native JavaScript classes names. See
24 /// [setNativeClassTagInfo]. 121 /// [setNativeClassTagInfo].
25 Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{}; 122 Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{};
26 123
27 /// Cache for [NativeBehavior]s for calling native methods. 124 /// Cache for [NativeBehavior]s for calling native methods.
28 Map<FunctionElement, NativeBehavior> nativeMethodBehavior = 125 Map<MethodElement, NativeBehavior> nativeMethodBehavior =
29 <FunctionElement, NativeBehavior>{}; 126 <MethodElement, NativeBehavior>{};
30 127
31 /// Cache for [NativeBehavior]s for reading from native fields. 128 /// Cache for [NativeBehavior]s for reading from native fields.
32 Map<MemberElement, NativeBehavior> nativeFieldLoadBehavior = 129 Map<MemberElement, NativeBehavior> nativeFieldLoadBehavior =
33 <FieldElement, NativeBehavior>{}; 130 <FieldElement, NativeBehavior>{};
34 131
35 /// Cache for [NativeBehavior]s for writing to native fields. 132 /// Cache for [NativeBehavior]s for writing to native fields.
36 Map<MemberElement, NativeBehavior> nativeFieldStoreBehavior = 133 Map<MemberElement, NativeBehavior> nativeFieldStoreBehavior =
37 <FieldElement, NativeBehavior>{}; 134 <FieldElement, NativeBehavior>{};
38 135
39 /// Prefix used to escape JS names that are not valid Dart names 136 /// Prefix used to escape JS names that are not valid Dart names
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 172
76 if (_isJsInterop(function)) return true; 173 if (_isJsInterop(function)) return true;
77 if (function.isClassMember) return isJsInterop(function.contextClass); 174 if (function.isClassMember) return isJsInterop(function.contextClass);
78 if (function.isTopLevel) return isJsInterop(function.library); 175 if (function.isTopLevel) return isJsInterop(function.library);
79 return false; 176 return false;
80 } else { 177 } else {
81 return _isJsInterop(element); 178 return _isJsInterop(element);
82 } 179 }
83 } 180 }
84 181
182 /// Returns `true` if [element] is a JsInterop class.
183 bool isJsInteropClass(ClassElement element) => isJsInterop(element);
184
185 /// Returns `true` if [element] is a JsInterop method.
186 bool isJsInteropMethod(MethodElement element) => isJsInterop(element);
187
85 /// Returns `true` if the name of [element] is fixed for the generated 188 /// Returns `true` if the name of [element] is fixed for the generated
86 /// JavaScript. 189 /// JavaScript.
87 bool hasFixedBackendName(Element element) { 190 bool hasFixedBackendName(Element element) {
88 return isJsInterop(element) || 191 return isJsInterop(element) ||
89 nativeMemberName.containsKey(element.declaration); 192 nativeMemberName.containsKey(element.declaration);
90 } 193 }
91 194
92 String _jsNameHelper(Element element) { 195 String _jsNameHelper(Element element) {
93 String jsInteropName = jsInteropNames[element.declaration]; 196 String jsInteropName = jsInteropNames[element.declaration];
94 assert(invariant(element, !(_isJsInterop(element) && jsInteropName == null), 197 assert(invariant(element, !(_isJsInterop(element) && jsInteropName == null),
(...skipping 29 matching lines...) Expand all
124 /// JavaScriptInterop mechanism which is allowed for user libraries. 227 /// JavaScriptInterop mechanism which is allowed for user libraries.
125 bool isNative(Element element) { 228 bool isNative(Element element) {
126 if (isJsInterop(element)) return true; 229 if (isJsInterop(element)) return true;
127 if (element.isClass) { 230 if (element.isClass) {
128 return nativeClassTagInfo.containsKey(element.declaration); 231 return nativeClassTagInfo.containsKey(element.declaration);
129 } else { 232 } else {
130 return nativeMemberName.containsKey(element.declaration); 233 return nativeMemberName.containsKey(element.declaration);
131 } 234 }
132 } 235 }
133 236
237 /// Returns `true` if [cls] is a native class.
238 bool isNativeClass(ClassElement element) => isNative(element);
239
240 /// Returns `true` if [element] is a native member of a native class.
241 bool isNativeMember(MemberElement element) => isNative(element);
242
134 /// Returns `true` if [element] or any of its superclasses is native. 243 /// Returns `true` if [element] or any of its superclasses is native.
135 bool isNativeOrExtendsNative(ClassElement element) { 244 bool isNativeOrExtendsNative(ClassElement element) {
136 if (element == null) return false; 245 if (element == null) return false;
137 if (isNative(element) || isJsInterop(element)) { 246 if (isNativeClass(element) || isJsInteropClass(element)) {
138 return true; 247 return true;
139 } 248 }
140 assert(element.isResolved); 249 assert(element.isResolved);
141 return isNativeOrExtendsNative(element.superclass); 250 return isNativeOrExtendsNative(element.superclass);
142 } 251 }
143 252
144 /// Sets the native [name] for the member [element]. This name is used for 253 /// Sets the native [name] for the member [element]. This name is used for
145 /// [element] in the generated JavaScript. 254 /// [element] in the generated JavaScript.
146 void setNativeMemberName(MemberElement element, String name) { 255 void setNativeMemberName(MemberElement element, String name) {
147 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer 256 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 .where((s) => !s.startsWith('!')) 298 .where((s) => !s.startsWith('!'))
190 .toList(); 299 .toList();
191 } 300 }
192 301
193 /// Returns `true` if [cls] has a `!nonleaf` tag word. 302 /// Returns `true` if [cls] has a `!nonleaf` tag word.
194 bool hasNativeTagsForcedNonLeaf(ClassElement cls) { 303 bool hasNativeTagsForcedNonLeaf(ClassElement cls) {
195 return getNativeTagsOfClassRaw(cls).contains('!nonleaf'); 304 return getNativeTagsOfClassRaw(cls).contains('!nonleaf');
196 } 305 }
197 306
198 /// Returns the [NativeBehavior] for calling the native [method]. 307 /// Returns the [NativeBehavior] for calling the native [method].
199 NativeBehavior getNativeMethodBehavior(FunctionElement method) { 308 NativeBehavior getNativeMethodBehavior(MethodElement method) {
200 assert(invariant(method, nativeMethodBehavior.containsKey(method), 309 assert(invariant(method, nativeMethodBehavior.containsKey(method),
201 message: "No native method behavior has been computed for $method.")); 310 message: "No native method behavior has been computed for $method."));
202 return nativeMethodBehavior[method]; 311 return nativeMethodBehavior[method];
203 } 312 }
204 313
205 /// Returns the [NativeBehavior] for reading from the native [field]. 314 /// Returns the [NativeBehavior] for reading from the native [field].
206 NativeBehavior getNativeFieldLoadBehavior(FieldElement field) { 315 NativeBehavior getNativeFieldLoadBehavior(FieldElement field) {
207 assert(invariant(field, nativeFieldLoadBehavior.containsKey(field), 316 assert(invariant(field, nativeFieldLoadBehavior.containsKey(field),
208 message: "No native field load behavior has been " 317 message: "No native field load behavior has been "
209 "computed for $field.")); 318 "computed for $field."));
210 return nativeFieldLoadBehavior[field]; 319 return nativeFieldLoadBehavior[field];
211 } 320 }
212 321
213 /// Returns the [NativeBehavior] for writing to the native [field]. 322 /// Returns the [NativeBehavior] for writing to the native [field].
214 NativeBehavior getNativeFieldStoreBehavior(FieldElement field) { 323 NativeBehavior getNativeFieldStoreBehavior(FieldElement field) {
215 assert(invariant(field, nativeFieldStoreBehavior.containsKey(field), 324 assert(invariant(field, nativeFieldStoreBehavior.containsKey(field),
216 message: "No native field store behavior has been " 325 message: "No native field store behavior has been "
217 "computed for $field.")); 326 "computed for $field."));
218 return nativeFieldStoreBehavior[field]; 327 return nativeFieldStoreBehavior[field];
219 } 328 }
220 329
221 /// Registers the [behavior] for calling the native [method]. 330 /// Registers the [behavior] for calling the native [method].
222 void setNativeMethodBehavior( 331 void setNativeMethodBehavior(MethodElement method, NativeBehavior behavior) {
223 FunctionElement method, NativeBehavior behavior) {
224 nativeMethodBehavior[method] = behavior; 332 nativeMethodBehavior[method] = behavior;
225 } 333 }
226 334
227 /// Registers the [behavior] for reading from the native [field]. 335 /// Registers the [behavior] for reading from the native [field].
228 void setNativeFieldLoadBehavior(FieldElement field, NativeBehavior behavior) { 336 void setNativeFieldLoadBehavior(FieldElement field, NativeBehavior behavior) {
229 nativeFieldLoadBehavior[field] = behavior; 337 nativeFieldLoadBehavior[field] = behavior;
230 } 338 }
231 339
232 /// Registers the [behavior] for writing to the native [field]. 340 /// Registers the [behavior] for writing to the native [field].
233 void setNativeFieldStoreBehavior( 341 void setNativeFieldStoreBehavior(
234 FieldElement field, NativeBehavior behavior) { 342 FieldElement field, NativeBehavior behavior) {
235 nativeFieldStoreBehavior[field] = behavior; 343 nativeFieldStoreBehavior[field] = behavior;
236 } 344 }
237 345
238 /// Apply JS$ escaping scheme to convert possible escaped Dart names into 346 /// Apply JS$ escaping scheme to convert possible escaped Dart names into
239 /// JS names. 347 /// JS names.
240 String getUnescapedJSInteropName(String name) { 348 String getUnescapedJSInteropName(String name) {
241 return name.startsWith(_jsInteropEscapePrefix) 349 return name.startsWith(_jsInteropEscapePrefix)
242 ? name.substring(_jsInteropEscapePrefix.length) 350 ? name.substring(_jsInteropEscapePrefix.length)
243 : name; 351 : name;
244 } 352 }
245 } 353 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698